plugin-ui-for-kzt 0.0.19 → 0.0.20

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 (41) hide show
  1. package/dist/components/BaseButton/BaseButton.vue.d.ts +0 -2
  2. package/dist/components/BaseCalendar/BaseCalendar.vue.d.ts +9 -1
  3. package/dist/components/BaseCheckbox/BaseCheckbox.vue.d.ts +0 -2
  4. package/dist/components/BaseDropdown/BaseDropdown.vue.d.ts +0 -2
  5. package/dist/components/BaseField/BaseField.vue.d.ts +98 -0
  6. package/dist/components/BaseInput/BaseInput.vue.d.ts +16 -14
  7. package/dist/components/BaseInputCalendar/BaseInputCalendar.vue.d.ts +13 -15
  8. package/dist/components/BaseInputCurrency/BaseInputCurrency.vue.d.ts +7 -9
  9. package/dist/components/BaseInputEmail/BaseInputEmail.vue.d.ts +7 -12
  10. package/dist/components/BaseInputPhone/BaseInputPhone.vue.d.ts +7 -12
  11. package/dist/components/BaseOpenedListItem/BaseOpenedListItem.vue.d.ts +0 -2
  12. package/dist/components/BaseRadio/BaseRadio.vue.d.ts +0 -2
  13. package/dist/components/BaseSegmentedButtons/BaseSegmentedButtons.vue.d.ts +0 -2
  14. package/dist/components/BaseSiteInput/BaseSiteInput.vue.d.ts +11 -7
  15. package/dist/components/BaseTextarea/BaseTextarea.vue.d.ts +7 -12
  16. package/dist/components/BaseToggle/BaseToggle.vue.d.ts +0 -2
  17. package/dist/components/BaseTooltip/BaseTooltip.vue.d.ts +1 -1
  18. package/dist/composables/kit/state.d.ts +1 -2
  19. package/dist/index.d.ts +2 -1
  20. package/dist/index.js +1 -1
  21. package/example/App.vue +170 -128
  22. package/package.json +1 -1
  23. package/src/components/BaseField/BaseField.vue +184 -0
  24. package/src/components/BaseField/README.md +85 -0
  25. package/src/components/BaseInput/BaseInput.vue +162 -228
  26. package/src/components/BaseInputCalendar/BaseInputCalendar.vue +10 -7
  27. package/src/components/BaseInputCurrency/BaseInputCurrency.vue +39 -78
  28. package/src/components/BaseInputEmail/BaseInputEmail.vue +2 -4
  29. package/src/components/BaseInputPhone/BaseInputPhone.vue +29 -89
  30. package/src/components/BaseSelect/BaseSelect.vue +9 -52
  31. package/src/components/BaseSiteInput/BaseSiteInput.vue +11 -63
  32. package/src/components/BaseTextarea/BaseTextarea.vue +3 -30
  33. package/src/composables/kit/state.ts +1 -2
  34. package/src/index.ts +5 -2
  35. package/src/styles/index.scss +87 -2
  36. package/src/styles/root.scss +1 -0
  37. package/src/styles/variables.scss +2 -1
  38. package/src/types/calendar.d.ts +2 -0
  39. package/src/types/field.d.ts +12 -0
  40. package/src/types/input.d.ts +26 -8
  41. package/src/types/utils.d.ts +0 -1
@@ -1,53 +1,42 @@
1
1
  <template>
