@para-ui/core 5.0.1 → 5.0.3-beta.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/FieldForm/component.json +22 -1
- package/FormItemGroup/component.json +72 -0
- package/Menu/component.json +9 -2
- package/es/Checkbox/index.js +26 -24
- package/es/CheckboxGroup/index.css +1 -1
- package/es/CheckboxGroup/style/index.css +1 -1
- package/es/ExpressionInput/Popup.js +11 -4
- package/es/ExpressionInput/useExpressionInput.js +40 -37
- package/es/FieldForm/ErrorList.js +9 -8
- package/es/FieldForm/FieldFormItem/ItemHolder.d.ts +2 -0
- package/es/FieldForm/FieldFormItem/ItemHolder.js +78 -68
- package/es/FieldForm/FieldFormItem/index.d.ts +3 -0
- package/es/FieldForm/FieldFormItem/index.js +131 -120
- package/es/FieldForm/Form.d.ts +3 -1
- package/es/FieldForm/Form.js +54 -50
- package/es/FieldForm/compactControlMarker.d.ts +18 -0
- package/es/FieldForm/compactControlMarker.js +5 -0
- package/es/FieldForm/component.json +22 -1
- package/es/FieldForm/context.d.ts +3 -1
- package/es/FieldForm/context.js +6 -5
- package/es/FieldForm/index.css +1 -1
- package/es/FieldForm/index.d.ts +2 -0
- package/es/FieldForm/index.js +13 -9
- package/es/FieldForm/interface.d.ts +9 -0
- package/es/FieldForm/style/index.css +1 -1
- package/es/FieldForm/util.d.ts +14 -0
- package/es/FieldForm/util.js +41 -17
- package/es/FormItemGroup/component.json +72 -0
- package/es/FormItemGroup/index.css +1 -0
- package/es/FormItemGroup/index.d.ts +14 -0
- package/es/FormItemGroup/index.js +27 -0
- package/es/FormItemGroup/style/css.js +1 -0
- package/es/FormItemGroup/style/index.css +1 -0
- package/es/FormItemGroup/style/index.js +1 -0
- package/es/HelperText/index.js +15 -13
- package/es/Menu/component.json +9 -2
- package/es/Menu/index.css +1 -1
- package/es/Menu/interface.d.ts +2 -0
- package/es/Menu/style/index.css +1 -1
- package/es/Menu/verticalMenuList.js +378 -361
- package/es/RadioGroup/index.css +1 -1
- package/es/RadioGroup/style/index.css +1 -1
- package/es/RangeInput/index.js +60 -60
- package/es/Switch/index.js +30 -28
- package/es/Tag/TagGroup.js +29 -32
- package/es/Tag/index.js +5 -5
- package/es/index.d.ts +2 -0
- package/es/index.js +175 -169
- package/lib/Checkbox/index.js +1 -1
- package/lib/CheckboxGroup/index.css +1 -1
- package/lib/CheckboxGroup/style/index.css +1 -1
- package/lib/ExpressionInput/Popup.js +1 -1
- package/lib/ExpressionInput/useExpressionInput.js +1 -1
- package/lib/FieldForm/ErrorList.js +1 -1
- package/lib/FieldForm/FieldFormItem/ItemHolder.d.ts +2 -0
- package/lib/FieldForm/FieldFormItem/ItemHolder.js +1 -1
- package/lib/FieldForm/FieldFormItem/index.d.ts +3 -0
- package/lib/FieldForm/FieldFormItem/index.js +1 -1
- package/lib/FieldForm/Form.d.ts +3 -1
- package/lib/FieldForm/Form.js +1 -1
- package/lib/FieldForm/compactControlMarker.d.ts +18 -0
- package/lib/FieldForm/compactControlMarker.js +2 -0
- package/lib/FieldForm/component.json +22 -1
- package/lib/FieldForm/context.d.ts +3 -1
- package/lib/FieldForm/context.js +1 -1
- package/lib/FieldForm/index.css +1 -1
- package/lib/FieldForm/index.d.ts +2 -0
- package/lib/FieldForm/index.js +1 -1
- package/lib/FieldForm/interface.d.ts +9 -0
- package/lib/FieldForm/style/index.css +1 -1
- package/lib/FieldForm/util.d.ts +14 -0
- package/lib/FieldForm/util.js +1 -1
- package/lib/FormItemGroup/component.json +72 -0
- package/lib/FormItemGroup/index.css +1 -0
- package/lib/FormItemGroup/index.d.ts +14 -0
- package/lib/FormItemGroup/index.js +2 -0
- package/lib/FormItemGroup/style/css.js +1 -0
- package/lib/FormItemGroup/style/index.css +1 -0
- package/lib/FormItemGroup/style/index.js +1 -0
- package/lib/HelperText/index.js +1 -1
- package/lib/Menu/component.json +9 -2
- package/lib/Menu/index.css +1 -1
- package/lib/Menu/interface.d.ts +2 -0
- package/lib/Menu/style/index.css +1 -1
- package/lib/Menu/verticalMenuList.js +1 -1
- package/lib/RadioGroup/index.css +1 -1
- package/lib/RadioGroup/style/index.css +1 -1
- package/lib/RangeInput/index.js +1 -1
- package/lib/Switch/index.js +1 -1
- package/lib/Tag/TagGroup.js +1 -1
- package/lib/Tag/index.js +1 -1
- package/lib/index.d.ts +2 -0
- package/lib/index.js +1 -1
- package/package.json +14 -1
package/es/FieldForm/Form.js
CHANGED
|
@@ -1,92 +1,96 @@
|
|
|
1
1
|
import { j as i } from "../_virtual/jsx-runtime.js";
|
|
2
|
-
import { forwardRef as
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
import { useWatch as
|
|
6
|
-
import { $prefixCls as
|
|
7
|
-
import
|
|
8
|
-
import { FormProvider as
|
|
9
|
-
import { defaultValidateMessages as
|
|
10
|
-
import
|
|
11
|
-
const n = `${
|
|
2
|
+
import { forwardRef as T, useState as q, useContext as w, useMemo as W, useRef as z, useImperativeHandle as V, useEffect as D } from "react";
|
|
3
|
+
import G from "../_virtual/index.js";
|
|
4
|
+
import H from "rc-field-form";
|
|
5
|
+
import { useWatch as me } from "rc-field-form";
|
|
6
|
+
import { $prefixCls as k } from "../GlobalContext/constant.js";
|
|
7
|
+
import B from "./hooks/useForm.js";
|
|
8
|
+
import { FormProvider as J, FormContext as K } from "./context.js";
|
|
9
|
+
import { defaultValidateMessages as O } from "./lang/index.js";
|
|
10
|
+
import Q from "../GlobalContext/index.js";
|
|
11
|
+
const n = `${k}-field-form`, U = (v, E) => {
|
|
12
12
|
const {
|
|
13
|
-
className:
|
|
13
|
+
className: R,
|
|
14
14
|
disabled: m,
|
|
15
|
-
form:
|
|
15
|
+
form: g,
|
|
16
16
|
colon: c,
|
|
17
17
|
labelAlign: f,
|
|
18
18
|
labelWidth: r,
|
|
19
|
-
labelWrap:
|
|
19
|
+
labelWrap: M,
|
|
20
20
|
layout: d = "vertical",
|
|
21
|
-
onFinishFailed:
|
|
21
|
+
onFinishFailed: C,
|
|
22
22
|
name: t,
|
|
23
|
-
style:
|
|
23
|
+
style: L,
|
|
24
24
|
size: u,
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
25
|
+
spacing: p = "normal",
|
|
26
|
+
itemDecorator: x,
|
|
27
|
+
...j
|
|
28
|
+
} = v, [l, y] = q(0), { language: h } = w(Q), I = W(
|
|
29
|
+
() => O[h || "zh"],
|
|
30
|
+
[h]
|
|
31
|
+
), [o] = B(g), { __INTERNAL__: F } = o;
|
|
32
|
+
F.name = t;
|
|
33
|
+
const a = z(null);
|
|
34
|
+
V(E, () => ({
|
|
33
35
|
...o,
|
|
34
36
|
nativeElement: a.current?.nativeElement
|
|
35
37
|
}));
|
|
36
|
-
const
|
|
37
|
-
|
|
38
|
-
},
|
|
38
|
+
const N = (e) => {
|
|
39
|
+
C?.(e);
|
|
40
|
+
}, _ = (e) => {
|
|
39
41
|
if (!e) return;
|
|
40
|
-
const
|
|
42
|
+
const A = e.querySelectorAll(`.${n}-item`);
|
|
41
43
|
let s = 0;
|
|
42
|
-
|
|
43
|
-
const
|
|
44
|
-
if (
|
|
45
|
-
const
|
|
46
|
-
s = Math.max(s,
|
|
44
|
+
A?.forEach((P) => {
|
|
45
|
+
const b = P.querySelector("label");
|
|
46
|
+
if (b) {
|
|
47
|
+
const S = b.offsetWidth;
|
|
48
|
+
s = Math.max(s, S);
|
|
47
49
|
}
|
|
48
|
-
}),
|
|
50
|
+
}), y(s);
|
|
49
51
|
};
|
|
50
|
-
|
|
52
|
+
D(() => {
|
|
51
53
|
const e = setTimeout(() => {
|
|
52
|
-
|
|
54
|
+
_(a.current?.nativeElement);
|
|
53
55
|
}, 0);
|
|
54
56
|
return () => clearTimeout(e);
|
|
55
57
|
}, []);
|
|
56
|
-
const
|
|
58
|
+
const $ = W(
|
|
57
59
|
() => ({
|
|
58
60
|
name: t,
|
|
59
61
|
labelAlign: f,
|
|
60
|
-
labelWrap: r ?
|
|
62
|
+
labelWrap: r ? M : !1,
|
|
61
63
|
labelWidth: r || l,
|
|
62
64
|
labelMaxWidth: l,
|
|
63
65
|
layout: d,
|
|
64
66
|
colon: c,
|
|
65
|
-
itemRef:
|
|
67
|
+
itemRef: F.itemRef,
|
|
66
68
|
form: o,
|
|
67
69
|
prefixCls: n,
|
|
68
70
|
disabled: m,
|
|
69
|
-
size: u
|
|
71
|
+
size: u,
|
|
72
|
+
spacing: p,
|
|
73
|
+
itemDecorator: x
|
|
70
74
|
}),
|
|
71
|
-
[t, f, d, c, o, m, l, r, u]
|
|
75
|
+
[t, f, d, c, o, m, l, r, u, p, x]
|
|
72
76
|
);
|
|
73
|
-
return /* @__PURE__ */ i.jsx(
|
|
74
|
-
|
|
77
|
+
return /* @__PURE__ */ i.jsx(J, { validateMessages: I, children: /* @__PURE__ */ i.jsx(K.Provider, { value: $, children: /* @__PURE__ */ i.jsx(
|
|
78
|
+
H,
|
|
75
79
|
{
|
|
76
80
|
id: t,
|
|
77
|
-
...
|
|
81
|
+
...j,
|
|
78
82
|
name: t,
|
|
79
|
-
onFinishFailed:
|
|
83
|
+
onFinishFailed: N,
|
|
80
84
|
form: o,
|
|
81
85
|
ref: a,
|
|
82
|
-
className:
|
|
83
|
-
style: { ...
|
|
86
|
+
className: G(R, n),
|
|
87
|
+
style: { ...L }
|
|
84
88
|
}
|
|
85
89
|
) }) });
|
|
86
|
-
},
|
|
90
|
+
}, se = T(U);
|
|
87
91
|
export {
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
92
|
+
se as default,
|
|
93
|
+
B as useForm,
|
|
94
|
+
me as useWatch
|
|
91
95
|
};
|
|
92
96
|
//# sourceMappingURL=Form.js.map
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @description Switch/Checkbox 类矮控件的 compact 间距自动识别标记约定。
|
|
3
|
+
*
|
|
4
|
+
* `FieldForm.Item` 在未显式指定 `spacing` 时,会检查唯一直接子节点是否为矮控件,
|
|
5
|
+
* 自动落 compact 档(见 `util.ts` 的 `isCompactControlChild`)。原生 `Switch`/`Checkbox`
|
|
6
|
+
* 靠类型引用直接比对即可命中;但消费方常见做法是自己再包一层组件(如加 label 布局),
|
|
7
|
+
* 包完之后子节点的类型引用就不再等于 `@para-ui/core` 原生组件,直接比对会失效。
|
|
8
|
+
*
|
|
9
|
+
* 为此原生 `Switch`/`Checkbox` 会在自身函数上挂这个标记,消费方若对它们做二次封装,
|
|
10
|
+
* 只需把标记原样透传到自己的包装组件上(`WrapperComponent[PARA_UI_COMPACT_CONTROL_MARKER] = true`),
|
|
11
|
+
* 包装组件即可继续被识别为矮控件——不需要 `@para-ui/core` 反过来认识具体消费方的包装组件。
|
|
12
|
+
*
|
|
13
|
+
* 独立成文件是为了避免循环依赖:这个标记同时被 `Switch`/`Checkbox`(声明"我是矮控件")
|
|
14
|
+
* 和 `FieldForm/util.ts`(读取标记做判断,同时也直接引用 Switch/Checkbox 做引用相等比对)
|
|
15
|
+
* 引用,若把标记定义放进 `FieldForm/util.ts` 会形成 `Switch → FieldForm/util.ts → Switch`
|
|
16
|
+
* 的循环引用。
|
|
17
|
+
*/
|
|
18
|
+
export declare const PARA_UI_COMPACT_CONTROL_MARKER = "__paraUiCompactControl__";
|
|
@@ -61,6 +61,20 @@
|
|
|
61
61
|
"children": {
|
|
62
62
|
"type": "ReactNode",
|
|
63
63
|
"description": "FieldForm 接收任意 ReactNode(包括 FieldForm.Item / Button type=submit / 自定义包装);**但每个 Item 的 child 必须是支持 value/onChange/error/disabled 的自定义组件**(TextField / Select / Checkbox / Switch / DatePicker / InputNumber 等);**不可用原生 input/textarea/select/button — 会触发 React non-boolean-attribute warning**(因 cloneElement 注入 error={false} 给原生 DOM 元素时,React 视 error 为 DOM attr → 报错);见 childrenContract.FormItem"
|
|
64
|
+
},
|
|
65
|
+
"itemDecorator": {
|
|
66
|
+
"type": "ItemDecorator",
|
|
67
|
+
"objectShape": {
|
|
68
|
+
"getItemClassName": {
|
|
69
|
+
"type": "(meta: ItemDecoratorMeta) => string | undefined | false",
|
|
70
|
+
"description": "按字段 namePath/path 返回要合并到该 FieldForm.Item 根节点的 className;返回 undefined/''/false 时不追加,不影响其他状态 class(is-error/is-success 等)"
|
|
71
|
+
},
|
|
72
|
+
"renderItemExtra": {
|
|
73
|
+
"type": "(meta: ItemDecoratorMeta) => ReactNode",
|
|
74
|
+
"description": "按字段 namePath/path 在该 FieldForm.Item 根节点内追加渲染内容(如 diff 命中原因说明);渲染在根节点内、内部间距容器之外,不影响 has-spacing/has-helper-text 的 20px 间距机制"
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
"description": "Form 级一次注册、所有子孙 FieldForm.Item 自动生效的字段装饰扩展点;meta.namePath 来自 rc-field-form 的 renderMeta.name(真实的、经过 List 等上下文处理后的最终路径),meta.path 是预拼接字符串(数组下标用方括号,如 'ubr.list[0].x');未传 name 的 Item 固定拿到 { namePath: [], path: '' };典型用法:`<FieldForm itemDecorator={{ getItemClassName: (meta) => isHit(meta.path) ? 'is-hit' : undefined, renderItemExtra: (meta) => isHit(meta.path) ? <span>命中原因</span> : null }}>`"
|
|
64
78
|
}
|
|
65
79
|
},
|
|
66
80
|
"childrenContract": {
|
|
@@ -137,7 +151,9 @@
|
|
|
137
151
|
"把'仅使用 FieldForm 本身'解读为'整个文件不能 import TextField/Button'(见 interpretivePriority.resolution)",
|
|
138
152
|
"字段过多不分组",
|
|
139
153
|
"忽略异步校验",
|
|
140
|
-
"在 mount 后修改 initialValues prop(应用 form.setFieldsValue;initialValues 仅 mount 时灌入)"
|
|
154
|
+
"在 mount 后修改 initialValues prop(应用 form.setFieldsValue;initialValues 仅 mount 时灌入)",
|
|
155
|
+
"在 itemDecorator.getItemClassName/renderItemExtra 回调体内调用 useContext/useXxx 等 Hook(回调运行在 ItemHolder 渲染过程中,不在业务组件自身的渲染调用栈里,会违反 Hooks 规则;应在业务组件顶层用 Hook 取数后,用 useMemo 包成闭包再传入 itemDecorator)",
|
|
156
|
+
"期望 itemDecorator 对 noStyle 的 FieldForm.Item 生效(noStyle 不渲染独立 wrapper 节点,没有可挂载 className/额外内容的位置)"
|
|
141
157
|
],
|
|
142
158
|
"events": {
|
|
143
159
|
"onFinish": {
|
|
@@ -187,6 +203,11 @@
|
|
|
187
203
|
"issue": "rules 中的 validator 函数签名必须返回 Promise(rc-field-form 约定),不是同步返回",
|
|
188
204
|
"wrong": "rules={[{ validator: (_, val) => val > 0 ? true : false }]} // 同步返回 boolean 不被识别",
|
|
189
205
|
"right": "rules={[{ validator: (_, val) => val > 0 ? Promise.resolve() : Promise.reject('必须大于 0') }]}"
|
|
206
|
+
},
|
|
207
|
+
{
|
|
208
|
+
"issue": "itemDecorator 的 getItemClassName/renderItemExtra 回调不能在函数体内调用 React Hook",
|
|
209
|
+
"wrong": "itemDecorator={{ getItemClassName: (meta) => { const hit = useFieldHighlight(meta.path); return hit ? 'is-hit' : undefined; } }} // 在回调体内调用 Hook,违反 Hooks 规则",
|
|
210
|
+
"right": "const highlightMap = useFieldHighlightMap();\nconst itemDecorator = useMemo(() => ({ getItemClassName: (meta) => (highlightMap[meta.path] ? 'is-hit' : undefined) }), [highlightMap]);\n<FieldForm itemDecorator={itemDecorator}>"
|
|
190
211
|
}
|
|
191
212
|
],
|
|
192
213
|
"mapping": {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { default as React, FC, ReactElement, Key, ReactNode } from 'react';
|
|
2
2
|
import { FormProviderProps as RcFormProviderProps } from 'rc-field-form/lib/FormContext';
|
|
3
3
|
import { Meta } from 'rc-field-form/lib/interface';
|
|
4
|
-
import { FormLabelAlign } from './interface';
|
|
4
|
+
import { FormLabelAlign, ItemDecorator } from './interface';
|
|
5
5
|
import { FormInstance, FormLayout } from './Form';
|
|
6
6
|
import { ValidateStatus } from './FieldFormItem';
|
|
7
7
|
export declare const FormProvider: FC<RcFormProviderProps>;
|
|
@@ -18,6 +18,8 @@ export interface FormContextProps {
|
|
|
18
18
|
prefixCls?: string;
|
|
19
19
|
disabled?: boolean;
|
|
20
20
|
size?: 'small' | 'medium' | 'large';
|
|
21
|
+
spacing: 'normal' | 'compact';
|
|
22
|
+
itemDecorator?: ItemDecorator;
|
|
21
23
|
}
|
|
22
24
|
export declare const FormContext: React.Context<FormContextProps>;
|
|
23
25
|
/** rc-field-form 在销毁字段时会传入带 destroy 标记的 meta(官方 Meta 类型未声明此字段) */
|
package/es/FieldForm/context.js
CHANGED
|
@@ -5,16 +5,17 @@ import i from "rc-util/lib/omit";
|
|
|
5
5
|
const x = (t) => {
|
|
6
6
|
const r = i(t, ["prefixCls"]);
|
|
7
7
|
return /* @__PURE__ */ e.jsx(m, { ...r });
|
|
8
|
-
},
|
|
8
|
+
}, a = o({
|
|
9
9
|
labelAlign: "left",
|
|
10
10
|
layout: "vertical",
|
|
11
|
+
spacing: "normal",
|
|
11
12
|
itemRef: () => () => {
|
|
12
13
|
}
|
|
13
|
-
}),
|
|
14
|
+
}), c = o(null), f = o({});
|
|
14
15
|
export {
|
|
15
|
-
|
|
16
|
-
|
|
16
|
+
a as FormContext,
|
|
17
|
+
f as FormItemInputContext,
|
|
17
18
|
x as FormProvider,
|
|
18
|
-
|
|
19
|
+
c as NoStyleItemContext
|
|
19
20
|
};
|
|
20
21
|
//# sourceMappingURL=context.js.map
|
package/es/FieldForm/index.css
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
@charset "UTF-8";.paraui-v4-field-form-item{vertical-align:top}.paraui-v4-field-form-item.is-horizontal{display:flex}.paraui-v4-field-form-item.is-horizontal .paraui-v4-field-form-label{
|
|
1
|
+
@charset "UTF-8";.paraui-v4-field-form-item{vertical-align:top}.paraui-v4-field-form-item.is-horizontal{display:flex}.paraui-v4-field-form-item.is-horizontal .paraui-v4-field-form-label{flex-shrink:0;padding:0;margin-right:8px;text-align:end}.paraui-v4-field-form-item.is-horizontal .paraui-v4-field-form-label.is-left{text-align:start}.paraui-v4-field-form-item.is-horizontal .paraui-v4-field-form-label.is-multiline .paraui-v4-field-form-label-comp{display:inline-block}.paraui-v4-field-form-item.is-horizontal .paraui-v4-field-form-label-comp{display:inline-flex;align-items:center;width:100%;max-width:100%;min-height:32px;margin:0}.paraui-v4-field-form-item.is-spacing-compact .paraui-v4-field-form-content.has-spacing{margin-bottom:16px}.paraui-v4-field-form-item.is-spacing-compact .paraui-v4-field-form-content.has-spacing.has-helper-text{margin-bottom:0}.paraui-v4-field-form-item.is-spacing-compact .paraui-v4-field-form-control-input{min-height:24px}.paraui-v4-field-form-item.is-spacing-compact .paraui-v4-helper-text{min-height:16px;line-height:16px}.paraui-v4-field-form-content{flex:1}.paraui-v4-field-form-content.has-spacing{margin-bottom:20px}.paraui-v4-field-form-content.has-spacing.has-helper-text{margin-bottom:0}.paraui-v4-field-form-control-input{display:flex;align-items:center;min-height:32px}.paraui-v4-field-form-control-input-content{width:100%}.paraui-v4-field-form-control-input-content .paraui-v4-radio-group>.radio-group-content .radio-item-box{margin-bottom:0}.paraui-v4-field-form-control-input-content .text-field-error-text:not(.paraui-v4-helper-text-force-visible),.paraui-v4-field-form-control-input-content .select-error-text:not(.paraui-v4-helper-text-force-visible){display:none}.paraui-v4-field-form-helper-text{line-height:20px;word-break:break-all}.paraui-v4-field-form-helper-text .is-warning>.paraui-v4-helper-text.paraui-v4-helper-text-error{color:#ff9326}
|
package/es/FieldForm/index.d.ts
CHANGED
|
@@ -19,3 +19,5 @@ declare const FieldForm: CompoundedComponent;
|
|
|
19
19
|
export type { ErrorListProps, FieldFormInstance, FieldFormItemProps, FieldFormListFieldData, FieldFormListOperation, FieldFormListProps, FieldFormProps, Rule, RuleObject, RuleRender };
|
|
20
20
|
export default FieldForm;
|
|
21
21
|
export type * from './interface';
|
|
22
|
+
export { joinNamePath } from './util';
|
|
23
|
+
export { PARA_UI_COMPACT_CONTROL_MARKER } from './compactControlMarker';
|
package/es/FieldForm/index.js
CHANGED
|
@@ -1,21 +1,25 @@
|
|
|
1
1
|
import { FormProvider as o } from "./context.js";
|
|
2
2
|
import m from "./Form.js";
|
|
3
3
|
import t from "./ErrorList.js";
|
|
4
|
-
import
|
|
5
|
-
import
|
|
4
|
+
import e from "./FieldFormItem/index.js";
|
|
5
|
+
import i from "./FormList.js";
|
|
6
6
|
import s from "./hooks/useFormInstance.js";
|
|
7
7
|
import './index.css';/* empty css */
|
|
8
|
-
import
|
|
9
|
-
import {
|
|
8
|
+
import { joinNamePath as R } from "./util.js";
|
|
9
|
+
import { PARA_UI_COMPACT_CONTROL_MARKER as h } from "./compactControlMarker.js";
|
|
10
|
+
import p from "./hooks/useForm.js";
|
|
11
|
+
import { useWatch as F } from "rc-field-form";
|
|
10
12
|
const r = m;
|
|
11
|
-
r.Item =
|
|
12
|
-
r.List =
|
|
13
|
+
r.Item = e;
|
|
14
|
+
r.List = i;
|
|
13
15
|
r.ErrorList = t;
|
|
14
|
-
r.useForm =
|
|
16
|
+
r.useForm = p;
|
|
15
17
|
r.useFormInstance = s;
|
|
16
|
-
r.useWatch =
|
|
18
|
+
r.useWatch = F;
|
|
17
19
|
r.Provider = o;
|
|
18
20
|
export {
|
|
19
|
-
|
|
21
|
+
h as PARA_UI_COMPACT_CONTROL_MARKER,
|
|
22
|
+
r as default,
|
|
23
|
+
R as joinNamePath
|
|
20
24
|
};
|
|
21
25
|
//# sourceMappingURL=index.js.map
|
|
@@ -1,2 +1,11 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
1
2
|
export type { InternalNamePath, NamePath, Store, StoreValue } from 'rc-field-form/lib/interface';
|
|
2
3
|
export type FormLabelAlign = 'left' | 'right';
|
|
4
|
+
export interface ItemDecoratorMeta {
|
|
5
|
+
namePath: (string | number)[];
|
|
6
|
+
path: string;
|
|
7
|
+
}
|
|
8
|
+
export interface ItemDecorator {
|
|
9
|
+
getItemClassName?: (meta: ItemDecoratorMeta) => string | undefined | false;
|
|
10
|
+
renderItemExtra?: (meta: ItemDecoratorMeta) => ReactNode;
|
|
11
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
.paraui-v4-field-form-item{vertical-align:top}.paraui-v4-field-form-item.is-horizontal{display:flex}.paraui-v4-field-form-item.is-horizontal .paraui-v4-field-form-label{
|
|
1
|
+
.paraui-v4-field-form-item{vertical-align:top}.paraui-v4-field-form-item.is-horizontal{display:flex}.paraui-v4-field-form-item.is-horizontal .paraui-v4-field-form-label{flex-shrink:0;padding:0;margin-right:8px;text-align:end}.paraui-v4-field-form-item.is-horizontal .paraui-v4-field-form-label.is-left{text-align:start}.paraui-v4-field-form-item.is-horizontal .paraui-v4-field-form-label.is-multiline .paraui-v4-field-form-label-comp{display:inline-block}.paraui-v4-field-form-item.is-horizontal .paraui-v4-field-form-label-comp{display:inline-flex;align-items:center;width:100%;max-width:100%;min-height:32px;margin:0}.paraui-v4-field-form-item.is-spacing-compact .paraui-v4-field-form-content.has-spacing{margin-bottom:16px}.paraui-v4-field-form-item.is-spacing-compact .paraui-v4-field-form-content.has-spacing.has-helper-text{margin-bottom:0}.paraui-v4-field-form-item.is-spacing-compact .paraui-v4-field-form-control-input{min-height:24px}.paraui-v4-field-form-item.is-spacing-compact .paraui-v4-helper-text{min-height:16px;line-height:16px}.paraui-v4-field-form-content{flex:1}.paraui-v4-field-form-content.has-spacing{margin-bottom:20px}.paraui-v4-field-form-content.has-spacing.has-helper-text{margin-bottom:0}.paraui-v4-field-form-control-input{display:flex;align-items:center;min-height:32px}.paraui-v4-field-form-control-input-content{width:100%}.paraui-v4-field-form-control-input-content .paraui-v4-radio-group>.radio-group-content .radio-item-box{margin-bottom:0}.paraui-v4-field-form-control-input-content .text-field-error-text:not(.paraui-v4-helper-text-force-visible),.paraui-v4-field-form-control-input-content .select-error-text:not(.paraui-v4-helper-text-force-visible){display:none}.paraui-v4-field-form-helper-text{line-height:20px;word-break:break-all}.paraui-v4-field-form-helper-text .is-warning>.paraui-v4-helper-text.paraui-v4-helper-text-error{color:#ff9326}
|
package/es/FieldForm/util.d.ts
CHANGED
|
@@ -13,9 +13,23 @@ export declare function toArray<T>(candidate?: T | T[] | false): T[];
|
|
|
13
13
|
* @returns string
|
|
14
14
|
*/
|
|
15
15
|
export declare function getFieldId(namePath: InternalNamePath, formName?: string): string | undefined;
|
|
16
|
+
/**
|
|
17
|
+
* 拼接 namePath 为 path 字符串,数组下标用方括号
|
|
18
|
+
* @example joinNamePath(['ubr', 'list', 0, 'x']) => 'ubr.list[0].x'
|
|
19
|
+
*/
|
|
20
|
+
export declare function joinNamePath(namePath: (string | number)[]): string;
|
|
16
21
|
/**
|
|
17
22
|
* 通过 meta 或传递的 validateStatus 获取合并后的状态
|
|
18
23
|
*/
|
|
19
24
|
export declare function getStatus<DefaultValue>(errors: ReactNode[], warnings: ReactNode[], meta: Meta, defaultValidateStatus: ValidateStatus | DefaultValue, hasFeedback?: boolean, validateStatus?: ValidateStatus): ValidateStatus | DefaultValue;
|
|
20
25
|
export declare function isReactComponent(element: React.ReactElement): boolean;
|
|
21
26
|
export declare function isDOMElement(element: React.ReactElement): boolean;
|
|
27
|
+
/**
|
|
28
|
+
* 判断表单项的直接子节点是否为 Switch/Checkbox 这类矮控件(含 React.memo 包裹场景,
|
|
29
|
+
* 以及消费方对 Switch/Checkbox 做二次封装、但透传了 PARA_UI_COMPACT_CONTROL_MARKER
|
|
30
|
+
* 标记的包装组件),用于在调用方未显式传 spacing 时自动选中 compact 档,替代此前
|
|
31
|
+
* 完全依赖手写 opt-in 的方式。仅识别单一直接子节点;children 为多个节点、或非合法
|
|
32
|
+
* element(如纯文本)时一律判定为不匹配,交由默认 normal 档处理,避免对组合型字段
|
|
33
|
+
* 做出错误猜测。
|
|
34
|
+
*/
|
|
35
|
+
export declare function isCompactControlChild(children: ReactNode): boolean;
|
package/es/FieldForm/util.js
CHANGED
|
@@ -1,25 +1,49 @@
|
|
|
1
|
-
import { isValidElement as
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
import u, { isValidElement as f } from "react";
|
|
2
|
+
import { Switch as s } from "../Switch/index.js";
|
|
3
|
+
import { Checkbox as c } from "../Checkbox/index.js";
|
|
4
|
+
import { PARA_UI_COMPACT_CONTROL_MARKER as m } from "./compactControlMarker.js";
|
|
5
|
+
const a = ["parentNode"], y = "field-form_item";
|
|
6
|
+
function $(t) {
|
|
7
|
+
return t === void 0 || t === !1 ? [] : Array.isArray(t) ? t : [t];
|
|
5
8
|
}
|
|
6
|
-
function
|
|
7
|
-
if (!
|
|
9
|
+
function T(t, r) {
|
|
10
|
+
if (!t.length)
|
|
8
11
|
return;
|
|
9
|
-
const
|
|
10
|
-
return r ? `${r}_${
|
|
12
|
+
const e = t.join("_");
|
|
13
|
+
return r ? `${r}_${e}` : a.includes(e) ? `${y}_${e}` : e;
|
|
11
14
|
}
|
|
12
|
-
function
|
|
13
|
-
|
|
14
|
-
|
|
15
|
+
function E(t) {
|
|
16
|
+
return t.reduce(
|
|
17
|
+
(r, e) => typeof e == "number" ? `${r}[${e}]` : r ? `${r}.${e}` : String(e),
|
|
18
|
+
""
|
|
19
|
+
);
|
|
15
20
|
}
|
|
16
|
-
function
|
|
17
|
-
|
|
21
|
+
function M(t, r, e, i, l, n) {
|
|
22
|
+
let o = i;
|
|
23
|
+
return n !== void 0 ? o = n : e.validating ? o = "validating" : t.length ? o = "error" : r.length ? o = "warning" : (e.touched || l && e.validated) && (o = "success"), o;
|
|
24
|
+
}
|
|
25
|
+
function I(t) {
|
|
26
|
+
return f(t) && (typeof t.type == "function" || typeof t.type == "object");
|
|
27
|
+
}
|
|
28
|
+
const d = /* @__PURE__ */ Symbol.for("react.memo");
|
|
29
|
+
function p(t) {
|
|
30
|
+
return t !== null && typeof t == "object" && t.$$typeof === d ? t.type : t;
|
|
31
|
+
}
|
|
32
|
+
const C = [s, c];
|
|
33
|
+
function R(t) {
|
|
34
|
+
const r = u.Children.toArray(t);
|
|
35
|
+
if (r.length !== 1) return !1;
|
|
36
|
+
const e = r[0];
|
|
37
|
+
if (!f(e)) return !1;
|
|
38
|
+
const i = p(e.type);
|
|
39
|
+
return C.includes(i) ? !0 : typeof i == "function" && i[m] === !0;
|
|
18
40
|
}
|
|
19
41
|
export {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
42
|
+
T as getFieldId,
|
|
43
|
+
M as getStatus,
|
|
44
|
+
R as isCompactControlChild,
|
|
45
|
+
I as isReactComponent,
|
|
46
|
+
E as joinNamePath,
|
|
47
|
+
$ as toArray
|
|
24
48
|
};
|
|
25
49
|
//# sourceMappingURL=util.js.map
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "FormItemGroup",
|
|
3
|
+
"category": "Layout",
|
|
4
|
+
"description": "表单项堆叠容器:官方推荐的字段间纵向/横向间距方案。字段自带的 20px 间距基线(helper-text 占位)原本要外层手动挂 `.paraui-v4-form` 类名才会生效,容易被忘记导致字段在 flex 布局下零间距;FormItemGroup 把这条基线内置在自己身上,不用再记类名。同时内部 gap 只认自身 CSS 变量(!important),裸写 style.gap 不会生效,用来替代业务/AI 随手在字段外层加 gap 导致的间距叠加问题(基线已经占了 20px,外层再加 gap 会翻倍)。一个组件同时兜住「漏挂基线类→零间距」和「叠加 gap→翻倍」两个方向。",
|
|
5
|
+
"semantic": {
|
|
6
|
+
"intent": ["表单字段堆叠", "受控间距容器", "间距基线兜底"],
|
|
7
|
+
"useCases": [
|
|
8
|
+
"多个 TextField/Select/Switch 等字段手写堆叠(最常见场景,不依赖 Form/FieldForm)",
|
|
9
|
+
"多个 FormItem/FieldFormItem 纵向堆叠(direction='vertical',默认)",
|
|
10
|
+
"少量字段并排展示(direction='horizontal')",
|
|
11
|
+
"需要在字段之间加统一间距的场景(gap 属性)"
|
|
12
|
+
],
|
|
13
|
+
"riskLevel": "low"
|
|
14
|
+
},
|
|
15
|
+
"variants": {
|
|
16
|
+
"vertical": {
|
|
17
|
+
"meaning": "默认值。`display:flex; flex-direction:column`,字段自上而下堆叠。"
|
|
18
|
+
},
|
|
19
|
+
"horizontal": {
|
|
20
|
+
"meaning": "`display:flex; flex-direction:row`,字段并排展示。"
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
"states": ["default"],
|
|
24
|
+
"idealProps": {
|
|
25
|
+
"direction": {
|
|
26
|
+
"type": "enum",
|
|
27
|
+
"values": ["vertical", "horizontal"],
|
|
28
|
+
"default": "vertical",
|
|
29
|
+
"description": "排列方向。表单场景基本用默认的 'vertical'。"
|
|
30
|
+
},
|
|
31
|
+
"gap": {
|
|
32
|
+
"type": "number",
|
|
33
|
+
"default": 0,
|
|
34
|
+
"description": "字段间距(px),默认 0——不额外加间距,完全依赖字段自身已有的间距(如 helper-text 占位)。真正需要更大间距时才传这个值,例如 gap={32}。"
|
|
35
|
+
},
|
|
36
|
+
"children": {
|
|
37
|
+
"type": "ReactNode",
|
|
38
|
+
"description": "子元素,通常是若干个 FormItem / FieldFormItem。"
|
|
39
|
+
},
|
|
40
|
+
"className": {
|
|
41
|
+
"type": "string",
|
|
42
|
+
"description": "外层根 div 的类名。"
|
|
43
|
+
},
|
|
44
|
+
"style": {
|
|
45
|
+
"type": "React.CSSProperties",
|
|
46
|
+
"description": "外层根 div 的内联样式。注意其中的 gap 不会生效(会被组件内部 !important 规则覆盖),间距请用 gap 属性。"
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
"do": [
|
|
50
|
+
"字段纵向堆叠用 <FormItemGroup> 替代手写 <div style={{ display:'flex', flexDirection:'column', gap: 16 }}>",
|
|
51
|
+
"用 <FormItemGroup> 包住字段就自动拿到 20px 间距基线,不需要再额外记着给外层容器挂 `.paraui-v4-form` 类名",
|
|
52
|
+
"确实需要比字段自带间距更大的间距时,用 gap 属性:<FormItemGroup gap={32}>",
|
|
53
|
+
"字段并排展示用 direction='horizontal'"
|
|
54
|
+
],
|
|
55
|
+
"dont": [
|
|
56
|
+
"不要在 style 里直接写 gap,例如 <FormItemGroup style={{ gap: 16 }}>——会被内部规则忽略,且不会有任何视觉效果,请改用 gap 属性",
|
|
57
|
+
"不要在没有堆叠需求的单个字段外面套一层 FormItemGroup,纯粹是多余包裹",
|
|
58
|
+
"确实需要密集布局下零间距(如表格内联编辑),仍可以用更具体的选择器覆盖 min-height(这条基线规则没有 !important),不需要绕开 FormItemGroup"
|
|
59
|
+
],
|
|
60
|
+
"events": {},
|
|
61
|
+
"typescriptPitfalls": [
|
|
62
|
+
{
|
|
63
|
+
"issue": "style.gap 不会生效,是设计上的行为而不是 bug",
|
|
64
|
+
"wrong": "<FormItemGroup style={{ gap: 16 }}>...</FormItemGroup> // 不生效,且不会报 TS 错误,容易被误以为生效了",
|
|
65
|
+
"right": "<FormItemGroup gap={16}>...</FormItemGroup> // 通过 gap 属性设置,实际生效"
|
|
66
|
+
}
|
|
67
|
+
],
|
|
68
|
+
"mapping": {
|
|
69
|
+
"realComponent": "FormItemGroup",
|
|
70
|
+
"adapter": null
|
|
71
|
+
}
|
|
72
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@charset "UTF-8";.paraui-v4-form-item-group{display:flex;gap:var(--paraui-v4-form-item-group-gap, 0)!important}.paraui-v4-form-item-group.paraui-v4-form-item-group-vertical{flex-direction:column}.paraui-v4-form-item-group.paraui-v4-form-item-group-horizontal{flex-direction:row}.paraui-v4-form-item-group .paraui-v4-helper-text{min-height:20px}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { default as React, FunctionComponent, ReactNode } from 'react';
|
|
2
|
+
export interface FormItemGroupProps {
|
|
3
|
+
/** 样式class */
|
|
4
|
+
className?: string;
|
|
5
|
+
/** style(其中的 gap 不会生效,请用 gap 属性设置间距) */
|
|
6
|
+
style?: React.CSSProperties;
|
|
7
|
+
/** 排列方向,默认 'vertical'(纵向堆叠,最常见的表单场景) */
|
|
8
|
+
direction?: 'vertical' | 'horizontal';
|
|
9
|
+
/** 字段间距(px),默认 0——即完全依赖字段自身已有的间距,不额外加间距 */
|
|
10
|
+
gap?: number;
|
|
11
|
+
children?: ReactNode;
|
|
12
|
+
}
|
|
13
|
+
declare const FormItemGroup: FunctionComponent<FormItemGroupProps>;
|
|
14
|
+
export default FormItemGroup;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { j as n } from "../_virtual/jsx-runtime.js";
|
|
2
|
+
import c from "clsx";
|
|
3
|
+
import { $prefixCls as o } from "../GlobalContext/constant.js";
|
|
4
|
+
import './index.css';/* empty css */
|
|
5
|
+
const x = (t) => {
|
|
6
|
+
const { className: p, style: r, children: e, direction: m = "vertical", gap: s = 0, ...i } = t;
|
|
7
|
+
process.env.NODE_ENV !== "production" && r && "gap" in r && console.warn(
|
|
8
|
+
"[FormItemGroup] style.gap 不会生效,组件内部的 gap 规则带 !important,只认 gap 属性。请使用 <FormItemGroup gap={number}> 设置间距。"
|
|
9
|
+
);
|
|
10
|
+
const a = {
|
|
11
|
+
...r,
|
|
12
|
+
[`--${o}-form-item-group-gap`]: `${s}px`
|
|
13
|
+
};
|
|
14
|
+
return /* @__PURE__ */ n.jsx(
|
|
15
|
+
"div",
|
|
16
|
+
{
|
|
17
|
+
className: c(`${o}-form-item-group ${o}-form-item-group-${m}`, p),
|
|
18
|
+
style: a,
|
|
19
|
+
...i,
|
|
20
|
+
children: e
|
|
21
|
+
}
|
|
22
|
+
);
|
|
23
|
+
};
|
|
24
|
+
export {
|
|
25
|
+
x as default
|
|
26
|
+
};
|
|
27
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import './index.css';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.paraui-v4-form-item-group{display:flex;gap:var(--paraui-v4-form-item-group-gap, 0) !important}.paraui-v4-form-item-group.paraui-v4-form-item-group-vertical{flex-direction:column}.paraui-v4-form-item-group.paraui-v4-form-item-group-horizontal{flex-direction:row}.paraui-v4-form-item-group .paraui-v4-helper-text{min-height:20px}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import './index.css';
|
package/es/HelperText/index.js
CHANGED
|
@@ -1,23 +1,25 @@
|
|
|
1
|
-
import { j as
|
|
2
|
-
import {
|
|
1
|
+
import { j as u } from "../_virtual/jsx-runtime.js";
|
|
2
|
+
import { useContext as a } from "react";
|
|
3
|
+
import { $prefixCls as t } from "../GlobalContext/constant.js";
|
|
4
|
+
import { FormItemInputContext as x } from "../FieldForm/context.js";
|
|
3
5
|
import './index.css';/* empty css */
|
|
4
|
-
const
|
|
5
|
-
const { className:
|
|
6
|
-
if (
|
|
7
|
-
const
|
|
8
|
-
let
|
|
9
|
-
return
|
|
6
|
+
const $ = (r) => {
|
|
7
|
+
const { className: o, style: i, error: l = !1, helperText: m } = r, { isFormItemInput: n } = a(x), s = r.hideErrorDom !== void 0 ? r.hideErrorDom : n ? null : !1;
|
|
8
|
+
if (s === null || !l && s) return null;
|
|
9
|
+
const f = () => {
|
|
10
|
+
let e = `${t}-helper-text`;
|
|
11
|
+
return o && (e += ` ${o}`), l && (e += ` ${t}-helper-text-error`), r.hideErrorDom === !1 && (e += ` ${t}-helper-text-force-visible`), e;
|
|
10
12
|
};
|
|
11
|
-
return /* @__PURE__ */
|
|
13
|
+
return /* @__PURE__ */ u.jsx(
|
|
12
14
|
"p",
|
|
13
15
|
{
|
|
14
|
-
className:
|
|
15
|
-
style:
|
|
16
|
-
children:
|
|
16
|
+
className: f(),
|
|
17
|
+
style: i,
|
|
18
|
+
children: m
|
|
17
19
|
}
|
|
18
20
|
);
|
|
19
21
|
};
|
|
20
22
|
export {
|
|
21
|
-
|
|
23
|
+
$ as default
|
|
22
24
|
};
|
|
23
25
|
//# sourceMappingURL=index.js.map
|
package/es/Menu/component.json
CHANGED
|
@@ -116,12 +116,14 @@
|
|
|
116
116
|
"配置 shrinkOthers 以提升用户查找效率",
|
|
117
117
|
"使用 icon 辅助识别菜单项",
|
|
118
118
|
"**菜单数据通过 menuListProps.list 传入**(不是顶层 list prop):`<Menu menuListProps={{ list: menuData }} />`,menuData 是 MenuChildrenProps[] 数组",
|
|
119
|
-
"MenuChildrenProps 核心字段(src/Menu/interface.ts:25-63):`label: ReactNode`(菜单名),`path: string`(路径,与 selectMenu 比对高亮),`icon: ReactNode`(图标),`children: MenuChildrenProps[]`(子菜单),`type: 'redirect'|'router'|'iframe'|'snack'|'snackPage'`(菜单类型),`href: string`(a 标签地址),`badge: ReactNode`(标记)"
|
|
119
|
+
"MenuChildrenProps 核心字段(src/Menu/interface.ts:25-63):`label: ReactNode`(菜单名),`path: string`(路径,与 selectMenu 比对高亮),`icon: ReactNode`(图标),`children: MenuChildrenProps[]`(子菜单),`type: 'redirect'|'router'|'iframe'|'snack'|'snackPage'`(菜单类型),`href: string`(a 标签地址),`badge: ReactNode`(标记)",
|
|
120
|
+
"`group: boolean`(仅一级生效,需同时有 children):把该项渲染成不可点击的纯文本分组小标题,children 常驻展开且按顶层菜单项样式渲染(不缩进,可配 icon)。示例:`{ label: '路由管理', group: true, children: [{ label: '路由规则', path: '/router/rule' }, { label: '静态资源', path: '/router/static' }] }`"
|
|
120
121
|
],
|
|
121
122
|
"dont": [
|
|
122
123
|
"在菜单项中放置非导航类的复杂交互组件",
|
|
123
124
|
"过度使用动态生成的菜单导致性能问题",
|
|
124
|
-
"把菜单数据传给顶层 list prop——Menu 没有顶层 list prop,数据必须通过 menuListProps.list 传入"
|
|
125
|
+
"把菜单数据传给顶层 list prop——Menu 没有顶层 list prop,数据必须通过 menuListProps.list 传入",
|
|
126
|
+
"不要在非一级菜单项或没有 children 的项上设置 group: true——不满足条件会被忽略,自动退化为原有渲染(普通叶子节点 / 普通折叠子菜单),不会报错但也不会生效"
|
|
125
127
|
],
|
|
126
128
|
"events": {
|
|
127
129
|
"onClickMenu": {
|
|
@@ -171,6 +173,11 @@
|
|
|
171
173
|
"issue": "color prop 只有 'deep' 和 'light' 两个有效值(ColorType),传其他字符串 TS 报错",
|
|
172
174
|
"wrong": "color='dark' // TS2322: Type '\"dark\"' is not assignable to type 'ColorType'",
|
|
173
175
|
"right": "color='deep' // 合法值: 'deep'(深色主题) | 'light'(浅色主题)"
|
|
176
|
+
},
|
|
177
|
+
{
|
|
178
|
+
"issue": "group 生效需同时满足两个前提:该项是一级菜单(level 1)且自身有 children;在二级菜单项或没有 children 的项上设置 group: true 会被静默忽略,自动退化为原渲染,容易被误以为是 bug",
|
|
179
|
+
"wrong": "// 二级菜单项上设置 group,不会生效\n{ label: '一级', children: [{ label: '二级', group: true, children: [...] }] }",
|
|
180
|
+
"right": "// group 只能设在一级菜单项上\n{ label: '路由管理', group: true, children: [{ label: '路由规则', path: '/router/rule' }] }"
|
|
174
181
|
}
|
|
175
182
|
],
|
|
176
183
|
"mapping": {
|