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 +2 -0
- package/package.json +1 -1
- package/src/patterns/McStack/McStack.vue +75 -53
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,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:
|
|
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.
|
|
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.
|
|
61
|
-
this.
|
|
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.
|
|
67
|
+
this.setFixedChildren(this.limit)
|
|
68
68
|
}
|
|
69
|
+
this.loaded = true
|
|
69
70
|
},
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
this.
|
|
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
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
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
|
-
|
|
94
|
-
this.
|
|
95
|
-
|
|
96
|
-
this.
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
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
|
}
|