@neatui/vue 2.17.2 → 2.17.3

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.
@@ -3,7 +3,7 @@
3
3
  :ui-form="`${theme} sz:${sz} ${state.error.co} type:input ${block ? ' :block' : ''} ${disabled ? 'disabled' : ''} ${readonly ? 'readonly' : ''}`"
4
4
  @click="emits('click', $event)"
5
5
  >
6
- <div :ui-form-tips="state.error.ontips">{{ state.error.tips }}</div>
6
+ <div v-if="state.interacted" :ui-form-tips="state.error.ontips">{{ state.error.tips }}</div>
7
7
  <div ui-form-prefix="">
8
8
  <template v-for="(item, idx) in prefix" :key="idx">
9
9
  <div v-if="isObject(item)" v-bind="item.attrs" v-on="event(item, props.modelValue)">
@@ -17,7 +17,7 @@
17
17
  <input
18
18
  :title="props.modelValue"
19
19
  :value="props.modelValue"
20
- :type="type"
20
+ :type="inputType"
21
21
  :placeholder="placeholder"
22
22
  :disabled="disabled"
23
23
  :readonly="readonly"
@@ -30,6 +30,12 @@
30
30
  </slot>
31
31
  <div ui-form-suffix="">
32
32
  <i ui-form-clean="" v-if="clearable && props.modelValue && !readonly && !disabled" @click.stop="clear"></i>
33
+ <div
34
+ class="o-ls"
35
+ v-if="type === 'password' && cipher"
36
+ :ui-form-cipher="cipherVisible ? '1' : ''"
37
+ @click.stop="toggleCipher"
38
+ ></div>
33
39
  <slot name="suffix"></slot>
34
40
  <template v-for="(item, idx) in suffix" :key="idx">
35
41
  <div v-if="isObject(item)" v-bind="item.attrs" v-on="event(item, props.modelValue)">
@@ -43,7 +49,7 @@
43
49
  </template>
44
50
 
45
51
  <script setup lang="ts">
46
- import { reactive, watch } from 'vue';
52
+ import { computed, reactive, ref, watch } from 'vue';
47
53
  import { isObject, isFunction } from '@fekit/utils';
48
54
 
49
55
  const emits = defineEmits(['update:modelValue', 'click', 'blur', 'focus', 'change', 'input', 'clear']);
@@ -66,7 +72,7 @@
66
72
  * readonly 是否只读
67
73
  * clearable 是否显示清除按钮
68
74
  * rules 校验规则
69
- * verify 是否是示校验图标 2=tips 3=text 4=icon 5=tips+text 6=text+icon 7=text+icon
75
+ * verify 是否显示校验
70
76
  * prefix 前缀内容
71
77
  * suffix 后缀内容
72
78
  * interacted 用户是否交互
@@ -89,10 +95,11 @@
89
95
  disabled?: boolean;
90
96
  readonly?: boolean;
91
97
  clearable?: boolean;
98
+ cipher?: boolean;
92
99
  verify?: boolean;
93
100
  prefix?: Array<any>;
94
101
  suffix?: Array<any>;
95
- interacted?: boolean;
102
+ interacted?: boolean | number | null;
96
103
  }
97
104
  const props: any = withDefaults(defineProps<Props>(), {
98
105
  modelValue: '',
@@ -110,52 +117,45 @@
110
117
  disabled: false,
111
118
  readonly: false,
112
119
  clearable: true,
120
+ cipher: true,
113
121
  verify: false,
114
122
  prefix: () => [],
115
123
  suffix: () => [],
116
- interacted: false,
124
+ interacted: null,
117
125
  });
118
126
 
119
127
  const state: any = reactive({
120
128
  // 用户是否交互
121
- interacted: false,
129
+ interacted: null,
122
130
  // 值
123
131
  value: props.modelValue,
124
132
  // 错误
125
133
  error: {},
126
134
  });
