mediacube-ui 0.1.346 → 0.1.347

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 (108) hide show
  1. package/CHANGELOG.md +2 -0
  2. package/dist/0.mediacube-ui.umd.js +50 -0
  3. package/dist/assets/img/icons.3b7d59b2f49c67a2a3a4566b8ab233fd.svg +1 -0
  4. package/dist/assets/img/no_table_data.236cd56f46cfb71fc363b008d4ca70d5.png +0 -0
  5. package/dist/assets/img/no_user.e0030d6e54e2400e1181fd22b83cf8ae.png +0 -0
  6. package/dist/mediacube-ui.umd.js +1 -0
  7. package/package.json +14 -16
  8. package/src/assets/tokens/tokens.json +5 -0
  9. package/dist/mediacube-ui.common.js +0 -378
  10. package/src/elements/McAvatar/McAvatar.vue +0 -274
  11. package/src/elements/McBadge/McBadge.vue +0 -148
  12. package/src/elements/McButton/McButton.vue +0 -841
  13. package/src/elements/McChip/McChip.vue +0 -300
  14. package/src/elements/McCropper/McCropper.vue +0 -133
  15. package/src/elements/McDate/McDate.vue +0 -105
  16. package/src/elements/McDatePicker/McDatePicker.vue +0 -902
  17. package/src/elements/McField/McFieldCheckbox/McFieldCheckbox.vue +0 -332
  18. package/src/elements/McField/McFieldRadio/McFieldRadioButton/McFieldRadioButton.vue +0 -201
  19. package/src/elements/McField/McFieldRadio/McFieldRadioGroup/McFieldRadioGroup.vue +0 -194
  20. package/src/elements/McField/McFieldSelect/McFieldSelect.vue +0 -1087
  21. package/src/elements/McField/McFieldText/McFieldText.vue +0 -969
  22. package/src/elements/McField/McFieldToggle/McFieldToggle.vue +0 -268
  23. package/src/elements/McInfinityLoadingIndicator/McInfinityLoadingIndicator.vue +0 -97
  24. package/src/elements/McNotification/McNotification.vue +0 -209
  25. package/src/elements/McProgress/McProgress.vue +0 -218
  26. package/src/elements/McRangeSlider/McRangeSlider.vue +0 -195
  27. package/src/elements/McSeparator/McSeparator.vue +0 -143
  28. package/src/elements/McSlideUpDown/McSlideUpDown.vue +0 -157
  29. package/src/elements/McSvgIcon/McSvgIcon.vue +0 -127
  30. package/src/elements/McTabs/McTab/McTab.vue +0 -187
  31. package/src/elements/McTabs/McTabs/McTabs.vue +0 -531
  32. package/src/elements/McTitle/McTitle.vue +0 -365
  33. package/src/elements/McTooltip/McTooltip.vue +0 -334
  34. package/src/helpers/consts.js +0 -3
  35. package/src/helpers/delayedAction.js +0 -26
  36. package/src/helpers/storybookFunctions.js +0 -20
  37. package/src/helpers/storybookVariables.js +0 -24
  38. package/src/mixins/equalFieldHeight.js +0 -59
  39. package/src/mixins/fieldErrors.js +0 -28
  40. package/src/patterns/McAccordion/McAccordion.vue +0 -53
  41. package/src/patterns/McCells/McCell/McCell.vue +0 -101
  42. package/src/patterns/McChat/McChat.vue +0 -305
  43. package/src/patterns/McChat/McChatComment/McChatComment.vue +0 -265
  44. package/src/patterns/McChat/McChatForm/McChatForm.vue +0 -147
  45. package/src/patterns/McCollapse/McCollapse.vue +0 -280
  46. package/src/patterns/McDrawer/McDrawer.vue +0 -146
  47. package/src/patterns/McDropdown/McDropdown.vue +0 -247
  48. package/src/patterns/McDropdown/McDropdownPanel/McDropdownPanel.vue +0 -40
  49. package/src/patterns/McFakeScroll/McFakeScroll.vue +0 -277
  50. package/src/patterns/McFilter/McFilter.vue +0 -847
  51. package/src/patterns/McFilter/McFilterChip/McFilterChip.vue +0 -83
  52. package/src/patterns/McFilter/McFilterTags/McFilterTags.vue +0 -374
  53. package/src/patterns/McFilter/McFilterTypeDate/McFilterTypeDate.vue +0 -70
  54. package/src/patterns/McFilter/McFilterTypeRange/McFilterTypeRange.vue +0 -132
  55. package/src/patterns/McFilter/McFilterTypeRelation/McFilterTypeRelation.vue +0 -221
  56. package/src/patterns/McFilter/McFilterTypeSimple/McFilterTypeSimple.vue +0 -161
  57. package/src/patterns/McFilter/McFilterTypeText/McFilterTypeText.vue +0 -62
  58. package/src/patterns/McGrid/McGridCol/McGridCol.vue +0 -165
  59. package/src/patterns/McGrid/McGridRow/McGridRow.vue +0 -158
  60. package/src/patterns/McModal/McModal.vue +0 -680
  61. package/src/patterns/McOverlay/McOverlay.vue +0 -78
  62. package/src/patterns/McPreview/McPreview.vue +0 -118
  63. package/src/patterns/McSideBar/McSideBar/McSideBar.vue +0 -387
  64. package/src/patterns/McSideBar/McSideBarBottom/McSideBarBottom.vue +0 -125
  65. package/src/patterns/McSideBar/McSideBarButton/McSideBarButton.vue +0 -252
  66. package/src/patterns/McSideBar/McSideBarCenter/McSideBarCenter.vue +0 -367
  67. package/src/patterns/McSideBar/McSideBarTop/McSideBarTop.vue +0 -238
  68. package/src/patterns/McStack/McStack.vue +0 -158
  69. package/src/patterns/McTable/McTable/McTable.vue +0 -854
  70. package/src/patterns/McTable/McTableCol/McTableCol.vue +0 -296
  71. package/src/patterns/McTableCard/McTableCard.vue +0 -135
  72. package/src/patterns/McTableCard/McTableCardHeader/McTableCardHeader.vue +0 -74
  73. package/src/patterns/McTopBar/McTopBar.vue +0 -153
  74. package/src/patterns/McWrapScroll/McWrapScroll.vue +0 -291
  75. package/src/styles/_functions.scss +0 -187
  76. package/src/styles/_mixins.scss +0 -612
  77. package/src/styles/_spacing.scss +0 -33
  78. package/src/styles/_variables.scss +0 -23
  79. package/src/styles/global.scss +0 -308
  80. package/src/styles/main.scss +0 -4
  81. package/src/styles/table.scss +0 -10
  82. package/src/styles/toast.scss +0 -55
  83. package/src/templates/layouts/McContentFixed/McContentFixed.vue +0 -60
  84. package/src/templates/layouts/McMain/McMain.vue +0 -115
  85. package/src/templates/layouts/McRoot/McRoot.vue +0 -45
  86. package/src/tokens/animations.scss +0 -9
  87. package/src/tokens/border-radius.scss +0 -26
  88. package/src/tokens/box-shadows.scss +0 -28
  89. package/src/tokens/colors.scss +0 -82
  90. package/src/tokens/durations.scss +0 -7
  91. package/src/tokens/easings.scss +0 -6
  92. package/src/tokens/font-families.scss +0 -8
  93. package/src/tokens/font-sizes.scss +0 -23
  94. package/src/tokens/font-weights.scss +0 -9
  95. package/src/tokens/gradients.scss +0 -19
  96. package/src/tokens/letter-spacings.scss +0 -6
  97. package/src/tokens/line-heights.scss +0 -22
  98. package/src/tokens/media-queries.scss +0 -32
  99. package/src/tokens/opacities.scss +0 -8
  100. package/src/tokens/sizes.scss +0 -47
  101. package/src/tokens/spacings.scss +0 -38
  102. package/src/tokens/z-indexes.scss +0 -14
  103. package/src/utils/dayjs.js +0 -19
  104. package/src/utils/filters.js +0 -11
  105. package/src/utils/getTokens.js +0 -41
  106. package/src/utils/load-icons.js +0 -3
  107. package/src/utils/treeSearch.js +0 -30
  108. package/src/utils/webFontLoader.js +0 -12
