@neatui/vue 5.1.9 → 5.1.11
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/CHANGELOG.md +8 -0
- package/README.md +2 -0
- package/package.json +3 -2
- package/src/components/form/MoreSelect.vue +1 -1
- package/src/components/form/MoreSelectTree.vue +1 -1
- package/src/components/form/PageMoreSelect.vue +1 -1
- package/src/components/form/PageSelect.vue +1 -1
- package/src/components/form/SearchMoreSelect.vue +1 -1
- package/src/components/form/SearchSelect.vue +1 -1
- package/src/components/form/Select.vue +1 -1
- package/src/components/form/SelectTree/SelectTree.vue +1 -1
- package/src/components/loader/FormLoader/FormLoader.vue +4 -4
- package/src/components/loader/FormLoader/FormRender.vue +7 -5
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# @neatui/vue 更新记录
|
|
2
|
+
|
|
3
|
+
## 5.1.11
|
|
4
|
+
|
|
5
|
+
- FormLoader 新增 `mode="read"`:保留表单控件,统一设置 `disabled`;禁止字段写回、数组增删和排序,隐藏校验提示。插槽的 `bind.disabled` 同步为 `true`,自定义控件需绑定该属性。
|
|
6
|
+
- FormLoader 的 `字段名-value` 插槽仅在 `view` 模式使用;`read` 使用普通控件或字段插槽。
|
|
7
|
+
- Select、树选择、多选、分页选择和搜索选择的搜索区域在移动端撑满宽度。
|
|
8
|
+
- CSS 依赖更新为 `@neatui/css@^5.1.11`。该版本包含不兼容的 Grid 间距语法调整:`ui-grid="3 mm"` 改为 `ui-grid="3" class="gap-mm"`,裸 `lm` 改为左侧垂直居中。响应式间距的前缀规则不同,请阅读 CSS 包随附的 `CHANGELOG.md` 进行迁移。
|
package/README.md
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@neatui/vue",
|
|
3
|
-
"version": "5.1.
|
|
3
|
+
"version": "5.1.11",
|
|
4
4
|
"description": "basic component ui",
|
|
5
5
|
"main": "./src/index.ts",
|
|
6
6
|
"license": "MIT",
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"@fekit/scrollto": "^3.0.3",
|
|
37
37
|
"@fekit/toast": "^2.7.2",
|
|
38
38
|
"@fekit/utils": "^6.0.0",
|
|
39
|
-
"@neatui/css": "^5.1.
|
|
39
|
+
"@neatui/css": "^5.1.11",
|
|
40
40
|
"@rollup/plugin-commonjs": "^26.0.1",
|
|
41
41
|
"@rollup/plugin-node-resolve": "^15.2.3",
|
|
42
42
|
"@vue/compiler-sfc": "^3.4.30",
|
|
@@ -52,6 +52,7 @@
|
|
|
52
52
|
"files": [
|
|
53
53
|
"src",
|
|
54
54
|
"README.md",
|
|
55
|
+
"CHANGELOG.md",
|
|
55
56
|
"MIGRATION-5.0.md"
|
|
56
57
|
]
|
|
57
58
|
}
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
</Input>
|
|
14
14
|
</slot>
|
|
15
15
|
<template #tips>
|
|
16
|
-
<div v-if="search" class="ny-sm nx-sl">
|
|
16
|
+
<div v-if="search" class="ny-sm nx-sl mob:w-full">
|
|
17
17
|
<Input v-model="state.search" :theme="theme" sz="s">
|
|
18
18
|
<template #suffix>
|
|
19
19
|
<i ui-form-search="" class="co-note"></i>
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
<template #suffix><i ui-form-select=""></i></template>
|
|
10
10
|
</Input>
|
|
11
11
|
<template #tips v-if="!disabled && !readonly">
|
|
12
|
-
<div v-if="search" class="nb-sm nx-sl">
|
|
12
|
+
<div v-if="search" class="nb-sm nx-sl mob:w-full">
|
|
13
13
|
<Input v-model="state.search" :theme="theme" sz="s">
|
|
14
14
|
<template #suffix>
|
|
15
15
|
<i ui-form-search="" class="co-note"></i>
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
</Input>
|
|
8
8
|
</slot>
|
|
9
9
|
<template #tips>
|
|
10
|
-
<div v-if="filterable" class="ny-sm nx-sl" style="height: 3em">
|
|
10
|
+
<div v-if="filterable" class="ny-sm nx-sl mob:w-full" style="height: 3em">
|
|
11
11
|
<div :ui-form="`${theme} type:input sz:s :block`">
|
|
12
12
|
<input type="text" :placeholder="props.placeholder" v-model="state.search" />
|
|
13
13
|
<div ui-form-suffix="">
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
<template #suffix><i ui-form-select=""></i></template>
|
|
6
6
|
</Input>
|
|
7
7
|
<template #tips>
|
|
8
|
-
<div v-if="filterable" class="ny-sm nx-sl" style="height: 3em">
|
|
8
|
+
<div v-if="filterable" class="ny-sm nx-sl mob:w-full" style="height: 3em">
|
|
9
9
|
<div :ui-form="`${theme} type:input sz:s :block`">
|
|
10
10
|
<input type="text" :placeholder="props.placeholder" v-model="state.search" />
|
|
11
11
|
<div ui-form-suffix="">
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
<template #suffix><i ui-form-select=""></i></template>
|
|
6
6
|
</Input>
|
|
7
7
|
<template #tips>
|
|
8
|
-
<div class="ny-sm nx-sl" style="height: 3em">
|
|
8
|
+
<div class="ny-sm nx-sl mob:w-full" style="height: 3em">
|
|
9
9
|
<div :ui-form="`${theme} type:input sz:s :block`">
|
|
10
10
|
<input type="text" :placeholder="props.placeholder" v-model="state.search" />
|
|
11
11
|
<div ui-form-suffix="">
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
<template #suffix><i ui-form-select=""></i></template>
|
|
10
10
|
</Input>
|
|
11
11
|
<template #tips v-if="!readonly || !disabled">
|
|
12
|
-
<div v-if="search" class="ny-sm nx-sl">
|
|
12
|
+
<div v-if="search" class="ny-sm nx-sl mob:w-full">
|
|
13
13
|
<Input v-model="state.search" :theme="theme" sz="s">
|
|
14
14
|
<template #suffix>
|
|
15
15
|
<i ui-form-search="" class="co-note"></i>
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
</template>
|
|
13
13
|
</Input>
|
|
14
14
|
<template #tips v-if="!readonly && !disabled">
|
|
15
|
-
<div v-if="search" class="ny-sm nx-sl">
|
|
15
|
+
<div v-if="search" class="ny-sm nx-sl mob:w-full">
|
|
16
16
|
<Input v-model="state.search" :theme="theme" :sz="sz">
|
|
17
17
|
<template #suffix>
|
|
18
18
|
<i ui-form-search="" class="co-note"></i>
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
<template #suffix><i ui-form-select=""></i></template>
|
|
10
10
|
</Input>
|
|
11
11
|
<template #tips v-if="!readonly || !disabled">
|
|
12
|
-
<div v-if="search" class="nb-sm nx-sl">
|
|
12
|
+
<div v-if="search" class="nb-sm nx-sl mob:w-full">
|
|
13
13
|
<Input v-model="state.search" :theme="theme" sz="s">
|
|
14
14
|
<template #suffix>
|
|
15
15
|
<i ui-form-search="" class="co-note"></i>
|
|
@@ -92,8 +92,8 @@
|
|
|
92
92
|
<FieldMessage :col="col" :mode="mode" />
|
|
93
93
|
</div>
|
|
94
94
|
|
|
95
|
-
<FormRender v-else :col="col" :mode="mode" :entry="resolveEntry(col)" :interacted="touched" :ctx="context()" :custom="(
|
|
96
|
-
<slot v-if="
|
|
95
|
+
<FormRender v-else :col="col" :mode="mode" :entry="resolveEntry(col)" :interacted="touched" :ctx="context()" :custom="(mode === 'view' && hasSlot(`${col.field}-value`)) || !resolveEntry(col)">
|
|
96
|
+
<slot v-if="mode === 'view' && hasSlot(`${col.field}-value`)" :name="`${col.field}-value`" v-bind="fieldScope(col)"></slot>
|
|
97
97
|
<template v-else>
|
|
98
98
|
<slot v-if="col.slot" :name="col.slot" v-bind="fieldScope(col)"></slot>
|
|
99
99
|
<slot v-else-if="col.model[0]" :name="col.model[0]" v-bind="fieldScope(col)"></slot>
|
|
@@ -591,7 +591,7 @@
|
|
|
591
591
|
type: Boolean,
|
|
592
592
|
default: false,
|
|
593
593
|
},
|
|
594
|
-
// edit 编辑 | view 查看
|
|
594
|
+
// edit 编辑 | read 禁用控件 | view 查看
|
|
595
595
|
mode: {
|
|
596
596
|
type: String,
|
|
597
597
|
default: 'edit',
|
|
@@ -693,7 +693,7 @@
|
|
|
693
693
|
shared.revision++;
|
|
694
694
|
if (!props.root) shared.dataVersion.value++;
|
|
695
695
|
}, { deep: true, flush: 'sync' });
|
|
696
|
-
const editable = computed(() => props.mode !== 'view');
|
|
696
|
+
const editable = computed(() => props.mode !== 'view' && props.mode !== 'read');
|
|
697
697
|
// 调用过 validate 后所有字段展示校验状态
|
|
698
698
|
const touched = computed(() => props.interacted || shared.state.validated);
|
|
699
699
|
|
|
@@ -252,7 +252,7 @@
|
|
|
252
252
|
};
|
|
253
253
|
// 内置控件和插槽使用相同写回规则,查看模式不接受写入。
|
|
254
254
|
export const writeValue = (col: any, value: any, ctx: FormContext) => {
|
|
255
|
-
if (!col.field || ctx.mode === 'view') return;
|
|
255
|
+
if (!col.field || ctx.mode === 'view' || ctx.mode === 'read') return;
|
|
256
256
|
const binding = col.value;
|
|
257
257
|
col._data[col.field] = valueBinding(binding) && typeof binding.set === 'function' ? binding.set(value, ctx) : value;
|
|
258
258
|
};
|
|
@@ -281,7 +281,7 @@
|
|
|
281
281
|
// native:控件自己用 ui-form-tips 显示错误,这里只留隐藏文本给读屏关联
|
|
282
282
|
props: ['col', 'mode', 'native'],
|
|
283
283
|
// 没有内容时返回空数组:客户端渲染不留占位注释
|
|
284
|
-
setup: (props) => () => props.mode !== 'view' ? [
|
|
284
|
+
setup: (props) => () => props.mode !== 'view' && props.mode !== 'read' ? [
|
|
285
285
|
props.col.model?.[1]?.verify && props.col._checked
|
|
286
286
|
? h('i', { 'ui-form-verify': props.col._error ? 'no' : isEmpty(props.col._data?.[props.col.field]) ? '' : 'ok', 'aria-hidden': 'true' }) : null,
|
|
287
287
|
props.col._error ? h('p', { id: `${props.col._fid}-error`, 'data-field-error': props.col.field,
|
|
@@ -466,6 +466,7 @@
|
|
|
466
466
|
return rest;
|
|
467
467
|
});
|
|
468
468
|
const update = (value: any) => {
|
|
469
|
+
if (props.mode === 'view' || props.mode === 'read') return;
|
|
469
470
|
props.col._touched = true;
|
|
470
471
|
writeValue(props.col, value, props.ctx);
|
|
471
472
|
events.value['update:modelValue']?.(value);
|
|
@@ -483,7 +484,7 @@
|
|
|
483
484
|
const controlProps = computed(() => {
|
|
484
485
|
const { col, entry, mode } = props;
|
|
485
486
|
const options = col.model?.[1] || {};
|
|
486
|
-
const error = mode !== 'view' && nativeTips.value ? col._error : null;
|
|
487
|
+
const error = mode !== 'view' && mode !== 'read' && nativeTips.value ? col._error : null;
|
|
487
488
|
const merged: Record<string, any> = {
|
|
488
489
|
interacted: props.interacted,
|
|
489
490
|
options: entry?.options ? col.enums : undefined,
|
|
@@ -494,7 +495,8 @@
|
|
|
494
495
|
tips: error?.msg || options.tips,
|
|
495
496
|
...(error ? { interacted: true } : {}),
|
|
496
497
|
readonly: mode === 'view' ? true : options.readonly,
|
|
497
|
-
|
|
498
|
+
// read 保留控件,统一使用 disabled 呈现不可编辑状态。
|
|
499
|
+
disabled: mode === 'view' || mode === 'read' ? true : options.disabled,
|
|
498
500
|
};
|
|
499
501
|
// 没有声明 props 的自定义注册控件可能通过 $attrs 读取这些参数,保持透传。
|
|
500
502
|
formOnly.forEach((key) => { if (!declaresOf(entry, key)) delete merged[key]; });
|
|
@@ -516,7 +518,7 @@
|
|
|
516
518
|
const el = root.value;
|
|
517
519
|
// 非 DOM 渲染环境(SSR、自定义渲染器)没有查询接口
|
|
518
520
|
if (!el || typeof el.querySelectorAll !== 'function') return;
|
|
519
|
-
const errorId = props.col._error && props.mode !== 'view' ? `${props.col._fid}-error` : '';
|
|
521
|
+
const errorId = props.col._error && props.mode !== 'view' && props.mode !== 'read' ? `${props.col._fid}-error` : '';
|
|
520
522
|
el.querySelectorAll<HTMLElement>(inputs).forEach((node) => {
|
|
521
523
|
if (errorId) {
|
|
522
524
|
node.setAttribute('aria-invalid', 'true');
|