@neatui/vue 5.1.0 → 5.1.2

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/MIGRATION-5.0.md CHANGED
@@ -60,6 +60,10 @@ Vue 最低版本声明统一为 3.5.11,与已有 Pinia 3 的要求一致;同
60
60
 
61
61
  ## 新增与行为修复
62
62
 
63
+ - 渲染结构精简:节点即元素,attrs 原样落在节点元素上。无标题的 Text / Html / Button 节点只输出内容元素本身;分组、数组内部的层级不再包根元素,子节点直接落在节点元素(无标题分组)或内容容器(有标题分组)里;纯文本不再包 span,不输出空的 style / ui-col。模板不输出说明注释,空内容、没有提示、没有 submit 时不留占位注释(客户端渲染)。依赖旧包裹层(`.flex-block > [ui-row]`、内容节点外层 div、`span`)的样式或测试需要调整。
64
+ - id 只给字段:`表单前缀-数据路径`(`.` 换成 `-`),如 `apply-contact-phone`、`apply-members-0-name`;前缀为 `idx`,未传时由 useId 生成 6 位短串。分组、容器、内容节点不再输出 id,需要时在 attrs 里写。旧的 `form-<idx>-g0-field-x` / `group-0` 形式不再生成,错误提示 id 为 `<字段 id>-error`。
65
+ - `child` 可写成 `{ attrs, lists }`:attrs(可为函数)描述承载子节点的容器;容器用 ui-flex 布局时不加栅格和默认间距 `n-sl-sub`,写了 class 时替换默认间距;无标题分组的节点元素就是容器,节点写了 class 时同样不加默认间距(与根元素规则一致)。
66
+ - `media: false`:这一层不用栅格,自身不带 ui-col,分组 / 数组的下一层也不带 ui-row;ui-col 只在所在层有栅格时输出;`rows=""` 时根元素不再输出空的 ui-row。
63
67
  - 标题与内容均可递归组合;数组支持默认值、数量限制、增删排序和行上下文。
64
68
  - 新增 `setErrors`(回填服务端错误)、`isDirty / getChanges`(未保存改动)、`setBaseline`(设置重置基线)、`getData({ visibleOnly })`(去掉隐藏字段),`validate({ paths })` 支持局部校验。在同一对象上用 `Object.assign` 加载记录后调用 `setBaseline()`。
65
69
  - `validate()` 等待异步联动并检查最新数据;`reset()` 恢复当前数据对象的初始状态;`clearValidate()` 取消未完成校验。
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neatui/vue",
3
- "version": "5.1.0",
3
+ "version": "5.1.2",
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.0",
39
+ "@neatui/css": "^5.1.2",
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",
@@ -10,7 +10,7 @@
10
10
  ref="tip"
11
11
  :class="`${tipClass}${mobile ? ' fekit-follow-mobile' : ''}`"
12
12
  :style="`position: fixed; pointer-events: none; ${tipStyle}`"
13
- ui-tips="@a"
13
+ :ui-tips="theme"
14
14
  :ui-tips-view="state.show ? 1 : 0"
15
15
  @mouseover="hovershow"
16
16
  @mouseout="hoverhide"
@@ -43,6 +43,7 @@
43
43
 
44
44
  // 类型
