mediacube-ui 0.1.316 → 0.1.318

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 CHANGED
@@ -2,6 +2,10 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
4
4
 
5
+ ### [0.1.318](https://github.com/MediaCubeCo/mcui/compare/v0.1.317...v0.1.318) (2024-10-09)
6
+
7
+ ### [0.1.317](https://github.com/MediaCubeCo/mcui/compare/v0.1.316...v0.1.317) (2024-10-04)
8
+
5
9
  ### [0.1.316](https://github.com/MediaCubeCo/mcui/compare/v0.1.315...v0.1.316) (2024-09-24)
6
10
 
7
11
  ### [0.1.315](https://github.com/MediaCubeCo/mcui/compare/v0.1.314...v0.1.315) (2024-09-16)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mediacube-ui",
3
- "version": "0.1.316",
3
+ "version": "0.1.318",
4
4
  "description": "Design system for Mediacube services",
5
5
  "author": "Mediacube",
6
6
  "private": false,
@@ -18,6 +18,14 @@
18
18
  @open="handleOpen"
19
19
  @close="handleClose"
20
20
  >
21
+ <template v-if="isShowLimitToggle" slot="caret">
22
+ <div :class="computedCaretClass" @click="toggleOptions" />
23
+ </template>
24
+ <template v-if="collapsed && !is_show_all_options" slot="limit">
25
+ <mc-title variation="body" class="mc-field-select__limit-text">
26
+ {{ limitText }}
27
+ </mc-title>
28
+ </template>
21
29
  <template slot="singleLabel" slot-scope="{ option }">
22
30
  <mc-preview v-if="optionWithPreview" class="option__desc" size="l">
23
31
  <mc-svg-icon slot="left" :name="option.icon" size="400" />
@@ -330,6 +338,13 @@ export default {
330
338
  type: Boolean,
331
339
  default: false,
332
340
  },
341
+ /**
342
+ * Ограничить ли отображение выбранных опций
343
+ */
344
+ collapsed: {
345
+ type: Boolean,
346
+ default: false,
347
+ },
333
348
  },
334
349
  data() {
335
350
  return {
@@ -339,6 +354,8 @@ export default {
339
354
  closest_scroll_element: null,
340
355
  scroll_resize_observer: null,
341
356
  local_options: [],
357
+ custom_limit: 0,
358
+ is_show_all_options: false,
342
359
  }
343
360
  },
344
361
  computed: {
@@ -348,7 +365,7 @@ export default {
348
365
  trackBy: 'value',
349
366
  value: this._value,
350
367
  loading: this.loading,
351
- options: this.computedOptions,
368
+ options: this.collapsed ? this.visibleOptions : this.computedOptions,
352
369
  searchable: this.searchable,
353
370
  showLabels: this.showLabels,
354
371
  multiple: this.multiple,
@@ -364,8 +381,26 @@ export default {
364
381
  tabindex: +this.tabindex,
365
382
  ...(this.groupKeys ? { groupLabel: this.groupKeys.label } : {}),
366
383
  ...(this.groupKeys ? { groupValues: this.groupKeys.values } : {}),
384
+ ...(this.collapsed ? { limit: this.is_show_all_options ? this.value?.length : this.custom_limit } : {}),
385
+ class: this.collapsed ? 'mc-field-select__limit' : '',
386
+ }
387
+ },
388
+ visibleOptions() {
389
+ return this.is_show_all_options ? this.computedOptions : this.computedOptions.slice(0, this.custom_limit)
390
+ },
391
+ computedCaretClass() {
392
+ return {
393
+ multiselect__select: true,
394
+ 'mc-field-select__limit-toggle': true,
395
+ 'mc-field-select__limit-toggle--close': this.is_show_all_options,
367
396
  }
368
397
  },
398
+ limitText() {
399
+ return `+${+this.value?.length - +this.custom_limit}`
400
+ },
401
+ isShowLimitToggle() {
402
+ return this.collapsed && this.value?.length > this.custom_limit
403
+ },
369
404
  hasTitle() {
370
405
  return !!this.title
371
406
  },
@@ -396,12 +431,15 @@ export default {
396
431
  'mc-field-select--error': this.errorText,
397
432
  'mc-field-select--disabled': this.disabled,
398
433
  [`mc-field-select--bg-${this.backgroundColor}`]: this.backgroundColor,
399
- 'mc-field-select--is-empty-options-list': this.isEmptyOptionsList || this.loading,
434
+ 'mc-field-select--is-empty-options-list': this.isEmptyOptions,
400
435
  'mc-field-select--with-preview': this.optionWithPreview,
401
436
  'mc-field-select--max-height': this.maxHeight,
402
437
  'mc-field-select--rtl': this.rtl,
403
438
  }
404
439
  },
440
+ isEmptyOptions() {
441
+ return this.isEmptyOptionsList || this.loading || this.computedOptions?.length === this._value?.length
442
+ },
405
443
  computedTitle() {
406
444
  return `${this.title}${this.required ? ' *' : ''}`
407
445
  },
@@ -483,6 +521,7 @@ export default {
483
521
  //Пушим все входящие опции в локальные опции
484
522
  this.local_options.push(...val)
485
523
  this.actualizeSavedOptions()
524
+ this.calcLimit()
486
525
  },
487
526
  },