@@ -1,969 +0,0 @@
1
- <template>
2
- <div ref="field" :dir="dir" :class="classes">
3
- <label :for="name" class="mc-field-text__header">
4
- <!-- @slot Слот заголовка -->
5
- <slot name="header">
6
- <mc-title v-if="title" :ellipsis="false" max-width="100%" weight="medium">{{ computedTitle }}</mc-title>
7
- </slot>
8
- </label>
9
- <div class="mc-field-text__inner">
10
- <div class="mc-field-text__main">
11
- <div v-if="$slots.prepend" class="mc-field-text__prepend">
12
- <!-- @slot Слот в начале инпута -->
13
- <slot name="prepend" />
14
- </div>
15
- <label class="mc-field-text__input-wrapper">
16
- <textarea
17
- v-if="isTextarea"
18
- v-bind="inputAttrs"
19
- :maxlength="maxLength"
20
- v-on="listeners"
21
- @input="$event => handleInput($event.target.value)"
22
- />
23
- <textarea-autosize
24
- v-else-if="isTextareaAutosize"
25
- v-bind="inputAttrs"
26
- rows="1"
27
- :min-height="minHeight"
28
- :max-height="maxHeight"
29
- v-on="listeners"
30
- @input="handleInput"
31
- />
32
-
33
- <template v-else>
34
- <!-- When possible, prefer to use input type="tel" to avoid glitch on android devices -->
35
- <imask-input
36
- v-if="isMaskVisible"
37
- ref="input"
38
- v-bind="maskInputAttrs"
39
- v-on="listeners"
40
- @input="handleInput"
41
- />
42
- <input
43
- v-else
44
- ref="input"
45
- v-bind="inputAttrs"
46
- :type="prettyType"
47
- :readonly="readOnly"
48
- :maxlength="maxLength"
49
- v-on="listeners"
50
- @input="prepareHandleInput"
51
- @keydown="prepareHandleKeyDown"
52
- />
53
- </template>
54
- </label>
55
- <div
56
- v-if="$slots.append || copy || isPassword"
57
- class="mc-field-text__append"
58
- :class="{ 'mc-field-text__append--indent-bottom': hasCharCounter }"
59
- >
60
- <!-- @slot Слот в конце инпута -->
61
- <slot name="append" />
62
- <mc-button v-if="copy" variation="black-link" size="m-compact" @click.prevent="handlerCopy(value)">
63
- <mc-svg-icon slot="icon-append" name="copy" />
64
- </mc-button>
65
- <component v-bind="passwordTooltipProps">
66
- <mc-button
67
- v-if="isPassword"
68
- variation="black-link"
69
- size="m-compact"
70
- tabindex="-1"
71
- type="button"
72
- @click.prevent="togglePasswordVisibility"
73
- >
74
- <mc-svg-icon slot="icon-append" :name="passwordIcon" />
75
- </mc-button>
76
- </component>
77
- </div>
78
- <mc-title
79
- v-if="hasCharCounter"
80
- class="mc-field-text__char-counter"
81
- variation="overline"
82
- text-align="right"
83
- :color="charCounterColor"
84
- >
85
- {{ charCounterTitle }}
86
- </mc-title>
87
- </div>
88
- <div v-if="$slots.right" class="mc-field-text__right">
89
- <!-- @slot Слот справа инпута -->
90
- <slot name="right" />
91
- </div>
92
- </div>
93
- <div v-if="errorText || helpText || $slots.footer" class="mc-field-text__footer">
94
- <mc-title
95
- v-if="errorText"
96
- tag-name="div"
97
- color="red"
98
- variation="overline"
99
- max-width="100%"
100
- :ellipsis="false"
101
- class="mc-field-text__error-text"
102
- v-html="errorText.replace(/-/gm, '&#x2011;')"
103
- />
104
- <br v-if="errorText" />
105
- <!-- @slot Слот доп. текста под инпутом -->
106
- <slot name="footer">
107
- <mc-title
108
- v-if="helpText"
109
- tag-name="div"
110
- variation="overline"
111
- color="gray"
112
- max-width="100%"
113
- :ellipsis="false"
114
- >
115
- {{ helpText }}
116
- </mc-title>
117
- </slot>
118
- </div>
119
- </div>
120
- </template>
121
-
122
- <script>
123
- import _omit from 'lodash/omit'
124
- import { getTokenValue } from '../../../utils/getTokens'
125
- import { IMaskComponent, IMask } from 'vue-imask'
126
-
127
- import TextareaAutosize from 'vue2-textarea-autosize/src/components/TextareaAutosize.vue'
128
- import McTitle from '../../McTitle/McTitle'
129
- import McButton from '../../McButton/McButton'
130
- import McSvgIcon from '../../McSvgIcon/McSvgIcon'
131
- import fieldErrors from '../../../mixins/fieldErrors'
132
- import McTooltip from '../../McTooltip/McTooltip'
133
- import equalFieldHeight from '../../../mixins/equalFieldHeight'
134
- import { LANGUAGES } from '../../../helpers/consts'
135
-
136
- export default {
137
- name: 'McFieldText',
138
- components: {
139
- McButton,
140
- McTitle,
141
- McSvgIcon,
142
- TextareaAutosize,
143
- // eslint-disable-next-line vue/no-unused-components
144
- McTooltip, //Используется через component :is
145
- 'imask-input': IMaskComponent,
146
- },
147
- mixins: [fieldErrors, equalFieldHeight],
148
- props: {
149
- /**
150
- * Тип:
151
- * `textarea, textarea-autosize и
152
- * нативные как text, password, email и т.д.`
153
- *
154
- * кастомный num - разрешает ввод только цифр и дробных чисел, без ислчений ввиде буквы 'E'
155
- * кастомный int - разрешает ввод только целочисленных значений
156
- * кастомный amount_format - форматирует ввод числовых данных разделяя на разряды(1 000 000)
157
- * date - добавляет placeholder, маску и ограничения ввода
158
- * uppercase\lowercase - форматирует текст согласну значению (верхний\нижний регистр)
159
- * phone_number - добавляет '+' к номеру телефона при фокусе без возможности удалить его
160
- */
161
- type: {
162
- type: String,
163
- default: 'text',
164
- },
165
-
166
- /**
167
- * Заголовок поля:
168
- *
169
- */
170
- title: {
171
- type: String,
172
- default: null,
173
- },
174
-
175
- /**
176
- * Маска поля:
177
- *
178
- * tokens - https://imask.js.org/guide.html
179
- *
180
- */
181
- mask: {
182
- type: String,
183
- default: null,
184
- },
185
-
186
- /**
187
- * Вспомогательный текст под инпутом:
188
- *
189
- */
190
- helpText: {
191
- type: String,
192
- default: null,
193
- },
194
-
195
- /**
196
- * Отключенное состояние
197
- *
198
- */
199
- disabled: {
200
- type: Boolean,
201
- default: false,
202
- },
203
-
204
- /**
205
- * Значение
206
- *
207
- */
208
- value: {
209
- default: null,
210
- },
211
-
212
- /**
213
- * Ошибки
214
- *
215
- */
216
- errors: {
217
- type: Array,
218
- default: null,
219
- },
220
-
221
- /**
222
- * Placeholder
223
- *
224
- */
225
- placeholder: {
226
- type: String,
227
- default: null,
228
- },
229
-
230
- /**
231
- * Name
232
- *
233
- */
234
- name: {
235
- type: String,
236
- required: true,
237
- },
238
- /**
239
- * плейсхолдеры для короткого обозначения даты (для маски dd.mm.yyyy)
240
- * {
241
- * date: 'd',
242
- * month: 'm',
243
- * year: 'y',
244
- * }
245
- *
246
- */
247
- dateMaskPlaceholder: {
248
- type: Object,
249
- default: () => ({}),
250
- },
251
- /**
252
- * textarea-autosize Min height
253
- *
254
- */
255
- minHeight: {
256
- type: Number,
257
- default: null,
258
- },
259
-
260
- /**
261
- * textarea-autosize Max height
262
- *
263
- */
264
- maxHeight: {
265
- type: Number,
266
- default: null,
267
- },
268
-
269
- /**
270
- * Максимальная длина строки в инпуте
271
- *
272
- */
273
- maxLength: {
274
- type: Number,
275
- default: null,
276
- },
277
-
278
- /**
279
- * Состояние копирования
280
- *
281
- */
282
- copy: {
283
- type: Boolean,
284
- default: false,
285
- },
286
-
287
- /**
288
- * Автокомплит введённого ранее текста: on, off
289
- *
290
- */
291
- autocomplete: {
292
- type: String,
293
- default: 'on',
294
- },
295
-
296
- /**
297
- * только чтение текста
298
- *
299
- */
300
- readOnly: {
301
- type: Boolean,
302
- default: false,
303
- },
304
-
305
- /**
306
- * Атрибут tabindex для главного элемента
307
- *
308
- */
309
- tabindex: {
310
- type: [String, Number],
311
- },
312
-
313
- /**
314
- * Tooltip для кнопка "показать пароль"
315
- *
316
- */
317
- passwordTooltip: {
318
- type: String,
319
- default: null,
320
- },
321
-
322
- /**
323
- * Tooltip для кнопка "Скрыть пароль", если не указывать, то будет аналогичен "показать"
324
- *
325
- */
326
- passwordHideTooltip: {
327
- type: String,
328
- default: null,
329
- },
330
-
331
- /**
332
- * Очищаем данные от маски на выходе
333
- */
334
- clearOutput: {
335
- type: Boolean,
336
- default: false,
337
- },
338
-
339
- /**
340
- * Кастомные настройки для маски
341
- * См. https://imask.js.org/guide.html
342
- *
343
- * Например:
344
- * {
345
- * autofix: true,
346
- * blocks: {
347
- * d: {mask: IMask.MaskedRange, placeholderChar: 'd', from: 1, to: 31, maxLength: 2},
348
- * m: {mask: IMask.MaskedRange, placeholderChar: 'm', from: 1, to: 12, maxLength: 2},
349
- * Y: {mask: IMask.MaskedRange, placeholderChar: 'y', from: 1900, to: 2999, maxLength: 4}
350
- * }
351
- * }
352
- */
353
- maskOptions: {
354
- type: Object,
355
- default: null,
356
- },
357
- required: {
358
- type: Boolean,
359
- default: false,
360
- },
361
- /**
362
- * Для какого языка поле ввода
363
- */
364
- locale: {
365
- type: String,
366
- default: null,
367
- },
368
- /**
369
- * Мобильное ли разрешение
370
- * (Используется для триггера тултипа в кнопке с паролем)
371
- */
372
- isMobile: {
373
- type: Boolean,
374
- default: false,
375
- },
376
- /**
377
- * Свойство на ограничение количества символов после точки для числовых типов (num || amount_format)
378
- */
379
- maxDecimals: {
380
- type: Number,
381
- default: 2,
382
- },
383
- },
384
-
385
- data() {
386
- return {
387
- prependWidth: 0,
388
- appendWidth: 0,
389
- prettyType: this.type,
390
- }
391
- },
392
-
393
- computed: {
394
- rtl() {
395
- return LANGUAGES.rtl.includes(this.locale)
396
- },
397
- dir() {
398
- return this.rtl ? 'rtl' : null
399
- },
400
- classes() {
401
- return {
402
- 'mc-field-text': true,
403
- 'mc-field-text--error': this.errorText,
404
- 'mc-field-text--textarea': this.isTextarea,
405
- 'mc-field-text--textarea-autosize': this.isTextareaAutosize,
406
- 'mc-field-text--disabled': this.disabled,
407
- 'mc-field-text--copy': this.copy,
408
- 'mc-field-text--rtl': this.rtl,
409
- }
410
- },
411
- computedTitle() {
412
- return `${this.title}${this.required ? ' *' : ''}`
413
- },
414
- isMaskVisible() {
415
- return this.mask || this.maskOptions || this.prettyType === 'date'
416
- },
417
-
418
- isTextarea() {
419
- return this.type === 'textarea'
420
- },
421
-
422
- isTextareaAutosize() {
423
- return this.type === 'textarea-autosize'
424
- },
425
-
426
- isPassword() {
427
- return this.type === 'password'
428
- },
429
- isAmountFormat() {
430
- return this.type === 'amount_format'
431
- },
432
-
433
- hasCharCounter() {
434
- return this.maxLength && (this.isTextarea || this.isTextareaAutosize)
435
- },
436
-
437
- dateMask() {
438
- return {
439
- mask: Date,
440
- autofix: true,
441
- blocks: {
442
- d: {
443
- mask: IMask.MaskedRange,
444
- placeholderChar: this.dateMaskPlaceholder.date || 'd',
445
- from: 1,
446
- to: 31,
447
- maxLength: 2,
448
- },
449
- m: {
450
- mask: IMask.MaskedRange,
451
- placeholderChar: this.dateMaskPlaceholder.month || 'm',
452
- from: 1,
453
- to: 12,
454
- maxLength: 2,
455
- },
456
- Y: {
457
- mask: IMask.MaskedRange,
458
- placeholderChar: this.dateMaskPlaceholder.year || 'y',
459
- from: 1900,
460
- to: 2999,
461
- maxLength: 4,
462
- },
463
- },
464
- }
465
- },
466
-
467
- maskInputAttrs() {
468
- return {
469
- ...this.inputAttrs,
470
- mask: this.mask,
471
- lazy: false,
472
- overwrite: false,
473
- unmask: this.clearOutput,
474
- definitions: {
475
- '#': /./,
476
- },
477
- readonly: this.readOnly,
478
- maxlength: this.maxLength,
479
- type: 'tel',
480
- ...(this.maskOptions ?? {}),
481
- ...(this.prettyType === 'date' ? this.dateMask : {}),
482
- }
483
- },
484
-
485
- computedValue() {
486
- if (this.isAmountFormat && !this.isRtl) {
487
- return this.getAmountFormat(this.value)
488
- } else return this.value
489
- },
490
- isRtl() {
491
- return (
492
- document.querySelector('html').getAttribute('dir') === 'rtl' ||
493
- document.querySelector('html').getAttribute('direction') === 'rtl'
494
- )
495
- },
496
-
497
- inputAttrs() {
498
- return {
499
- class: 'mc-field-text__input',
500
- style: this.inputStyles,
501
- placeholder: this.placeholder,
502
- value: this.computedValue,
503
- disabled: this.disabled,
504
- name: this.name,
505
- id: this.name,
506
- autocomplete: this.autocomplete,
507
- tabindex: this.tabindex,
508
- }
509
- },
510
-
511
- isPasswordType() {
512
- return this.prettyType === 'password'
513
- },
514
-
515
- passwordIcon() {
516
- return this.isPasswordType ? 'visibility_off' : 'visibility'
517
- },
518
-
519
- charCounter() {
520
- return this.value ? this.value.length : 0
521
- },
522
-
523
- charCounterTitle() {
524
- return `${this.charCounter}/${this.maxLength}`
525
- },
526
-
527
- charCounterColor() {
528
- return this.maxLength < this.charCounter ? 'red' : 'dark-gray'
529
- },
530
-
531
- inputStyles() {
532
- const space = parseInt(getTokenValue('$space-150'))
533
- let bottomStyle = {}
534
- if (this.isTextarea || this.isTextareaAutosize) {
535
- const spaceBottomToken = this.hasCharCounter ? '$space-400' : '$space-150'
536
- const spaceBottomValue = parseInt(getTokenValue(spaceBottomToken))
537
- bottomStyle = { paddingBottom: `${spaceBottomValue - 1}px` }
538
- }
539
- return {
540
- paddingInlineStart: this.prependWidth && `${this.prependWidth + space}px`,
541
- paddingInlineEnd: this.appendWidth && `${this.appendWidth + space}px`,
542
- ...bottomStyle,
543
- }
544
- },
545
-
546
- listeners() {
547
- return _omit(this.$listeners, 'input')
548
- },
549
-
550
- passwordTooltipProps() {
551
- return this.passwordTooltip
552
- ? {
553
- is: 'mc-tooltip',
554
- content: this.isPasswordType
555
- ? this.passwordTooltip
556
- : this.passwordHideTooltip || this.passwordTooltip,
557
- placement: 'top',
558
- trigger: this.isMobile ? 'focus click' : 'hover focus',
559
- size: 's',
560
- }
561
- : {
562
- is: 'div',
563
- class: 'mc-field-text__empty-tooltip',
564
- }
565
- },
566
- },
567
-
568
- mounted() {
569
- this.calculatePadding()
570
- },
571
-
572
- methods: {
573
- setDecimalsLimit(val) {
574
- if (val && this.maxDecimals) {
575
- const [integerPart, decimalPart] = val.split('.')
576
- if (decimalPart?.length > this.maxDecimals) {
577
- return `${integerPart}.${decimalPart.slice(0, this.maxDecimals)}`
578
- }
579
- }
580
- return val
581
- },
582
- /**
583
- * Remove leading zero from input if length > 1 && number isn't decimal
584
- * */
585
- removeLeadingZero(val) {
586
- let result = val
587
- const [first_char] = val || []
588
- if (val.length > 1 && +first_char === 0 && val.indexOf('.') === -1) result = val.slice(1)
589
- return result
590
- },
591
- prepareHandleInput(e) {
592
- let value = e.target.value
593
- const number_types = ['num', 'amount_format']
594
- // For number types add possibility to write ","
595
- if (number_types.includes(this.type)) value = value?.replace(',', '.')
596
- switch (this.type) {
597
- case 'num': {
598
- let [num] = /-?\d*[\.]?\d*/.exec(String(value)) || []
599
- num = this.setDecimalsLimit(num)
600
- num = this.removeLeadingZero(num)
601
- value = num
602
- e.target.value = num
603
- break
604
- }
605
- case 'int': {
606
- let [int] = /-?\d*/.exec(String(e.target.value)) || []
607
- int = this.removeLeadingZero(int)
608
- value = int
609
- e.target.value = int
610
- break
611
- }
612
- case 'amount_format': {
613
- value = this.setDecimalsLimit(value)
614
- value = this.removeLeadingZero(value)
615
- const cursor_position = this.getCaretPos(e.target)?.start
616
- const prepared_value = this.formattedToNumber(value)
617
-
618
- const float_value = parseFloat(prepared_value)
619
- const without_spaces_value = prepared_value.replace(/ /gm, '')
620
-
621
- value = prepared_value
622
- ? String(float_value) === without_spaces_value
623
- ? float_value
624
- : without_spaces_value || float_value || prepared_value
625
- : null
626
- const formatted_value = this.getAmountFormat(prepared_value)
627
- e.target.value = this.isRtl ? formatted_value.replace(/ /gm, '') : formatted_value
628
- const space_length = e.target.value?.slice(0, cursor_position).replace(/[^ ]/gm, '')?.length || 0
629
- this.setCaretPos(e.target, cursor_position + space_length, cursor_position + space_length)
630
- break
631
- }
632
- case 'uppercase': {
633
- const cursor_position = this.getCaretPos(e.target)?.start
634
- value = value?.toUpperCase()
635
- e.target.value = value
636
- this.setCaretPos(e.target, cursor_position, cursor_position)
637
- break
638
- }
639
- case 'lowercase': {
640
- const cursor_position = this.getCaretPos(e.target)?.start
641
- value = value?.toLowerCase()
642
- e.target.value = value
643
- this.setCaretPos(e.target, cursor_position, cursor_position)
644
- break
645
- }
646
- case 'password':
647
- const cursor_position = this.getCaretPos(e.target)?.start
648
- value = value?.replace(/ /gm, '')
649
- e.target.value = value
650
- this.setCaretPos(e.target, cursor_position, cursor_position)
651
- break
652
- case 'phone_number':
653
- if (value.length === 0) value = '+'
654
- if (value.charAt(0) !== '+') value = '+' + value
655
- value = value.replace(/(?!^)\D/g, '')
656
- e.target.value = value
657
- break
658
- }
659
-
660
- this.handleInput(value)
661
- },
662
- prepareHandleKeyDown(e) {
663
- switch (this.type) {
664
- case 'amount_format':
665
- case 'num': {
666
- const exluded_symbols = ['.', ',']
667
- const already_has_symbol =
668
- typeof this.value === 'string' && exluded_symbols.some(symbol => this.value.includes(symbol))
669
- if (exluded_symbols.includes(e.key) && already_has_symbol) {
670
- e.preventDefault()
671
- }
672
- break
673
- }
674
- }
675
- this.$emit('keydown', e)
676
- },
677
- formattedToNumber(value) {
678
- const [first] =
679
- /-?\d*[\.]?\d*/.exec(
680
- String(value)
681
- ?.replace(/ /gm, '')
682
- ?.trim(),
683
- ) || []
684
-
685
- return first
686
- },
687
- setCaretPos(ctrl, start, end) {
688
- // IE >= 9 and other browsers
689
- if (ctrl.setSelectionRange) {
690
- ctrl.focus()
691
- ctrl.setSelectionRange(start, end)
692
- }
693
- // IE < 9
694
- else if (ctrl.createTextRange) {
695
- let range = ctrl.createTextRange()
696
- range.collapse(true)
697
- range.moveEnd('character', end)
698
- range.moveStart('character', start)
699
- range.select()
700
- }
701
- },
702
- getCaretPos(ctrl) {
703
- // IE < 9 Support
704
- if (document.selection) {
705
- ctrl.focus()
706
- let range = document.selection.createRange()
707
- let rangelen = range.text.length
708
- range.moveStart('character', -ctrl.value.length)
709
- let start = range.text.length - rangelen
710
- return { start: start, end: start + rangelen }
711
- }
712
- // IE >=9 and other browsers
713
- else if (ctrl.selectionStart || ctrl.selectionStart == '0') {
714
- return { start: ctrl.selectionStart, end: ctrl.selectionEnd }
715
- } else {
716
- return { start: 0, end: 0 }
717
- }
718
- },
719
- getAmountFormat(value) {
720
- const formatted_number = this.formattedToNumber(value)
721
- const has_fraction = !!String(formatted_number)?.match(/\./)
722
-
723
- const [int, fraction] = String(formatted_number)
724
- .replace(/[^\d\.-]/g, '')
725
- .replace(/\B(?=(?:\d{3})+(?!\d))/g, ' ')
726
- .split('.')
727
-
728
- const formatted_values = [int, fraction?.replace(/ /gm, '') || '']
729
- if (has_fraction) {
730
- return formatted_values.join('.')
731
- }
732
- return formatted_values.filter(v => !!v).join('.')
733
- },
734
- handleInput(value) {
735
- this.toggleErrorVisible()
736
- /**
737
- * Событие инпута
738
- * @property {string}
739
- */
740
- this.$emit('input', value)
741
- },
742
-
743
- calculatePadding() {
744
- this.prependWidth = this.calculateSlotPadding('prepend')
745
- this.appendWidth = this.calculateSlotPadding('append')
746
- },
747
-
748
- calculateSlotPadding(name) {
749
- const tokenSpace = parseInt(getTokenValue('$space-50'))
750
- let result =
751
- this.$slots[name] &&
752
- this.$slots[name].reduce((acc, cur, index) => {
753
- const $el = cur.elm || cur
754
- const space = index && tokenSpace
755
- return acc + $el.getBoundingClientRect().width + space
756
- }, 0)
757
-
758
- if (name === 'prepend') return result
759
-
760
- /**
761
- * Также увеличиваем padding при наличии кнопки копирования и если тип password
762
- */
763
-
764
- const iconSpace = parseInt(getTokenValue('$space-300'))
765
-
766
- result = result ? result + tokenSpace : tokenSpace
767
- this.copy && (result += iconSpace)
768
- this.isPassword && (result += iconSpace)
769
- return result
770
- },
771
- handlerCopy(value) {
772
- /**
773
- * Событие по кнопке копирования
774
- * @property {string}
775
- */
776
- this.$emit('copy', value)
777
- },
778
- togglePasswordVisibility() {
779
- this.prettyType = this.isPasswordType ? 'text' : 'password'
780
- },
781
- },
782
- }
783
- </script>
784
-
785
- <style lang="scss">
786
- @import '../../../styles/mixins';
787
- @import '../../../tokens/durations';
788
- @import '../../../tokens/font-families';
789
- .mc-field-text {
790
- $block-name: &;
791
- display: block;
792
-
793
- &__header {
794
- @include reset-text-indents();
795
- display: block;
796
- margin-bottom: $space-100;
797
-
798
- &:empty {
799
- display: none;
800
- }
801
- }
802
-
803
- &__inner {
804
- display: flex;
805
- align-items: center;
806
- }
807
-
808
- &__right {
809
- flex-shrink: 0;
810
- }
811
-
812
- &__main {
813
- position: relative;
814
- width: 100%;
815
- @include custom-scroll($space-50);
816
- }
817
-
818
- &__prepend,
819
- &__append {
820
- @include reset-text-indents();
821
- position: absolute;
822
- top: 0;
823
- display: flex;
824
- align-items: center;
825
- justify-content: center;
826
- height: 100%;
827
-
828
- &:empty {
829
- display: none;
830
- }
831
-
832
- @include child-indent-right($space-50);
833
- }
834
-
835
- &__prepend {
836
- inset-inline-start: 0;
837
- padding: $space-100 0;
838
- padding-inline: $space-100 $space-50;
839
- }
840
-
841
- &__append {
842
- inset-inline-end: $space-100;
843
- padding: $space-100 0;
844
- padding-inline: $space-50 0;
845
- &--indent-bottom {
846
- padding-bottom: $space-400;
847
- }
848
- }
849
-
850
- &__char-counter {
851
- width: auto !important;
852
- position: absolute;
853
- inset-inline-end: $space-150;
854
- bottom: $space-150;
855
- background-color: $color-transparent;
856
- }
857
-
858
- &__input-wrapper {
859
- display: block;
860
- }
861
-
862
- &__input {
863
- font-family: $font-family-main;
864
- display: inline-block;
865
- vertical-align: middle;
866
- width: 100%;
867
- height: $size-500;
868
- margin: 0;
869
- border: 1px solid $color-outline-gray;
870
- border-radius: $radius-100;
871
- padding: $space-150 - 1px $space-150;
872
- line-height: $line-height-200;
873
- font-size: $font-size-200;
874
- background-color: $color-white;
875
- -moz-appearance: textfield;
876
- transition: background-color $duration-s ease, border-color $duration-s ease;
877
- color: $color-black;
878
-
879
- &:focus,
880
- &:hover {
881
- outline: 0;
882
- border-color: $color-purple;
883
- }
884
-
885
- &::-webkit-search-cancel-button,
886
- &::-webkit-search-decoration,
887
- &::-webkit-inner-spin-button,
888
- &::-webkit-outer-spin-button {
889
- -webkit-appearance: none;
890
- }
891
-
892
- @include input-placeholder() {
893
- color: $color-gray;
894
- }
895
- }
896
-
897
- &__footer {
898
- margin-top: $space-50;
899
- line-height: $line-height-150;
900
-
901
- &:empty {
902
- display: none;
903
- }
904
- }
905
-
906
- &--error {
907
- #{$block-name} {
908
- &__input {
909
- border-color: $color-red;
910
- }
911
- }
912
- }
913
-
914
- &--textarea {
915
- #{$block-name} {
916
- &__append,
917
- &__prepend {
918
- align-items: flex-start;
919
- }
920
-
921
- &__input {
922
- height: auto;
923
- min-height: 92px;
924
- resize: vertical;
925
- }
926
- }
927
- }
928
-
929
- &--textarea-autosize {
930
- #{$block-name} {
931
- &__input {
932
- height: auto;
933
- }
934
- }
935
- }
936
-
937
- &--disabled {
938
- #{$block-name} {
939
- &__input {
940
- color: $color-gray;
941
- cursor: not-allowed;
942
- background-color: $color-hover-gray;
943
- border-color: $color-outline-gray;
944
- }
945
- }
946
- }
947
-
948
- &--copy {
949
- #{$block-name} {
950
- &__input {
951
- color: $color-dark-gray;
952
- background-color: $color-hover-gray;
953
- border-color: $color-outline-gray;
954
- }
955
- }
956
- }
957
-
958
- &--rtl {
959
- direction: rtl;
960
- input {
961
- direction: rtl;
962
- }
963
- }
964
-
965
- &__empty-tooltip {
966
- display: contents;
967
- }
968
- }
969
- </style>