2
- <div class="base-input" :class="classList">
3
- <label class="base-input__label" :for="id">
4
- <span v-if="label" class="base-input__label-text">{{ label }}</span>
5
-
6
- <div class="base-input__wrapper">
7
- <div v-if="$slots['left-icon']" class="base-input__icon base-input__icon--left">
8
- <slot name="left-icon"></slot>
9
- </div>
10
-
11
- <input
12
- :id="id"
13
- :type="type"
14
- :value="modelValue"
15
- v-maska="mask"
16
- v-bind="componentAttrs"
17
- :placeholder="placeholder || ''"
18
- class="base-input__field"
19
- @input="handleInput"
20
- />
21
-
22
- <div v-if="$slots['right-icon']" class="base-input__icon base-input__icon--right">
23
- <slot name="right-icon"></slot>
24
- </div>
2
+ <div class="base-input" :class="classList">
3
+ <div class="base-input__wrapper">
4
+ <div v-if="$slots['left-icon']" class="base-input__icon base-input__icon--left">
5
+ <slot name="left-icon"></slot>
6
+ </div>
7
+ <input
8
+ :id="id"
9
+ :type="type"
10
+ :value="modelValue"
11
+ v-maska="mask"
12
+ v-bind="componentAttrs"
13
+ :placeholder="placeholder || ''"
14
+ class="base-input__field"
15
+ :class="{ 'base-input__field--focusable': focusable }"
16
+ @input="handleInput"
17
+ />
18
+ <div v-if="$slots['right-icon']" class="base-input__icon base-input__icon--right">
19
+ <slot name="right-icon"></slot>
25
20
  </div>
26
-
27
- <transition name="error">
28
- <div v-if="(error && typeof error === 'string') || hint" class="base-input__hint">
29
- {{ error || hint }}
30
- </div>
31
- </transition>
32
- </label>
33
21
  </div>
22
+ </div>
34
23
  </template>
35
24
 
36
25
  <script setup lang="ts">
37
26
  import { computed, useAttrs, useSlots } from 'vue';
38
- import type { ICoreInputProps } from '../../types/input'
39
- import { useKitSize } from '../../composables/kit/size'
40
- import { useKitState } from '../../composables/kit/state'
41
- import { vMaska } from "maska/vue"
27
+ import type { ICoreInputProps } from '../../types/input';
28
+ import { useKitSize } from '../../composables/kit/size';
29
+ import { useKitState } from '../../composables/kit/state';
30
+ import { vMaska } from 'maska/vue';
42
31
 
43
32
  const props = withDefaults(defineProps<ICoreInputProps>(), {
33
+ id: '',
44
34
  size: 'medium',
45
35
  type: 'text',
46
36
  modelValue: '',
47
- placeholder: '' as string,
48
- error: '',
49
- hint: '',
37
+ placeholder: '',
50
38
  mask: '',
39
+ focusable: true,
51
40
  });
52
41
 
53
42
  const emit: (event: 'update:modelValue', value: string) => void = defineEmits();
@@ -55,22 +44,21 @@ const emit: (event: 'update:modelValue', value: string) => void = defineEmits();
55
44
  const { sizeClassList } = useKitSize(props);
56
45
  const { stateClassList, stateAttrs } = useKitState(props);
57
46
  const attrs = useAttrs();
47
+ const slots = useSlots();
58
48
 
59
49
  const componentAttrs = computed(() => ({
60
50
  ...attrs,
61
51
  ...stateAttrs.value,
62
52
  }));
63
53
 
64
- const slots = useSlots();
65
-
66
54
  const classList = computed(() => [
67
55
  sizeClassList.value,
68
56
  stateClassList.value,
69
-
70
57
  {
71
- '--is-readonly': props.readonly,
72
58
  '--icon-left': !!slots['left-icon'],
73
59
  '--icon-right': !!slots['right-icon'],
60
+ '--is-error': props.error,
61
+ '--is-readonly': props.readonly,
74
62
  },
75
63
  ]);
76
64
 
