mediacube-ui 0.1.400 → 0.1.401

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,8 @@
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.401](https://github.com/MediaCubeCo/mcui/compare/v0.1.400...v0.1.401) (2025-07-29)
6
+
5
7
  ### [0.1.400](https://github.com/MediaCubeCo/mcui/compare/v0.1.399...v0.1.400) (2025-07-29)
6
8
 
7
9
  ### [0.1.399](https://github.com/MediaCubeCo/mcui/compare/v0.1.398...v0.1.399) (2025-07-28)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mediacube-ui",
3
- "version": "0.1.400",
3
+ "version": "0.1.401",
4
4
  "description": "Design system for Mediacube services",
5
5
  "author": "Mediacube",
6
6
  "private": false,
@@ -1,14 +1,3 @@
1
- <template>
2
- <div ref="stack" class="mc-stack">
3
- <div v-show="loaded" ref="mc-stack-body" class="mc-stack__body">
4
- <slot />
5
- </div>
6
- <div v-if="more" ref="counter" class="mc-stack__counter">
7
- {{ counterText }}
8
- </div>
9
- </div>
10
- </template>
11
-
12
1
  <script>
13
2
  export default {
14
3
  name: 'McStack',
@@ -29,10 +18,14 @@ export default {
29
18
  },
30
19
  },
31
20
  data: () => ({
32
- children: null,
21
+ children: [],
22
+ visible_children: [],
33
23
  more: 0,
34
24
  loaded: false,
35
25
  custom_limit: 0,
26
+ containerWidth: 0,
27
+ counterWidth: 0,
28
+ resizeTimeout: null,
36
29
  }),
37
30
  computed: {
38
31
  classes() {
@@ -47,71 +40,86 @@ export default {
47
40
  counterText() {
48
41
  return `+${this.more}`
49
42
  },
43
+ slotDefaultChildren() {
44
+ return this.$slots.default || []
45
+ },
50
46
  },
51
47
  mounted() {
52
48
  this.init()
53
49
  },
54
50
  beforeDestroy() {
55
- if (this.isAutoLimit) window.removeEventListener('resize', this.calcLimit)
51
+ if (this.isAutoLimit) window.removeEventListener('resize', () => this.throttle(this.setResizeWidth))
56
52
  },
57
53
  methods: {
54
+ throttle(method) {
55
+ clearTimeout(this.resizeTimeout)
56
+ this.resizeTimeout = setTimeout(() => {
57
+ method()
58
+ clearTimeout(this.resizeTimeout)
59
+ }, 100) // 100ms пауза между вызовами
60
+ },
58
61
  init() {
62
+ this.children = this.slotDefaultChildren
59
63
  if (this.isAutoLimit) {
60
- window.addEventListener('resize', this.calcLimit)
61
- this.calcLimit()
62
- // setTimeout из-за случаев, когда элемент рендерится с 0 шириной, а потом она устанавливается динамически
63
- if (!this.$refs.stack?.clientWidth) {
64
- setTimeout(() => this.calcLimit(), 1)
65
- }
64
+ window.addEventListener('resize', this.setResizeWidth)
65
+ this.$nextTick(this.setWidth)
66
66
  } else {
67
- this.toggleChilds(true, this.limit)
67
+ this.setFixedChildren(this.limit)
68
68
  }
69
+ this.loaded = true
69
70
  },
70
- calcLimit(showAll, limit) {
71
- if (showAll) this.toggleChilds()
72
- this.custom_limit = Infinity
73
- let childWidth = 0
74
- // ширина родителя без учета счетчика
75
- const parentWidth = +this.$refs.stack?.clientWidth - (+this.$refs.counter?.clientWidth || 0)
76
- for (let i = 0; i < this.children?.length; i++) {
77
- const elemStyle = window.getComputedStyle(this.children[i])
78
- childWidth += +this.children[i]?.clientWidth + +parseInt(elemStyle.marginRight)
79
- // считаем занимаемую дочерними элементами ширину, если превышает родительскую, то выходим из цикла и ставим лимит
80
- if (childWidth > parentWidth) {
81
- this.custom_limit = i
82
- break
83
- }
84
- }
85
- // Сравниваем переданный лимит с заново выставленным, если они не равны, то ререндерим потомков
86
- if (this.custom_limit !== limit) this.toggleChilds(true, this.custom_limit)
71
+ setFixedChildren(limit) {
72
+ this.visible_children = [...this.children].splice(0, limit)
73
+ this.more = Math.max(this.children.length - limit, 0)
87
74
  },
88
- setStyles(elem, opacity = 1, visibility = 'visible', position = 'relative') {
89
- elem.style.opacity = opacity
90
- elem.style.visibility = visibility
91
- elem.style.position = position
75
+ setWidth() {
76
+ this.containerWidth = this.$refs.stack?.clientWidth
77
+ if (this.containerWidth === 0) setTimeout(() => this.calcVisibleChildren(), 1)
78
+ else this.calcVisibleChildren()
92
79
  },
93
- toggleChilds(hide, limit = 0) {
94
- this.loaded = true
95
- this.more = 0
96
- this.children = this.$refs?.['mc-stack-body']?.children
97
- let elementsLimit = hide ? limit - 1 : this.children.length
98
- for (let i = 0; i < this.children?.length; i++) {
99
- this.setStyles(this.children[i])
100
- if (i > elementsLimit) {
101
- this.setStyles(this.children[i], 0, 'hidden', 'absolute')
102
- this.more++
80
+ setResizeWidth() {
81
+ if (this.containerWidth === this.$refs.stack?.clientWidth)
82
+ return console.warn('mc-stack container width no changed')
83
+ else this.setWidth()
84
+ },
85
+ async calcVisibleChildren() {
86
+ this.containerWidth = this.$refs.stack?.clientWidth
87
+ if (this.containerWidth === 0) return console.warn('mc-stack container have no width')
88
+ this.visible_children = []
89
+ for (let key = 0; key < this.children.length; key++) {
90
+ this.visible_children.push(this.children[key])
91
+
92
+ await this.$nextTick() // ждём DOM
93
+
94
+ const total = [...this.$refs['mc-stack-body'].children].reduce((a, c) => (a += c.offsetWidth + 12), 0) // 12 отступ между элементами
95
+ if (total > this.containerWidth) {
96
+ this.setFixedChildren(key)
97
+ break
103
98
  }
104
99
  }
105
- // Передаем в $nextTick лимит для пересчета, т.к. рендерится counter, который занимает доп место и обрезает элементы
106
- if (hide && this.isAutoLimit) this.$nextTick(() => this.calcLimit(false, limit))
107
100
  },
108
101
  },
102
+ render(h) {
103
+ return h('div', { ref: 'stack', class: `mc-stack` }, [
104
+ h(
105
+ 'div',
106
+ {
107
+ ref: 'mc-stack-body',
108
+ class: 'mc-stack__body',
109
+ directives: [{ name: 'show', value: this.loaded }],
110
+ },
111
+ this.visible_children,
112
+ ),
113
+ this.more ? h('div', { ref: 'counter', class: 'mc-stack__counter' }, [this.counterText]) : null,
114
+ ])
115
+ },
109
116
  }
110
117
  </script>
111
118
 
112
119
  <style lang="scss">
113
120
  @import '../../styles/mixins';
114
121
  @import '../../tokens/font-families';
122
+
115
123
  .mc-stack {
116
124
  $block-name: &;
117
125
 
@@ -121,9 +129,22 @@ export default {
121
129
  align-items: center;
122
130
  flex-wrap: nowrap;
123
131
 
132
+ &__hidden {
133
+ opacity: 0;
134
+ visibility: hidden;
135
+ position: absolute;
136
+ }
137
+
138
+ &__visible {
139
+ opacity: 1;
140
+ visibility: visible;
141
+ position: relative;
142
+ }
143
+
124
144
  &--collapsed {
125
145
  #{$block-name}__body {
126
146
  @include child-indent-right(-$space-200);
147
+
127
148
  > * {
128
149
  border: 2px solid $color-white;
129
150
  }
@@ -137,6 +158,7 @@ export default {
137
158
  flex-wrap: nowrap;
138
159
  flex-direction: row;
139
160
  @include child-indent-right($space-150);
161
+
140
162
  > * {
141
163
  justify-content: center;
142
164
  }