Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 969695c

Browse files
committed
#54 - feat: table scroll wrapper, feat: inherit tb-column slots markup to default hidden slot
1 parent 355c62d commit 969695c

File tree

7 files changed

+198
-110
lines changed

7 files changed

+198
-110
lines changed

‎dist/css/main.css‎

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎dist/js/main.js‎

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎dist/js/main.legacy.js‎

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎examples/index.html‎

Lines changed: 10 additions & 9 deletions
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‎

Lines changed: 53 additions & 38 deletions
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
theadtd,
@@ -57,6 +53,10 @@ vendor-prefixes = official
5753
tbodytd
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‎

Lines changed: 68 additions & 58 deletions
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‎

Lines changed: 62 additions & 0 deletions
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)

AltStyle によって変換されたページ (->オリジナル) /