@@ -84,94 +72,81 @@ function handleInput(event: Event) {
84
72
  @import '../../styles/variables';
85
73
  @import '../../styles/root';
86
74
 
87
- .base-input {
88
- width: 100%;
89
- $input: &;
90
-
91
- &__wrapper {
92
- position: relative;
93
- display: flex;
94
- flex-direction: column;
95
- align-items: flex-start;
96
- width: 100%;
97
- }
98
-
99
- &__field {
100
- flex: 1;
101
- width: 100%;
102
- height: 100%;
103
- color: var(--primary-text-primary);
104
- background: var(--bg-light);
105
- border: 1px solid var(--primary-black-300);
106
- outline: none;
107
- transition: all var(--transition);
108
-
109
- &::placeholder {
110
- color: var(--primary-text-tertiary);
111
- }
75
+ .base-input {
76
+ width: 100%;
77
+ $input: &;
112
78
 
113
- @include pressed {
114
- color: var(--primary-blue);
115
- }
116
-
117
- @include focused {
118
- border: 1px solid var(--primary-blue-500);
119
- outline: 4px solid var(--effects-primary-focus);
120
- }
121
-
122
- @include is-disabled-state {
123
- & {
124
- color: var(--primary-text-tertiary);
125
- background: var(--primary-black-100);
126
- }
127
- }
128
- }
79
+ &__wrapper {
80
+ position: relative;
81
+ display: flex;
82
+ align-items: center;
83
+ width: 100%;
84
+ }
129
85
 
130
- &__icon {
131
- display: flex;
132
- align-items: center;
133
- justify-content: center;
134
- color: var(--primary-black-500);
86
+ &__field {
87
+ flex: 1;
88
+ width: 100%;
89
+ height: 100%;
90
+ color: var(--primary-text-primary);
91
+ background: var(--bg-light);
92
+ border: 1px solid var(--primary-black-300);
93
+ outline: none;
94
+ transition: all var(--transition);
95
+
96
+ &::placeholder {
97
+ color: var(--primary-text-tertiary);
135
98
  }
136
99
 
137
- &__hint {
138
- transition: opacity 0.3s ease, transform 0.3s ease;
100
+ @include pressed {
101
+ color: var(--primary-blue);
139
102
  }
140
103
 
141
104
  @include is-disabled-state {
142
- #{$input}__icon--right {
143
- color: var(--primary-black-400);
144
- }
145
-
146
- #{$input}__hint {
147
- color: var(--primary-text-secondary);
105
+ & {
106
+ color: var(--primary-text-tertiary);
107
+ background: var(--primary-black-100);
148
108
  }
149
109
  }
150
110
 
151
- &__icon--left, &__icon--right {
152
- position: absolute;
153
- top: 50%;
154
- transform: translateY(-50%);
111
+ &--focusable {
112
+ @include focused {
113
+ border: 1px solid var(--primary-blue-500);
114
+ outline: 4px solid var(--effects-primary-focus);
115
+ }
155
116
  }
117
+ }
156
118
 
157
- &__label {
158
- display: flex;
159
- flex-direction: column;
160
- gap: 6px;
161
- width: 100%;
162
- }
119
+ &__icon {
120
+ display: flex;
121
+ align-items: center;
122
+ justify-content: center;
123
+ color: var(--primary-black-500);
124
+ }
163
125
 
164
- &__label-text {
165
- color: var(--primary-text-primary);
126
+ @include is-disabled-state {
127
+ #{$input}__icon--right {
128
+ color: var(--primary-black-400);
166
129
  }
130
+ }
167
131
 
168
- &.--is-error {
169
- #{$input}__hint {
170
- color: var(--error-red);
171
- }
132
+ &__icon--left,
133
+ &__icon--right {
134
+ position: absolute;
135
+ top: 50%;
136
+ transform: translateY(-50%);
137
+ }
138
+
139
+ &.--is-error {
172
140
 
173
141
  #{$input}__field {
174
142
  border-color: var(--error-red-light-01);
143
+
144
+ &--focusable {
145
+ @include focused {
146
+ border: 1px solid var(--error-red-light-02);
147
+ outline: 4px solid var(--effects-error-focus);
148
+ }
149
+ }
175
150
  }
176
151
 
177
152
  #{$input}__icon--right > * {
@@ -179,141 +154,100 @@ function handleInput(event: Event) {
179
154
  }
180
155
  }
181
156
 
182
- &.--small-size {
183
- #{$input} {
184
- &__label {
185
- font: var(--typography-text-s-medium);
186
- }
187
-
188
- &__hint {
189
- font: var(--typography-text-s-regular);
190
- }
191
- }
192
-
193
- #{$input}__wrapper {
194
- height: 40px;
195
- }
196
-
197
- #{$input}__field {
198
- padding: 8px 14px;
199
- font: var(--typography-text-m-regular);
200
- border-radius: 10px;
201
- }
202
-
203
- &.--icon-left #{$input}__field {
204
- padding-left: 42px;
205
- }
206
-
207
- &.--icon-right #{$input}__field {
208
- padding-right: 38px;
209
- }
210
-
211
- #{$input}__icon--left {
212
- left: 14px;
213
- width: 20px;
214
- height: 20px;
215
- }
216
-
217
- #{$input}__icon--right {
218
- right: 14px;
219
- width: 16px;
220
- height: 16px;
221
- }
157
+ &.--small-size {
158
+ #{$input}__wrapper {
159
+ height: 40px;
222
160
  }