488
527
  value: {
@@ -490,6 +529,7 @@ export default {
490
529
  immediate: true,
491
530
  handler() {
492
531
  this.actualizeSavedOptions()
532
+ this.calcLimit()
493
533
  },
494
534
  },
495
535
  },
@@ -537,11 +577,10 @@ export default {
537
577
  if (!ref) return
538
578
  const ios_devices = ['iPhone', 'iPad']
539
579
  // Добавляем к позиции отступ visualViewport?.offsetTop, который добавляет iOs при открытии вирутальной клавиатуры
540
- const iosViewportIndent = ios_devices?.some(device => navigator?.platform?.includes(device)) ? window.visualViewport?.offsetTop || 0 : 0
580
+ const iosViewportIndent = ios_devices?.some(device => navigator?.platform?.includes(device))
581
+ ? window.visualViewport?.offsetTop || 0
582
+ : 0
541
583
  // if field hides under scrolled element borders -> blur select to prevent overlap
542
- const scrolledHeight = this.closest_scroll_element?.scrollTop
543
- const fieldHeght = this.$refs[this.field_key]?.clientHeight || 0
544
- const scrolledElementTop = this.closest_scroll_element?.getBoundingClientRect().top
545
584
  if (top >= -height && bottom <= (window.innerHeight || document.documentElement.clientHeight)) {
546
585
  ref.$refs.list.style.width = `${width}px`
547
586
  ref.$refs.list.style.position = 'fixed'
@@ -564,8 +603,10 @@ export default {
564
603
  ref.$refs.list.style.top = `${top + iosViewportIndent + height}px`
565
604
  break
566
605
  }
567
- }
568
- else {
606
+ // Задержка для предотвращения закрытия выпадающего списка на android
607
+ const is_android = /Android/i.test(navigator.userAgent)
608
+ is_android && setTimeout(() => ref.activate(), 100) // переактивировать, если выпадающий список должен быть открыт
609
+ } else {
569
610
  // прячем селект, если его не видно юзеру
570
611
  return ref.deactivate()
571
612
  }
@@ -612,6 +653,43 @@ export default {
612
653
  */
613
654
  this.$emit('input', value)
614
655
  },
656
+ /**
657
+ * Вычисляем custom_limit, которое ограничивает кол-во дочерних элементов внутри родительского, чтобы они не превышали его ширину
658
+ * */
659
+ calcLimit() {
660
+ if (!this.collapsed) return
661
+ this.$nextTick(() => {
662
+ this.custom_limit = Infinity
663
+ let child_width = 0
664
+ const parent = this.$refs[this.key]?.$refs?.tags?.firstChild
665
+ if (!this.value?.length) return
666
+ const limit_text_width = this.getLimitTextWidth() // Получаем ширину текста лимита
667
+ const total_width = +parent?.clientWidth - +limit_text_width
668
+ for (let i = 0; i < this.value?.length; i++) {
669
+ const children = parent?.children?.[i]
670
+ const elem_style = window.getComputedStyle(children)
671
+ child_width += children?.clientWidth + (parseInt(elem_style?.marginRight) || 0)
672
+ // считаем занимаемую дочерними элементами ширину, если превышает родительскую, то выходим из цикла и ставим лимит
673
+ if (+child_width > +total_width) {
674
+ this.custom_limit = i
675
+ break
676
+ }
677
+ }
678
+ })
679
+ },
680
+ getLimitTextWidth() {
681
+ const temp_limit_element = document.createElement('div')
682
+ temp_limit_element.style.visibility = 'hidden'
683
+ temp_limit_element.style.position = 'absolute'
684
+ temp_limit_element.innerText = `+${this.value?.length}` // Устанавливаем текст лимита
685
+ document.body.appendChild(temp_limit_element)
686
+ const limit_text_width = temp_limit_element.clientWidth
687
+ document.body.removeChild(temp_limit_element)
688
+ return limit_text_width
689
+ },
690
+ toggleOptions() {
691
+ this.is_show_all_options = !this.is_show_all_options
692
+ },
615
693
  },
616
694
  }
617
695
  </script>
@@ -755,6 +833,7 @@ export default {
755
833
  }
756
834
 
757
835
  &__tags-wrap {
836
+ width: 100%;
758
837
  position: relative;
759
838
  padding-top: 4px;
760
839
  padding-bottom: 3px;
@@ -976,5 +1055,27 @@ export default {
976
1055
  &--rtl {
977
1056
  direction: rtl;
978
1057
  }
1058
+
1059
+ &__limit {
1060
+ &-text {
1061
+ position: relative;
1062
+ z-index: 1;
1063
+ width: auto;
1064
+ }
1065
+ &-toggle {
1066
+ pointer-events: auto;
1067
+ &:before {
1068
+ border-color: black transparent transparent !important;
1069
+ }
1070
+ &--close {
1071
+ transform: rotate(180deg);
1072
+ }
1073
+ }
1074
+ .multiselect__tags {
1075
+ display: flex;
1076
+ justify-content: space-between;
1077
+ align-items: center;
1078
+ }
1079
+ }
979
1080
  }
980
1081
  </style>