45
45
  interface Props {
46
+ theme?: string;
46
47
  modelValue?: string | number;
47
48
  pos?: string;
48
49
  event?: string;
@@ -62,6 +63,7 @@
62
63
 
63
64
  // 入参
64
65
  const props: any = withDefaults(defineProps<Props>(), {
66
+ theme: '@a',
65
67
  modelValue: 0,
66
68
  pos: 'bl',
67
69
  event: 'click',
@@ -372,7 +374,7 @@
372
374
  touch-action: none !important;
373
375
  }
374
376
 
375
- &[ui-tips~='@a'] [ui-tips-box] {
377
+ &[ui-tips] [ui-tips-box] {
376
378
  position: relative !important;
377
379
 
378
380
  width: 100% !important;
@@ -316,7 +316,7 @@
316
316
  .side-preview {
317
317
  min-width: 10rem;
318
318
  height: 100%;
319
- box-shadow: -0.25em 0 0.5em rgba(0, 0, 0, 0.05);
319
+ box-shadow: -0.25em 0 0.5em var(--co-deep-o-mm);
320
320
  pointer-events: auto;
321
321
 
322
322
  &[ui-card~='@a'][ui-card~=':max'] {
@@ -1,6 +1,6 @@
1
1
  <template>
2
2
  <div :ui-form="`${theme} type:select sz:${sz}`" :ui-form-open="state.show ? 'show' : ''" class="mc-cascader">
3
- <IFollowView
3
+ <IFollowView :theme="popupTheme"
4
4
  ref="ifollow"
5
5
  :tipBoxStyle="`${state.flatOpts.length && state.flatOpts[0]?.length > 0 ? 'min-width: 10em;' : 'min-width: 100%'}`"
6
6
  pos="bl"
@@ -41,7 +41,7 @@
41
41
  class="ux-hover nx-sm r-ss nowrap"
42
42
  @click="select(item, optIndex)"
43
43
  >
44
- <IFollowView v-if="item.optTips" event="hover">
44
+ <IFollowView :theme="popupTheme" v-if="item.optTips" event="hover">
45
45
  <div ui-flex="row xm">
46
46
  <span :class="`${state.transSelected.value[optIndex] === item.value ? 'co-main' : ''}`"> {{ item.label || item }}</span>
47
47
  <i v-if="item.children?.length" :class="`icon icon-next ${state.transSelected.value[optIndex] === item.value ? 'co-main' : 'co-note'}`"></i>
@@ -95,6 +95,7 @@
95
95
 
96
96
  const props = defineProps({
97
97
  theme: { type: String, default: '@a' },
98
+ popupTheme: { type: String, default: '@a' },
98
99
  sz: { type: String, default: 'm' },
99
100
  co: { type: String, default: '' },
100
101
  block: { type: Boolean, default: true },
@@ -1,6 +1,6 @@
1
1
  <template>
2
2
  <div :ui-form="`${theme} type:select sz:${sz}`" ui-tips="@a co:well" :ui-tips-view="state.show">
3
- <IFollowView ref="ifollow">
3
+ <IFollowView :theme="popupTheme" ref="ifollow">
4
4
  <Input
5
5
  v-bind="{ placeholder, rules, theme, sz, co, block, ready, type, tips, maxlength, minlength, disabled, readonly, clearable, verify, prefix, suffix, interacted }"
6
6
  :clearable="false"
@@ -46,6 +46,7 @@
46
46
  placeholder?: string;
47
47
  rules?: Array<object>;
48
48
  theme?: string;
49
+ popupTheme?: string;
49
50
  sz?: '' | 'xs' | 's' | 'm' | 'l' | 'xl';
50
51
  co?: string;
51
52
  block?: boolean;
@@ -76,6 +77,7 @@
76
77
  placeholder: '',
77
78
  rules: () => [],
78
79
  theme: '@a',
80
+ popupTheme: '@a',
79
81
  sz: '',
80
82
  co: '',
81
83
  block: true,
@@ -1,6 +1,6 @@
1
1
  <template>
2
2
  <div :ui-form="`${theme} type:select sz:${sz}`" ui-tips="@a co:well" :ui-tips-view="state.show">
3
- <IFollowView ref="ifollow">
3
+ <IFollowView :theme="popupTheme" ref="ifollow">
4
4
  <InputRange
5
5
  v-bind="{ placeholder, rules, theme, sz, co, block, ready, type, tips, maxlength, minlength, disabled, readonly, clearable, verify, prefix, suffix, interacted }"
6
6
  :clearable="false"
@@ -39,6 +39,7 @@
39
39
  placeholder?: string;
40
40
  rules?: Array<object>;
41
41
  theme?: string;
42
+ popupTheme?: string;
42
43
  sz?: '' | 'xs' | 's' | 'm' | 'l' | 'xl';
43
44
  co?: string;
44
45
  block?: boolean;
@@ -69,6 +70,7 @@
69
70
  placeholder: '',
70
71
  rules: () => [],
71
72
  theme: '@a',
73
+ popupTheme: '@a',
72
74
  sz: '',
73
75
  co: '',
74
76
  block: true,
@@ -1,6 +1,6 @@
1
1
  <template>
2
2
  <div
3
- :ui-form="`${theme} sz:${sz} ${state.error.co} type:input ${block ? ' :block' : ''} ${disabled ? 'disabled' : ''} ${readonly ? 'readonly' : ''} ${preview ? 'preview' : ''}`"
3
+ :ui-form="[theme, sz && `sz:${sz}`, state.error.co, 'type:input', block && ':block', disabled && 'disabled', readonly && 'readonly', preview && 'preview'].filter(Boolean).join(' ')"
4
4
  @click="emits('click', $event)"
5
5
  >
6
6
  <div v-if="state.interacted" :ui-form-tips="state.error.ontips">{{ state.error.tips }}</div>
@@ -1,6 +1,6 @@
1
1
  <template>
2
2
  <div
3
- :ui-form="`${theme} sz:${sz} ${state.error.co} type:input ${block ? ' :block' : ''} ${disabled ? 'disabled' : ''} ${readonly ? 'readonly' : ''}`"
3
+ :ui-form="[theme, sz && `sz:${sz}`, state.error.co, 'type:input', block && ':block', disabled && 'disabled', readonly && 'readonly'].filter(Boolean).join(' ')"
4
4
  @click="emits('click', $event)"
5
5
  >
6
6
  <div :ui-form-tips="state.error.ontips">{{ state.error.tips }}</div>
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <div :ui-form="`${theme} sz:${sz} ${state.co} type:input ${block ? ' :block' : ''} ${disabled ? 'disabled' : ''} ${readonly ? 'readonly' : ''}`" @click="emits('click', $event)">
2
+ <div :ui-form="[theme, sz && `sz:${sz}`, state.co, 'type:input', block && ':block', disabled && 'disabled', readonly && 'readonly'].filter(Boolean).join(' ')" @click="emits('click', $event)">
3
3
  <div v-if="ready" :ui-form-tips="state.ontips">{{ state.tips }}</div>
4
4
  <div ui-form-prefix="">
5
5
  <template v-for="(item, idx) in prefix" :key="idx">
@@ -1,6 +1,6 @@
1
1
  <template>
2
2
  <div :ui-form="`${theme} type:select ${sz ? 'sz:' + sz : ''}`">
3
- <IFollowView ref="ifollow" tipBoxClass="ny-sm nx-no" tipBoxStyle="min-width: 100%">
3
+ <IFollowView :theme="popupTheme" ref="ifollow" tipBoxClass="ny-sm nx-no" tipBoxStyle="min-width: 100%">
4
4
  <slot>
5
5
  <Input
6
6
  v-bind="{ placeholder, rules, theme, sz, co, block, ready: true, type: 'text', tips, disabled, readonly, clearable: false, verify, prefix, suffix, interacted }"
@@ -107,6 +107,7 @@
107
107
  placeholder?: string;
108
108
  rules?: Array<object>;
109
109
  theme?: string;
110
+ popupTheme?: string;
110
111
  sz?: '' | 'xs' | 's' | 'm' | 'l' | 'xl';
111
112
  co?: string;
112
113
  block?: boolean;
@@ -135,6 +136,7 @@
135
136
  placeholder: '',
136
137
  rules: () => [],
137
138
  theme: '@a',
139
+ popupTheme: '@a',
138
140
  sz: '',
139
141
  co: '',
140
142
  block: true,
@@ -1,6 +1,6 @@
1
1
  <template>
2
2
  <div :ui-form="`${theme} type:select sz:${sz}`" :ui-form-open="state.show ? 'show' : 'hide'">
3
- <IFollowView ref="ifollow" v-model="state.show" tipBoxClass="ny-sm nx-no" tipBoxStyle="min-width: 100%" @onshow="onshow" @onhide="onhide">
3
+ <IFollowView :theme="popupTheme" ref="ifollow" v-model="state.show" tipBoxClass="ny-sm nx-no" tipBoxStyle="min-width: 100%" @onshow="onshow" @onhide="onhide">
4
4
  <Input
5
5
  v-bind="{ placeholder, rules, theme, sz, co, block, ready, type: 'text', tips, disabled, readonly: true, clearable: false, verify, prefix, suffix, interacted }"
6
6
  :modelValue="state.label"
@@ -102,6 +102,7 @@
102
102
  placeholder?: string;
103
103
  rules?: Array<object>;
104
104
  theme?: string;
105
+ popupTheme?: string;
105
106
  sz?: '' | 'xs' | 's' | 'm' | 'l' | 'xl';
106
107
  co?: string;
107
108
  block?: boolean;
@@ -131,6 +132,7 @@
131
132
  placeholder: '',
132
133
  rules: () => [],
133
134
  theme: '@a',
135
+ popupTheme: '@a',
134
136
  sz: '',
135
137
  co: '',
136
138
  block: true,
@@ -1,6 +1,6 @@
1
1
  <template>
2
2
  <div :ui-form="`${theme} type:select ${sz ? 'sz:' + sz : ''}`" :ui-form-open="state.show ? 'show' : ''" ref="dom">
3
- <IFollowView ref="ifollow" tipBoxClass="ny-sm nx-no" tipBoxStyle="min-width: 100%">
3
+ <IFollowView :theme="popupTheme" ref="ifollow" tipBoxClass="ny-sm nx-no" tipBoxStyle="min-width: 100%">
4
4
  <slot>
5
5
  <Input v-bind="$props" :clearable="false" readonly v-model="state.selectd">
6
6
  <template #suffix><i ui-form-select=""></i></template>
@@ -60,6 +60,7 @@
60
60
 
61
61
  const props: any = defineProps({
62
62
  theme: { type: String, default: '@a' },
63
+ popupTheme: { type: String, default: '@a' },
63
64
  sz: { type: String, default: '' },
64
65
  co: { type: String, default: '' },
65
66
  block: { type: Boolean, default: true },
@@ -1,6 +1,6 @@
1
1
  <template>
2
2
  <div :ui-form="`${theme} type:select sz:${sz}`" :ui-form-open="state.show ? 'show' : ''" ref="dom">
3
- <IFollowView ref="ifollow" tipBoxClass="ny-sm nx-no" tipBoxStyle="min-width: 100%">
3
+ <IFollowView :theme="popupTheme" ref="ifollow" tipBoxClass="ny-sm nx-no" tipBoxStyle="min-width: 100%">
4
4
  <Input v-bind="$props" :clearable="false" readonly v-model="state.selectd.label" :interacted="interacted">
5
5
  <template #suffix><i ui-form-select=""></i></template>
6
6
  </Input>
@@ -55,6 +55,7 @@
55
55
  default: false,
56
56
  },
57
57
  theme: { type: String, default: '@a' },
58
+ popupTheme: { type: String, default: '@a' },
58
59
  sz: { type: String as PropType<'' | 'xs' | 's' | 'm' | 'l' | 'xl'>, default: 'm' },
59
60
  co: { type: String, default: '' },
60
61
  block: { type: Boolean, default: true },
@@ -1,6 +1,6 @@
1
1
  <template>
2
2
  <div :ui-form="`${theme} type:select sz:${sz}`" :ui-form-open="state.show ? 'show' : ''">
3
- <IFollowView ref="ifollow" tipBoxClass="ny-sm nx-no" tipBoxStyle="min-width: 100%" @onshow="onshow" @onhide="onhide">
3
+ <IFollowView :theme="popupTheme" ref="ifollow" tipBoxClass="ny-sm nx-no" tipBoxStyle="min-width: 100%" @onshow="onshow" @onhide="onhide">
4
4
  <Input v-bind="$props" :clearable="false" readonly v-model="state.selectd" @click="toggle" :interacted="interacted">
5
5
  <template #suffix><i ui-form-select=""></i></template>
6
6
  </Input>
@@ -59,6 +59,7 @@
59
59
  default: false,
60
60
  },
61
61
  theme: { type: String, default: '@a' },
62
+ popupTheme: { type: String, default: '@a' },
62
63
  sz: { type: String as PropType<'' | 'xs' | 's' | 'm' | 'l' | 'xl'>, default: 'm' },
63
64
  co: { type: String, default: '' },
64
65
  block: { type: Boolean, default: true },
@@ -1,6 +1,6 @@
1
1
  <template>
2
2
  <div :ui-form="`${theme} type:select sz:${sz}`" :ui-form-open="state.show ? 'show' : ''">
3
- <IFollowView ref="ifollow" tipBoxClass="ny-sm nx-no" tipBoxStyle="min-width: 100%" @onshow="onshow" @onhide="onhide">
3
+ <IFollowView :theme="popupTheme" ref="ifollow" tipBoxClass="ny-sm nx-no" tipBoxStyle="min-width: 100%" @onshow="onshow" @onhide="onhide">
4
4
  <Input
5
5
  v-bind="{ placeholder, rules, theme, sz, co, block, ready, type, tips, disabled, readonly: true, clearable: false, verify, prefix, suffix, interacted }"
6
6
  v-model="state.selectd.label"
@@ -100,6 +100,7 @@
100
100
  placeholder?: string;
101
101
  rules?: Array<object>;
102
102
  theme?: string;
103
+ popupTheme?: string;
103
104
  sz?: '' | 'xs' | 's' | 'm' | 'l' | 'xl';
104
105
  co?: string;
105
106
  block?: boolean;
@@ -131,6 +132,7 @@
131
132
  placeholder: '',
132
133
  rules: () => [],
133
134
  theme: '@a',
135
+ popupTheme: '@a',
134
136
  sz: '',
135
137
  co: '',
136
138
  block: true,
@@ -1,6 +1,6 @@
1
1
  <template>
2
2
  <div :ui-form="`${theme} type:select sz:${sz}`" :ui-form-open="state.show ? 'show' : ''">
3
- <IFollowView ref="ifollow" tipBoxClass="ny-sm nx-no" tipBoxStyle="min-width: 100%" @onshow="onshow" @onhide="onhide">
3
+ <IFollowView :theme="popupTheme" ref="ifollow" tipBoxClass="ny-sm nx-no" tipBoxStyle="min-width: 100%" @onshow="onshow" @onhide="onhide">
4
4
  <Input
5
5
  v-bind="{ placeholder, rules, theme, sz, co, block, ready, type, tips, disabled, readonly: true, clearable: false, verify, prefix, suffix, interacted }"
6
6
  v-model="state.displayLabel"
@@ -127,6 +127,7 @@
127
127
  placeholder?: string;
128
128
  rules?: Array<object>;
129
129
  theme?: string;
130
+ popupTheme?: string;
130
131
  sz?: '' | 'xs' | 's' | 'm' | 'l' | 'xl';
131
132
  co?: string;
132
133
  block?: boolean;
@@ -161,6 +162,7 @@
161
162
  placeholder: '',
162
163
  rules: () => [],
163
164
  theme: '@a',
165
+ popupTheme: '@a',
164
166
  sz: 'm',
165
167
  co: '',
166
168
  block: true,
@@ -1,6 +1,6 @@
1
1
  <template>
2
2
  <div :ui-form="`${theme} type:select sz:${sz}`" :ui-form-open="state.show ? 'show' : 'hide'">
3
- <IFollowView ref="ifollow" v-model="state.show" tipBoxClass="ny-sm nx-no" tipBoxStyle="min-width: 100%" @onshow="onshow" @onhide="onhide">
3
+ <IFollowView :theme="popupTheme" ref="ifollow" v-model="state.show" tipBoxClass="ny-sm nx-no" tipBoxStyle="min-width: 100%" @onshow="onshow" @onhide="onhide">
4
4
  <Input
5
5
  v-bind="{ placeholder, rules, theme, sz, co, block, ready, type, tips, disabled, readonly: true, clearable: false, verify, prefix, suffix, interacted }"
6
6
  v-model="state.label"
@@ -96,6 +96,7 @@
96
96
  placeholder?: string;
97
97
  rules?: Array<object>;
98
98
  theme?: string;
99
+ popupTheme?: string;
99
100
  sz?: '' | 'xs' | 's' | 'm' | 'l' | 'xl';
100
101
  co?: string;
101
102
  block?: boolean;
@@ -130,6 +131,7 @@
130
131
  placeholder: '',
131
132
  rules: () => [],
132
133
  theme: '@a',
134
+ popupTheme: '@a',
133
135
  sz: '',
134
136
  co: '',
135
137
  block: true,
@@ -1,6 +1,6 @@
1
1
  <template>
2
2
  <div
3
- :ui-form="`${theme} sz:${sz} ${state.error.co} type:textarea ${isAutoHeight ? 'auto-height' : ''} ${block ? ' :block' : ''} ${disabled ? 'disabled' : ''} ${readonly ? 'readonly' : ''}`"
3
+ :ui-form="[theme, sz && `sz:${sz}`, state.error.co, 'type:textarea', isAutoHeight && 'auto-height', block && ':block', disabled && 'disabled', readonly && 'readonly'].filter(Boolean).join(' ')"
4
4
  @click="emits('click', $event)"
5
5
  >
6
6
  <div :ui-form-tips="state.error.ontips">{{ state.error.tips }}</div>
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <div :ui-form="`${theme} type:input ${disabled ? 'disabled' : ''}`">
2
+ <div :ui-form="[theme, 'type:input', disabled && 'disabled'].filter(Boolean).join(' ')">
3
3
  <input type="time" :value="modelValue || ''" :min="min" :max="max" :step="step" :disabled="disabled" :readonly="readonly"
4
4
  :aria-invalid="error ? true : undefined" :aria-label="label" :required="required" @input="update" @change="change" @blur="emit('blur', $event)" @focus="emit('focus', $event)" />
5
5
  <span v-if="verify && error" role="alert" class="co-risk">{{ error }}</span>