223
161
 
224
- &.--medium-size {
225
- #{$input} {
226
- &__label {
227
- font: var(--typography-text-s-medium);
228
- }
162
+ #{$input}__field {
163
+ padding: 8px 14px;
164
+ font: var(--typography-text-m-regular);
165
+ border-radius: 10px;
166
+ }
229
167
 
230
- &__hint {
231
- font: var(--typography-text-s-regular);
232
- }
168
+ &.--icon-left #{$input}__field {
169
+ padding-left: 42px;
170
+ }
233
171
 
234
- &__wrapper {
235
- height: 48px;
236
- }
172
+ &.--icon-right #{$input}__field {
173
+ padding-right: 38px;
174
+ }
237
175
 
238
- &__field {
239
- padding: 12px 14px;
240
- font: var(--typography-text-m-regular);
241
- border-radius: 12px;
242
- }
243
- }
176
+ #{$input}__icon--left {
177
+ left: 14px;
178
+ width: 20px;
179
+ height: 20px;
180
+ }
244
181
 
245
- &.--icon-left #{$input}__field {
246
- padding-left: 46px;
247
- }
182
+ #{$input}__icon--right {
183
+ right: 14px;
184
+ width: 16px;
185
+ height: 16px;
186
+ }
187
+ }
248
188
 
249
- &.--icon-right #{$input}__field {
250
- padding-right: 42px;
251
- }
189
+ &.--medium-size {
190
+ #{$input}__wrapper {
191
+ height: 48px;
192
+ }
252
193
 
253
- #{$input}__icon--left {
254
- left: 14px;
255
- width: 24px;
256
- height: 24px;
257
- }
194
+ #{$input}__field {
195
+ padding: 12px 14px;
196
+ font: var(--typography-text-m-regular);
197
+ border-radius: 12px;
198
+ }
258
199
 
259
- #{$input}__icon--right {
260
- right: 14px;
261
- width: 20px;
262
- height: 20px;
263
- }
200
+ &.--icon-left #{$input}__field {
201
+ padding-left: 46px;
264
202
  }
265
203
 
266
- &.--large-size {
267
- #{$input} {
268
- &__label {
269
- font: var(--typography-text-m-medium);
270
- }
204
+ &.--icon-right #{$input}__field {
205
+ padding-right: 42px;
206
+ }
271
207
 
272
- &__hint {
273
- font: var(--typography-text-m-regular);
274
- }
208
+ #{$input}__icon--left {
209
+ left: 14px;
210
+ width: 24px;
211
+ height: 24px;
212
+ }
275
213
 
276
- &__wrapper {
277
- height: 56px;
278
- }
214
+ #{$input}__icon--right {
215
+ right: 14px;
216
+ width: 20px;
217
+ height: 20px;
218
+ }
219
+ }
279
220
 
