Skip to content

Commit 4799c7b

Browse files
author
Ilya Kitayev
committed
Merge branch 'dev' into 'master'
#54 - feat: table scroll wrapper, feat: inherit tb-column slots markup to default hidden slot See merge request awes-io/table-builder!32
2 parents 8812793 + 969695c commit 4799c7b

File tree

7 files changed

+198
-110
lines changed

7 files changed

+198
-110
lines changed

dist/css/main.css

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/js/main.js

+2-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/js/main.legacy.js

+2-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

examples/index.html

+10-9
Original file line numberDiff line numberDiff line change
@@ -57,30 +57,31 @@ <h2 style="padding: 1rem; background-color: lightgray">
5757
</tb-column>
5858
<tb-column name="phone" class="int-table__nowrap" media="tablet, desktop">
5959
<template slot-scope="col">
60-
<a :href="'tel:' + $get(col.data.phones[0], 'phone_link')">
61-
{{ $get(col.data.phones[0], 'phone_formatted') }}
60+
<a v-if="col.data.phones[0]"
61+
:href="'tel:' + $get(col.data.phones[0], 'phone_link')">
62+
{{ $get(col.data, 'phones[0].phone_formatted') }}
6263
</a>
6364
</template>
6465
</tb-column>
65-
<tb-column name="email" sort="mail|mail_down" class="int-table__nowrap" media="desktop">
66+
<tb-column name="email" sort="mail|mail_down" class="int-table__nowrap" media="tablet, desktop">
6667
<template slot-scope="col">
6768
<a :href="'mailto:' + col.data.email">{{ col.data.email }}</a>
6869
</template>
6970
</tb-column>
7071

71-
<template slot="hidden" slot-scope="h">
72+
<!-- <template slot="hidden" slot-scope="h">
7273
<ul>
7374
<li v-if="h.matchedMedia.includes('mobile')">
74-
<strong>{{ h.rowData.profile_manager.position }}</strong>
75+
<strong>{{ $get( h.data, 'profile_manager.position') }}</strong>
7576
</li>
76-
<li v-if="h.rowData.phones.length">
77-
<a :href="'tel:' + h.rowData.phones[0].phone_link">
78-
{{ h.rowData.phones[0].phone_formatted }}
77+
<li v-if="$get(h.data, 'phones', []).length">
78+
<a :href="'tel:' + $get(h.data, 'phones[0].phone_link')">
79+
{{ $get( h.data, 'phones[0].phone_formatted') }}
7980
</a>
8081
</li>
8182
<li><a :href="'mailto:' + h.data.email">{{ h.data.email }}</a></li>
8283
</ul>
83-
</template>
84+
</template> -->
8485

8586
<template slot="footer">
8687
<div style="padding: 1rem; background-color: lightgray">

resources/css/main.styl

+53-38
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,3 @@
1-
flex-version = flex
2-
support-for-ie = false
3-
vendor-prefixes = official
4-
51
@keyframes rotate
62
from
73
transform: none
@@ -10,43 +6,43 @@ vendor-prefixes = official
106

117

128
.int-table
13-
position: relative
14-
15-
&.is-loading
16-
.int-table
17-
&__table,
18-
&__list,
19-
&__no-data
20-
opacity: .5
21-
user-select: none
22-
pointer-events: none
23-
24-
&__loader
25-
position: absolute
26-
z-index: 2
27-
top: 50%
28-
left: 50%
29-
transform: translate(-50%, -50%)
30-
padding: 1rem
31-
padding-left: 40px
32-
background-color: lightgray
33-
34-
&:before
35-
content: ''
36-
display: block
37-
size 20px
38-
position: absolute
39-
left: 10px
40-
top: 50%
41-
margin-top: -10px
42-
border-left: 2px solid currentColor
43-
border-top: 2px solid currentColor
44-
border-radius: 50%
45-
animation rotate 1s linear infinite
9+
// position: relative
10+
11+
// &.is-loading
12+
// .int-table
13+
// &__table,
14+
// &__list,
15+
// &__no-data
16+
// opacity: .5
17+
// user-select: none
18+
// pointer-events: none
19+
20+
// &__loader
21+
// position: absolute
22+
// z-index: 2
23+
// top: 50%
24+
// left: 50%
25+
// transform: translate(-50%, -50%)
26+
// padding: 1rem
27+
// padding-left: 40px
28+
// background-color: lightgray
29+
30+
// &:before
31+
// content: ''
32+
// display: block
33+
// size 20px
34+
// position: absolute
35+
// left: 10px
36+
// top: 50%
37+
// margin-top: -10px
38+
// border-left: 2px solid currentColor
39+
// border-top: 2px solid currentColor
40+
// border-radius: 50%
41+
// animation rotate 1s linear infinite
4642