127
- // 外部传入交互标识,主要用于外部没有输入但点击了提交
135
+ const cipherVisible = ref(false);
136
+
137
+ const inputType = computed(() => {
138
+ if (props.type === 'password') {
139
+ return cipherVisible.value ? 'text' : 'password';
140
+ }
141
+ return props.type;
142
+ });
143
+ // 外部传入交互标识,主要用于外部没有输入但点击了提交,或表单提交成功后重置状态
128
144
  watch(
129
145
  () => props.interacted,
130
146
  (interacted: any) => {
131
- if (interacted) {
132
- state.interacted = interacted;
133
- }
147
+ state.interacted = interacted;
134
148
  },
135
- { deep: true, immediate: true },
149
+ { immediate: true },
136
150
  );
137
151
 
138
- // 监听外部数据
139
- // watch(
140
- // () => props.modelValue,
141
- // (value: any) => {
142
- // state.value = value;
143
- // },
144
- // { deep: true, immediate: true }
145
- // );
146
- // watch(
147
- // () => state.value,
148
- // (value: any) => {
149
- // emits('update:modelValue', value);
150
- // },
151
- // { deep: true, immediate: true }
152
- // );
153
-
154
152
  // 校验
155
153
  watch(
156
154
  [() => state.interacted, () => props.modelValue],
157
155
  async () => {
158
156
  if (state.interacted) {
157
+ const hasValue =
158
+ props.modelValue !== '' && props.modelValue !== null && props.modelValue !== undefined;
159
159
  // 提示文案
160
160
  let tips = '';
161
161
  // 错误类型
@@ -163,7 +163,7 @@
163
163
  // 验证结果
164
164
  let verify = '';
165
165
 
166
- if (props.modelValue) {
166
+ if (hasValue) {
167
167
  // 有值
168
168
  let hasError = false;
169
169
  // 遍历校验规则
@@ -215,6 +215,11 @@
215
215
  emits('update:modelValue', null);
216
216
  emits('clear');
217
217
  }
218
+
219
+ const toggleCipher = () => {
220
+ if (props.disabled || props.readonly) return;
221
+ cipherVisible.value = !cipherVisible.value;
222
+ };
218
223
  // 输入
219
224
  const input = (e: any) => {
220
225
  // 用户交互
@@ -230,11 +235,6 @@
230
235
  e.target.value = props.modelValue;
231
236
  return false;
232
237
  }
233
- // 数字类型 - 移除有问题的逻辑,允许用户正常删除数字
234
- // if (props.type === 'number' && !value && props.modelValue?.length !== 1) {
235
- // e.target.value = props.modelValue;
236
- // return false;
237
- // }
238
238
  // 输入事件
239
239
  emits('input', e, state);
240
240
  emits('update:modelValue', value || null);
@@ -35,47 +35,70 @@
35
35
  </template>
36
36
 
37
37
  <script setup lang="ts">
38
- import { reactive, watch, PropType } from 'vue';
38
+ import { reactive, watch } from 'vue';
39
39
  import { isObject } from '@fekit/utils';
40
40
 
41
41
  const emits = defineEmits(['update:modelValue', 'click', 'blur', 'focus', 'change', 'input', 'clear']);
42
- const props = defineProps({
42
+
43
+ interface Props {
43
44
  // 主题
44
- theme: { type: String, default: '@a' },
45
+ theme?: string;
45
46
  // 尺寸
46
- sz: { type: String, default: '' },
47
+ sz?: string;
47
48
  // 颜色
48
- co: { type: String, default: '' },
49
+ co?: string;
49
50
  // 撑满
50
- block: { type: Boolean, default: true },
51
+ block?: boolean;
51
52
  // 准备就绪
52
- ready: { type: Boolean, default: false },
53
+ ready?: boolean;
53
54
  // 值
54
- modelValue: { type: [String, Number], default: '' },
55
+ modelValue?: string | number;
55
56
  // 类型
56
- type: { type: String, default: 'text' },
57
+ type?: string;
57
58
  // 提示文案
58
- tips: { type: String, default: '' },
59
+ tips?: string;
59
60
  // 内容占位
60
- placeholder: { type: String, default: '' },
61
+ placeholder?: string;
61
62
  // 最大长度
62
- maxlength: { type: Number, default: null },
63
+ maxlength?: number | null;
63
64
  // 最小长度
64
- minlength: { type: Number, default: null },
65
+ minlength?: number | null;
65
66
  // 是否禁用
66
- disabled: { type: Boolean, default: false },
67
+ disabled?: boolean;
67
68
  // 是否只读
68
- readonly: { type: Boolean, default: false },
69
+ readonly?: boolean;
69
70
  // 是否显示清除按钮
70
- clearable: { type: Boolean, default: true },
71
+ clearable?: boolean;
71
72
  // 校验规则
72
- rules: { type: Array as PropType<any[]>, default: () => [] },
73
+ rules?: any[];
73
74
  // 是否是示校验图标
74
- verify: { type: Boolean, default: false },
75
- prefix: { type: Array as PropType<any[]>, default: () => [] },
76
- suffix: { type: Array as PropType<any[]>, default: () => [] },
75
+ verify?: boolean;
76
+ prefix?: any[];
77
+ suffix?: any[];
77
78
  // 用户是否交互
78
- interacted: { type: Boolean, default: false }
79
+ interacted?: boolean;
80
+ }
81
+
82
+ const props = withDefaults(defineProps<Props>(), {
83
+ theme: '@a',
84
+ sz: '',
85
+ co: '',
86
+ block: true,
87
+ ready: false,
88
+ modelValue: '',
89
+ type: 'text',
90
+ tips: '',
91
+ placeholder: '',
92
+ maxlength: null,
93
+ minlength: null,
94
+ disabled: false,
95
+ readonly: false,
96
+ clearable: true,
97
+ rules: () => [],
98
+ verify: false,
99
+ prefix: () => [],
100
+ suffix: () => [],
101
+ interacted: false
79
102
  });
80
103
 
81
104
  const state: any = reactive({
@@ -86,13 +109,11 @@
86
109
  // 错误
87
110
  error: {}
88
111
  });
89
- // 外部传入交互标识,主要用于外部没有输入但点击了提交
112
+ // 外部传入交互标识,主要用于外部没有输入但点击了提交,或表单提交成功后重置状态
90
113
  watch(
91
114
  () => props.interacted,
92
115
  (interacted: any) => {
93
- if (interacted) {
94
- state.interacted = interacted;
95
- }
116
+ state.interacted = interacted;
96
117
  },
97
118
  { deep: true, immediate: true }
98
119
  );
@@ -148,9 +148,7 @@
148
148
  watch(
149
149
  () => props.interacted,
150
150
  (interacted: any) => {
151
- if (interacted) {
152
- state.interacted = interacted;
153
- }
151
+ state.interacted = interacted;
154
152
  },
155
153
  { deep: true, immediate: true },
156
154
  );
@@ -1,9 +1,11 @@
1
1
  import Input from './Input@v3.vue';
2
2
  import InputRange from './InputRange.vue';
3
3
  import Switch from './Switch.vue';
4
- import Textarea from './Textarea@v2.vue';
4
+ import Textarea from './Textarea.vue';
5
5
 
6
6
  import Checkbox from './Checkbox.vue';
7
+ import CheckboxItem from './CheckboxItem.vue';
8
+ import CheckboxGroup from './CheckboxGroup.vue';
7
9
  import Select from './Select@v3.vue';
8
10
  import SelectList from './SelectList.vue';
9
11
  import SelectTags from './SelectTags.vue';
@@ -17,8 +19,6 @@ import SearchMoreSelect from './SearchMoreSelect.vue';
17
19
  import PageSelect from './PageSelect.vue';
18
20
  import SelectTree from './SelectTree/SelectTree@v1.vue';
19
21
 
20
- // import DateView from './DateView.vue';
21
- // import DateView from './DateView@v2.vue';
22
22
  import DateView from './DateView@v3.vue';
23
23
  import DateRangeView from './DateRangeView@v3.vue';
24
24
  import DatePicker from './DatePicker.vue';
@@ -34,6 +34,8 @@ export {
34
34
  Switch,
35
35
  Textarea,
36
36
  Checkbox,
37
+ CheckboxItem,
38
+ CheckboxGroup,
37
39
  Select,
38
40
  SelectList,
39
41
  SelectTags,