280
- &__field {
281
- padding: 14px 16px;
282
- font: var(--typography-text-l-regular);
283
- border-radius: 12px;
284
- }
285
- }
221
+ &.--large-size {
222
+ #{$input}__wrapper {
223
+ height: 56px;
224
+ }
286
225
 
287
- &.--icon-left #{$input}__field {
288
- padding-left: 56px;
289
- }
226
+ #{$input}__field {
227
+ padding: 14px 16px;
228
+ font: var(--typography-text-l-regular);
229
+ border-radius: 12px;
230
+ }
290
231
 
291
- &.--icon-right #{$input}__field {
292
- padding-right: 48px;
293
- }
232
+ &.--icon-left #{$input}__field {
233
+ padding-left: 56px;
234
+ }
294
235
 
295
- #{$input}__icon--left {
296
- left: 16px;
297
- width: 32px;
298
- height: 32px;
299
- }
236
+ &.--icon-right #{$input}__field {
237
+ padding-right: 48px;
238
+ }
300
239
 
301
- #{$input}__icon--right {
302
- right: 16px;
303
- width: 24px;
304
- height: 24px;
305
- }
240
+ #{$input}__icon--left {
241
+ left: 16px;
242
+ width: 32px;
243
+ height: 32px;
306
244
  }
307
- }
308
- .error-enter-active,
309
- .error-leave-active {
310
- transition: opacity 0.3s ease, transform 0.3s ease;
311
- }
312
245
 
313
- .error-enter-from,
314
- .error-leave-to {
315
- opacity: 0;
316
- transform: translateY(10px);
317
- max-height: 0;
246
+ #{$input}__icon--right {
247
+ right: 16px;
248
+ width: 24px;
249
+ height: 24px;
250
+ }
318
251
  }
319
- </style>
252
+ }
253
+ </style>
@@ -6,11 +6,11 @@
6
6
  :range="range"
7
7
  :size="size"
8
8
  :min-date="minDate"
9
+ :id="id"
9
10
  >
10
11
  <base-input
11
- v-bind="{ ...$props, ...$attrs }"
12
+ v-bind="{ ...$props }"
12
13
  :model-value="formattedValue"
13
- :error="errorMessage || props.error"
14
14
  @update:model-value="handleInputUpdate"
15
15
  >
16
16
  <template #['left-icon']>
@@ -37,13 +37,14 @@ const props = withDefaults(defineProps<TCoreInputCalendarProps>(), {
37
37
  type: 'text',
38
38
  modelValue: '',
39
39
  placeholder: '',
40
- error: '',
41
- hint: '',
42
40
  range: false,
43
41
  minDate: null,
44
42
  });
45
43
 
46
- const emit: (event: 'update:modelValue', value: string) => void = defineEmits();
44
+ const emit = defineEmits<{
45
+ 'update:modelValue': [value: string],
46
+ 'validationError': [value: string],
47
+ }>();
47
48
 
48
49
  const inputValue = ref<string>('');
49
50
 
@@ -201,16 +202,18 @@ function handleInputUpdate(value: string) {
201
202
 
202
203
  inputValue.value = filteredValue;
203
204
  emit('update:modelValue', filteredValue);
205
+ emit('validationError', validation.value);
204
206
 
205
207
  const parsed = parseDateString(filteredValue);
206
208
  if (parsed) {
207
209
  const formatted = formatDateRange(parsed);
208
210
  inputValue.value = formatted;
209
211
  emit('update:modelValue', formatted);
212
+ emit('validationError', validation.value);
210
213
  }
211
214
  }
212
215
 
213
- const errorMessage = computed<string>(() => {
216
+ const validation = computed<string>(() => {
214
217
  if (!inputValue.value) {
215
218
  return '';
216
219
  }
@@ -233,7 +236,7 @@ const errorMessage = computed<string>(() => {
233
236
 
234
237
  <style scoped lang="scss">
235
238
  .base-input-calendar {
236
- width: max-content;
239
+ width: 100%;
237
240
 
238
241
  &__wrapper {
239
242
  position: relative;