4743

4844
&__table
49-
width: 100%
45+
width 100%
5046
border-collapse: collapse
5147

5248
thead td,
@@ -57,6 +53,10 @@ vendor-prefixes = official
5753
tbody td
5854
padding: .5em
5955
border-bottom: 1px solid
56+
57+
tr:hover
58+
background gray
59+
color white
6060

6161
&__no-data
6262
display: flex
@@ -103,6 +103,21 @@ vendor-prefixes = official
103103

104104
&-name
105105
text-transform: capitalize
106+
107+
&__overflow
108+
overflow-x auto
109+
max-width 100%
110+
position relative
111+
background:
112+
linear-gradient(90deg, white 16px, rgba(255,255,255,0)),
113+
linear-gradient(90deg, rgba(255,255,255,0), white 16px) 100% 0,
114+
radial-gradient(farthest-side at 0 50%, rgba(0,0,0,.2), rgba(0,0,0,0)),
115+
radial-gradient(farthest-side at 100% 50%, rgba(0,0,0,.2), rgba(0,0,0,0)) 100% 0;
116+
background-repeat no-repeat
117+
background-color white
118+
background-size 48px 100%, 48px 100%, 16px 100%, 16px 100%
119+
background-attachment local, local, scroll, scroll
120+
106121

107122
.pager
108123
margin-top: 30px

resources/vue/table-builder.vue

+68-58
Original file line numberDiff line numberDiff line change
@@ -36,62 +36,67 @@
3636

3737

3838
<!-- table -->
39-
<table
40-
v-if="tableData && hasColumns"
41-
class="int-table__table"
42-
>
43-
<thead>
44-
<tr>
45-
<th v-for="({ label, sort }, i) in columnsHead" :key="i">
46-
<tb-sort-button
47-
v-if="sort"
48-
v-bind="sort"
49-
>
50-
{{ label }}
51-
</tb-sort-button>
52-
<template v-else>{{ label }}</template>
53-
</th>
54-
<th v-if="hiddenOptions && hiddenOptions.length"></th>
55-
</tr>
56-
</thead>
57-
<tbody>
58-
<template v-for="(rowData, i) in tableData">
59-
<tb-row
60-
:key="i + '-row'"
61-
:tableOptions="shownOptions"
62-
:data="rowData"
63-
:index="i"
64-
:active="activeItem === i"
65-
:url="rowUrl"
66-
:matchedMedia="matchedMedia"
67-
:showToggler="!!hiddenColumnData"
68-
@setActive="setActiveItem"
69-
@click="rowClick"
70-
ref="tbRows"
71-
></tb-row>
72-
<tr class="int-table__hidden"
73-
v-if="hiddenColumnData"
74-
v-show="activeItem === i"
75-
:key="i + '-hidden-row'">
76-
<td :colspan="shownOptions.length + 1">
77-
<slot
78-
name="hidden"
79-
:data="rowData"
80-
:hiddenData="hiddenColumnData[i]"
81-
:matchedMedia="matchedMedia"
82-
:index="i"
39+
<div class="int-table__overflow">
40+
<table
41+
v-if="tableData && hasColumns"
42+
class="int-table__table"
43+
>
44+
<thead>
45+
<tr>
46+
<th v-for="({ label, sort }, i) in columnsHead" :key="i">
47+
<tb-sort-button
48+
v-if="sort"
49+
v-bind="sort"
8350
>
84-
<ul>
85-
<li v-for="(option, j) in hiddenColumnData[i]" :key="j + '-hidden'">
86-
{{ option }}
87-
</li>
88-
</ul>
89-
</slot>
90-
</td>
91-
</tr>
92-
</template>
93-
</tbody>
94-
</table>
51+
{{ label }}
52+
</tb-sort-button>
53+
<template v-else>{{ label }}</template>
54+
</th>
55+
<th v-if="hiddenOptions && hiddenOptions.length"></th>
56+
</tr>
57+
</thead>
58+
<tbody>
59+
<template v-for="(rowData, i) in tableData">
60+
<tb-row
61+
:key="i + '-row'"
62+
:tableOptions="shownOptions"
63+
:data="rowData"
64+
:index="i"
65+
:active="activeItem === i"
66+
:url="rowUrl"
67+
:matchedMedia="matchedMedia"
68+
:showToggler="!!hiddenColumnData"
69+
@setActive="setActiveItem"
70+
@click="rowClick"
71+
ref="tbRows"
72+
></tb-row>
73+
<tr class="int-table__hidden"
74+
v-if="hiddenColumnData"
75+
v-show="activeItem === i"
76+
:key="i + '-hidden-row'">
77+
<td :colspan="shownOptions.length + 1">
78+
<slot
79+
name="hidden"
80+
:data="rowData"
81+
:hiddenData="hiddenColumnData[i]"
82+
:matchedMedia="matchedMedia"
83+
:index="i"
84+
>
85+
<tb-hidden-items
86+
:hiddenOptions="hiddenOptions"
87+
:data="rowData"
88+
:index="i"
89+
:active="activeItem === i"
90+
:matchedMedia="matchedMedia"
91+
>
92+
</tb-hidden-items>
93+
</slot>
94+
</td>
95+
</tr>
96+
</template>
97+
</tbody>
98+
</table>
99+
</div>
95100

96101
<!-- footer slot -->
97102
<slot name="footer"></slot>
@@ -103,6 +108,7 @@ import { ucFirst, trimStr } from '../js/modules/fp.js'
103108
import mediaQueriesMixin from '../js/mixins/media-queries.js'
104109
import configMixin from '../js/mixins/config.js'
105110
import tbRow from './tb-row.vue'
111+
import tbHiddenItems from './tb-hidden-items.vue'
106112
import tbSortButton from './tb-sort-button.vue'
107113
108114
export default {
@@ -111,7 +117,7 @@ export default {
111117
112118
mixins: [ mediaQueriesMixin, configMixin ],
113119
114-
components: { tbRow, tbSortButton },
120+
components: { tbRow, tbHiddenItems, tbSortButton },
115121
116122
117123
props: {
@@ -184,7 +190,11 @@ export default {
184190
hiddenOptions() {
185191
return this.tableOptions && this.tableOptions.filter( item => {
186192
if ( item.media && ! this._checkMediaMatch(item.media) ) return true
187-
}).map( item => item.name )
193+
})/*.map( item => item.name )*/
194+
},
195+
196+
hiddenOptionsNames() {
197+
return this.hiddenOptions && this.hiddenOptions.map( item => item.name )
188198
},
189199
190200
hiddenColumnData() {
@@ -193,7 +203,7 @@ export default {
193203
if ( ! row ) return
194204
let hiddenData = {}
195205
Object.keys(row)
196-
.filter( key => this.hiddenOptions.includes(key) )
206+
.filter( key => this.hiddenOptionsNames.includes(key) )
197207
.forEach( key => { hiddenData[key] = row[key] })
198208
return hiddenData
199209
})

resources/vue/tb-hidden-items.vue

+62
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
<script>
2+
function getItem(props, option) {
3+
return option.scopedSlots ?
4+
option.scopedSlots({
5+
data: props.data,
6+
index: props.index,
7+
active: props.active,
8+
matchedMedia: props.matchedMedia
9+
}) :
10+
props.data[option.name]
11+
}
12+
13+
function isEmpty(item) {
14+
return Array.isArray(item) ? item.every(isEmpty) : item.isComment
15+
}
16+
17+
export default {
18+
19+
name: 'tb-row-hidden',
20+
21+
functional: true,
22+
23+
props: {
24+
25+
data: {
26+
type: Object,
27+
required: true
28+
},
29+
30+
hiddenOptions: {
31+
type: Array,
32+
required: true
33+
},
34+
35+
index: {
36+
type: Number,
37+
required: true
38+
},
39+
40+
active: {
41+
type: Boolean,
42+
default: false
43+
},
44+
45+
matchedMedia: Array,
46+
},
47+
48+
render(h, ctx) {
49+
50+
const { props } = ctx
51+
52+
const items = props.hiddenOptions
53+
.map( option => getItem(props, option) )
54+
.filter( item => ! isEmpty(item) )
55+
56+
return h('ul', { staticClass: 'int-table__hidden-items' }, items.map( (item, i) => {
57+
return h('li', { staticClass: 'int-table__hidden-item', key: i }, item)
58+
})
59+
)
60+
}
61+
}
62+
</script>

0 commit comments

Comments
 (0)