mirror of
https://github.com/Hopiu/vue-material.git
synced 2026-05-16 11:13:12 +00:00
recreate list item
This commit is contained in:
parent
a4697bc9f6
commit
f0b9d1909f
13 changed files with 528 additions and 235 deletions
|
|
@ -957,15 +957,7 @@
|
|||
}
|
||||
|
||||
.custom-list {
|
||||
.md-list-action {
|
||||
position: absolute;
|
||||
top: 8px;
|
||||
right: 16px;
|
||||
pointer-events: auto;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.md-icon {
|
||||
.md-icon:not(.md-primary) {
|
||||
color: rgba(#000, .26);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -161,6 +161,7 @@ $button-icon-size: 40px;
|
|||
&[disabled] {
|
||||
color: rgba(#000, .26);
|
||||
cursor: default;
|
||||
pointer-events: none;
|
||||
|
||||
&.md-raised,
|
||||
&.md-fab {
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
import mdList from './mdList.vue';
|
||||
import mdListItem from './mdListItem.vue';
|
||||
import mdListItem from './mdListItem.js';
|
||||
import mdListExpand from './mdListExpand.vue';
|
||||
import mdListTheme from './mdList.theme';
|
||||
|
||||
export default function install(Vue) {
|
||||
Vue.component('md-list', Vue.extend(mdList));
|
||||
Vue.component('md-list-item', Vue.extend(mdListItem));
|
||||
Vue.component('md-list-expand', Vue.extend(mdListExpand));
|
||||
Vue.component('md-list', mdList);
|
||||
Vue.component('md-list-item', mdListItem);
|
||||
Vue.component('md-list-expand', mdListExpand);
|
||||
|
||||
Vue.material.styles.push(mdListTheme);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -114,10 +114,6 @@
|
|||
.md-avatar {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.md-list-item-container {
|
||||
align-items: flex-start;
|
||||
}
|
||||
}
|
||||
|
||||
.md-subheader {
|
||||
|
|
@ -134,6 +130,12 @@
|
|||
.md-list-item {
|
||||
height: auto;
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
|
||||
&.md-disabled {
|
||||
cursor: default;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
&.md-inset {
|
||||
.md-list-item-container {
|
||||
|
|
@ -141,15 +143,44 @@
|
|||
}
|
||||
}
|
||||
|
||||
.md-list-item-holder {
|
||||
.md-button-ghost {
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
z-index: 1;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
.md-button:not(.md-button-ghost):not(.md-list-item-container) {
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
|
||||
.md-icon {
|
||||
position: relative;
|
||||
}
|
||||
}
|
||||
|
||||
.md-list-item-container {
|
||||
min-height: 48px;
|
||||
margin: 0;
|
||||
padding: 0 16px;
|
||||
display: flex;
|
||||
flex-flow: row nowrap;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
flex: 1;
|
||||
position: relative;
|
||||
font-size: 16px;
|
||||
font-weight: 400;
|
||||
text-align: left;
|
||||
text-transform: none;
|
||||
|
||||
> .md-ink-ripple {
|
||||
border-radius: 0;
|
||||
&:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
> .md-icon:first-child {
|
||||
|
|
@ -161,27 +192,14 @@
|
|||
}
|
||||
|
||||
.md-list-action {
|
||||
margin: 0 -2px 0 0;
|
||||
margin: 0 -10px 0 0;
|
||||
|
||||
&:nth-child(3) {
|
||||
margin: 0 -2px 0 16px;
|
||||
margin: 0 -10px 0 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.md-list-item-container {
|
||||
width: 100%;
|
||||
min-height: 48px;
|
||||
margin: 0;
|
||||
padding: 0 16px;
|
||||
position: relative;
|
||||
border-radius: 0;
|
||||
font-size: 16px;
|
||||
font-weight: 400;
|
||||
text-align: left;
|
||||
text-transform: none;
|
||||
}
|
||||
|
||||
.md-divider {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
|
|
@ -216,6 +234,7 @@
|
|||
min-height: 48px;
|
||||
flex-flow: column wrap;
|
||||
overflow: hidden;
|
||||
transform: translate3D(0, 0, 0);
|
||||
|
||||
&:before,
|
||||
&:after {
|
||||
|
|
@ -265,11 +284,6 @@
|
|||
}
|
||||
}
|
||||
|
||||
> .md-list-item-container > .md-list-item-holder {
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.md-expansion-indicator,
|
||||
.md-list-item-container,
|
||||
.md-icon {
|
||||
|
|
@ -299,9 +313,14 @@
|
|||
flex: 1;
|
||||
overflow: hidden;
|
||||
line-height: 1.25em;
|
||||
text-overflow: ellipsis;
|
||||
white-space: normal;
|
||||
|
||||
> * {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
> :nth-child(1) {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,64 +1,5 @@
|
|||
<template>
|
||||
<div class="md-list-expand" :style="styles" :class="classes" ref="expand">
|
||||
<div class="md-list-expand-container">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
height: 0,
|
||||
contentObserver: null,
|
||||
transitionOff: true
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
classes() {
|
||||
return {
|
||||
'md-transition-off': this.transitionOff
|
||||
};
|
||||
},
|
||||
styles() {
|
||||
return {
|
||||
'margin-bottom': this.height
|
||||
};
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
calculatePadding() {
|
||||
window.requestAnimationFrame(() => {
|
||||
this.height = -this.$el.offsetHeight - 48 + 'px';
|
||||
|
||||
window.setTimeout(() => {
|
||||
this.transitionOff = false;
|
||||
});
|
||||
});
|
||||
},
|
||||
recalculateAfterChange() {
|
||||
this.transitionOff = true;
|
||||
this.calculatePadding();
|
||||
},
|
||||
observeChildChanges() {
|
||||
this.contentObserver = new MutationObserver(this.recalculateAfterChange);
|
||||
this.contentObserver.observe(this.$refs.expand, {
|
||||
childList: true,
|
||||
characterData: true,
|
||||
subtree: true
|
||||
});
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.calculatePadding();
|
||||
this.observeChildChanges();
|
||||
window.addEventListener('resize', this.recalculateAfterChange);
|
||||
},
|
||||
beforeDestroy() {
|
||||
if (this.contentObserver) {
|
||||
this.contentObserver.disconnect();
|
||||
}
|
||||
|
||||
window.removeEventListener('resize', this.recalculateAfterChange);
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
|
|||
277
src/components/mdList/mdListItem.js
Normal file
277
src/components/mdList/mdListItem.js
Normal file
|
|
@ -0,0 +1,277 @@
|
|||
/*<template>
|
||||
<li class="md-list-item" :class="classes">
|
||||
<md-button class="md-list-item-container" :href="href" :disabled="disabled" :target="target" v-if="href">
|
||||
<slot></slot>
|
||||
</md-button>
|
||||
|
||||
<slot v-else-if="isRouterLink"></slot>
|
||||
|
||||
<div class="md-list-item-container" v-else>
|
||||
<slot></slot>
|
||||
|
||||
<md-icon class="md-list-expand-indicator" v-if="hasExpand">keyboard_arrow_down</md-icon>
|
||||
</div>
|
||||
|
||||
<md-ink-ripple v-if="isRouterLink" :md-disabled="disabled"></md-ink-ripple>
|
||||
<md-button class="md-button md-button-ghost" @click="hasExpand && toggleExpandList" :disabled="disabled" v-if="!href && !isRouterLink"></md-button>
|
||||
</li>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import MdListItemButton from 'mdListItemButton';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
href: String,
|
||||
target: String,
|
||||
disabled: Boolean
|
||||
},
|
||||
data: () => ({
|
||||
hasExpand: false,
|
||||
isRouterLink: false
|
||||
}),
|
||||
computed: {
|
||||
classes() {
|
||||
return {
|
||||
'md-list-item-expand': this.hasExpand
|
||||
};
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
toggleExpandList() {
|
||||
let target;
|
||||
const recalculateExpand = (element) => {
|
||||
element.$children.some((expand) => {
|
||||
if (expand.$el.classList.contains('md-list-expand')) {
|
||||
expand.calculatePadding();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
this.$parent.$children.some((child) => {
|
||||
var classList = child.$el.classList;
|
||||
|
||||
if (classList.contains('md-list-item-expand') && classList.contains('md-active')) {
|
||||
target = child;
|
||||
classList.remove('md-active');
|
||||
|
||||
recalculateExpand(child);
|
||||
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
if (!target || this.$el !== target.$el) {
|
||||
this.$el.classList.add('md-active');
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.$nextTick(() => {
|
||||
const children = this.$children;
|
||||
const containerClass = 'md-button md-list-item-container';
|
||||
|
||||
if (children) {
|
||||
children.forEach((child) => {
|
||||
if (child.$options && child.$options._componentTag === 'router-link') {
|
||||
child.$el.className = containerClass;
|
||||
child.$vnode.data.attrs.class = containerClass;
|
||||
this.isRouterLink = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
render(createElement) {
|
||||
let containerClass = 'md-button md-list-item-container';
|
||||
let holderClass = 'md-list-item-holder';
|
||||
let slot = this.$slots.default;
|
||||
let componentOptions = slot[0].componentOptions;
|
||||
let expandSlot;
|
||||
let expandSlotIndex;
|
||||
|
||||
let listItemSpec = {
|
||||
staticClass: 'md-list-item',
|
||||
on: {
|
||||
click: ($event) => {
|
||||
this.$emit('click', $event);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let createItemHolder = (content) => {
|
||||
return createElement('div', { staticClass: holderClass }, content);
|
||||
};
|
||||
|
||||
let createRipple = () => {
|
||||
return createElement('md-ink-ripple');
|
||||
};
|
||||
|
||||
let createCompatibleRouterLink = () => {
|
||||
slot[0].data.staticClass = containerClass + ' ' + holderClass;
|
||||
|
||||
return createElement('li', listItemSpec, [...slot, createRipple()]);
|
||||
};
|
||||
|
||||
let prepareExpandList = () => {
|
||||
slot.some((slot, index) => {
|
||||
if (slot.componentOptions && slot.componentOptions.tag === 'md-list-expand') {
|
||||
expandSlot = slot;
|
||||
expandSlotIndex = index;
|
||||
|
||||
return true;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
let createExpandIndicator = () => {
|
||||
return createElement('md-icon', {
|
||||
staticClass: 'md-list-expand-indicator'
|
||||
}, 'keyboard_arrow_down');
|
||||
};
|
||||
|
||||
let recalculateExpand = (element) => {
|
||||
element.$children.some((expand) => {
|
||||
if (expand.$el.classList.contains('md-list-expand')) {
|
||||
expand.calculatePadding();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
let handleExpandClick = (scope) => {
|
||||
let target;
|
||||
|
||||
scope.$parent.$children.some((child) => {
|
||||
var classList = child.$el.classList;
|
||||
|
||||
if (classList.contains('md-list-item-expand') && classList.contains('md-active')) {
|
||||
target = child;
|
||||
classList.remove('md-active');
|
||||
|
||||
recalculateExpand(child);
|
||||
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
if (!target || scope.$el !== target.$el) {
|
||||
scope.$el.classList.add('md-active');
|
||||
}
|
||||
};
|
||||
|
||||
let createExpandElement = () => {
|
||||
slot.splice(expandSlotIndex, 1);
|
||||
slot.push(createExpandIndicator());
|
||||
|
||||
return createElement('button', {
|
||||
staticClass: containerClass,
|
||||
on: {
|
||||
click: () => {
|
||||
handleExpandClick(this);
|
||||
this.$emit('click');
|
||||
}
|
||||
}
|
||||
}, [createItemHolder(slot), createRipple()]);
|
||||
};
|
||||
|
||||
let createExpandList = () => {
|
||||
listItemSpec.staticClass += ' md-list-item-expand';
|
||||
|
||||
return createElement('li', listItemSpec, [createExpandElement(), expandSlot]);
|
||||
};
|
||||
|
||||
if (componentOptions && componentOptions.tag === 'router-link') {
|
||||
return createCompatibleRouterLink();
|
||||
}
|
||||
|
||||
prepareExpandList();
|
||||
|
||||
if (expandSlot) {
|
||||
return createExpandList();
|
||||
}
|
||||
|
||||
let buttonSpec = createElement('md-button', {
|
||||
staticClass: containerClass,
|
||||
attrs: {
|
||||
target: this.target,
|
||||
href: this.href,
|
||||
disabled: this.disabled
|
||||
}
|
||||
}, [createItemHolder(slot)]);
|
||||
|
||||
if (this.target) {
|
||||
buttonSpec.data.attrs.rel = 'noopener';
|
||||
}
|
||||
|
||||
return createElement('li', listItemSpec, [buttonSpec]);
|
||||
}
|
||||
};
|
||||
</script>*/
|
||||
|
||||
import MdListItemButton from './mdListItemButton';
|
||||
import MdListItemLink from './mdListItemLink';
|
||||
import MdListItemRouter from './mdListItemRouter';
|
||||
import mdListItemExpand from './mdListItemExpand';
|
||||
import MdListItemDefault from './mdListItemDefault';
|
||||
|
||||
export default {
|
||||
functional: true,
|
||||
props: {
|
||||
href: String,
|
||||
disabled: Boolean
|
||||
},
|
||||
render(createElement, { children, data, props }) {
|
||||
const getItemComponent = () => {
|
||||
const nativeOn = data.nativeOn;
|
||||
const interactionEvents = [
|
||||
'contextmenu',
|
||||
'dblclick',
|
||||
'dragend',
|
||||
'mousedown',
|
||||
'touchstart',
|
||||
'click'
|
||||
];
|
||||
let childrenCount = children.length;
|
||||
|
||||
if (props.href) {
|
||||
return MdListItemLink;
|
||||
}
|
||||
|
||||
if (nativeOn) {
|
||||
let counter = interactionEvents.length;
|
||||
|
||||
while (counter--) {
|
||||
if (nativeOn[interactionEvents[counter]]) {
|
||||
return MdListItemButton;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while (childrenCount--) {
|
||||
const options = children[childrenCount].componentOptions;
|
||||
|
||||
if (options) {
|
||||
if (options.tag === 'md-list-expand') {
|
||||
const expandComponent = children[childrenCount];
|
||||
|
||||
data.scopedSlots = {
|
||||
expand: () => expandComponent
|
||||
};
|
||||
|
||||
children.splice(childrenCount, 1);
|
||||
|
||||
return mdListItemExpand;
|
||||
} else if (options.tag === 'router-link') {
|
||||
children[childrenCount].data.staticClass = 'md-list-item-container md-button';
|
||||
|
||||
return MdListItemRouter;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return MdListItemDefault;
|
||||
};
|
||||
|
||||
return createElement(getItemComponent(), { props, ...data }, children);
|
||||
}
|
||||
};
|
||||
|
|
@ -1,132 +0,0 @@
|
|||
<script>
|
||||
export default {
|
||||
props: {
|
||||
href: String,
|
||||
target: String,
|
||||
disabled: Boolean
|
||||
},
|
||||
render(createElement) {
|
||||
let containerClass = 'md-button md-list-item-container';
|
||||
let holderClass = 'md-list-item-holder';
|
||||
let slot = this.$slots.default;
|
||||
let componentOptions = slot[0].componentOptions;
|
||||
let expandSlot;
|
||||
let expandSlotIndex;
|
||||
|
||||
let listItemSpec = {
|
||||
staticClass: 'md-list-item',
|
||||
on: {
|
||||
click: ($event) => {
|
||||
this.$emit('click', $event);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let createItemHolder = (content) => {
|
||||
return createElement('div', { staticClass: holderClass }, content);
|
||||
};
|
||||
|
||||
let createRipple = () => {
|
||||
return createElement('md-ink-ripple');
|
||||
};
|
||||
|
||||
let createCompatibleRouterLink = () => {
|
||||
slot[0].data.staticClass = containerClass + ' ' + holderClass;
|
||||
|
||||
return createElement('li', listItemSpec, [...slot, createRipple()]);
|
||||
};
|
||||
|
||||
let prepareExpandList = () => {
|
||||
slot.some((slot, index) => {
|
||||
if (slot.componentOptions && slot.componentOptions.tag === 'md-list-expand') {
|
||||
expandSlot = slot;
|
||||
expandSlotIndex = index;
|
||||
|
||||
return true;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
let createExpandIndicator = () => {
|
||||
return createElement('md-icon', {
|
||||
staticClass: 'md-list-expand-indicator'
|
||||
}, 'keyboard_arrow_down');
|
||||
};
|
||||
|
||||
let recalculateExpand = (element) => {
|
||||
element.$children.some((expand) => {
|
||||
if (expand.$el.classList.contains('md-list-expand')) {
|
||||
expand.calculatePadding();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
let handleExpandClick = (scope) => {
|
||||
let target;
|
||||
|
||||
scope.$parent.$children.some((child) => {
|
||||
var classList = child.$el.classList;
|
||||
|
||||
if (classList.contains('md-list-item-expand') && classList.contains('md-active')) {
|
||||
target = child;
|
||||
classList.remove('md-active');
|
||||
|
||||
recalculateExpand(child);
|
||||
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
if (!target || scope.$el !== target.$el) {
|
||||
scope.$el.classList.add('md-active');
|
||||
}
|
||||
};
|
||||
|
||||
let createExpandElement = () => {
|
||||
slot.splice(expandSlotIndex, 1);
|
||||
slot.push(createExpandIndicator());
|
||||
|
||||
return createElement('button', {
|
||||
staticClass: containerClass,
|
||||
on: {
|
||||
click: () => {
|
||||
handleExpandClick(this);
|
||||
this.$emit('click');
|
||||
}
|
||||
}
|
||||
}, [createItemHolder(slot), createRipple()]);
|
||||
};
|
||||
|
||||
let createExpandList = () => {
|
||||
listItemSpec.staticClass += ' md-list-item-expand';
|
||||
|
||||
return createElement('li', listItemSpec, [createExpandElement(), expandSlot]);
|
||||
};
|
||||
|
||||
if (componentOptions && componentOptions.tag === 'router-link') {
|
||||
return createCompatibleRouterLink();
|
||||
}
|
||||
|
||||
prepareExpandList();
|
||||
|
||||
if (expandSlot) {
|
||||
return createExpandList();
|
||||
}
|
||||
|
||||
let buttonSpec = createElement('md-button', {
|
||||
staticClass: containerClass,
|
||||
attrs: {
|
||||
target: this.target,
|
||||
href: this.href,
|
||||
disabled: this.disabled
|
||||
}
|
||||
}, [createItemHolder(slot)]);
|
||||
|
||||
if (this.target) {
|
||||
buttonSpec.data.attrs.rel = 'noopener';
|
||||
}
|
||||
|
||||
return createElement('li', listItemSpec, [buttonSpec]);
|
||||
}
|
||||
};
|
||||
</script>
|
||||
25
src/components/mdList/mdListItemButton.vue
Normal file
25
src/components/mdList/mdListItemButton.vue
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
<template>
|
||||
<li class="md-list-item" :class="classes">
|
||||
<div class="md-list-item-container md-button">
|
||||
<slot></slot>
|
||||
</div>
|
||||
|
||||
<md-button class="md-button-ghost" :disabled="disabled"></md-button>
|
||||
</li>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'md-list-item',
|
||||
props: {
|
||||
disabled: Boolean
|
||||
},
|
||||
computed: {
|
||||
classes() {
|
||||
return {
|
||||
'md-disabled': this.disabled
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
13
src/components/mdList/mdListItemDefault.vue
Normal file
13
src/components/mdList/mdListItemDefault.vue
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
<template>
|
||||
<li class="md-list-item">
|
||||
<div class="md-list-item-container">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</li>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'md-list-item'
|
||||
};
|
||||
</script>
|
||||
103
src/components/mdList/mdListItemExpand.vue
Normal file
103
src/components/mdList/mdListItemExpand.vue
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
<template>
|
||||
<li class="md-list-item md-list-item-expand" :class="classes">
|
||||
<div class="md-list-item-container md-button">
|
||||
<slot></slot>
|
||||
|
||||
<md-icon class="md-list-expand-indicator">keyboard_arrow_down</md-icon>
|
||||
</div>
|
||||
|
||||
<md-button class="md-button-ghost" @click.native="toggleExpandList" :disabled="disabled"></md-button>
|
||||
|
||||
<div class="md-list-expand" ref="expand" :class="expandClasses" :style="expandStyles">
|
||||
<slot name="expand"></slot>
|
||||
</div>
|
||||
</li>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import getClosestVueParent from '../../core/utils/getClosestVueParent';
|
||||
|
||||
export default {
|
||||
name: 'md-list-item',
|
||||
props: {
|
||||
disabled: Boolean
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
parentList: false,
|
||||
active: false,
|
||||
height: 0,
|
||||
contentObserver: null,
|
||||
transitionOff: true
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
classes() {
|
||||
return {
|
||||
'md-disabled': this.disabled,
|
||||
'md-active': this.active
|
||||
};
|
||||
},
|
||||
expandClasses() {
|
||||
return {
|
||||
'md-transition-off': this.transitionOff
|
||||
};
|
||||
},
|
||||
expandStyles() {
|
||||
return {
|
||||
'margin-bottom': this.height
|
||||
};
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
resetSiblings() {
|
||||
this.parentList.$children.forEach((child) => {
|
||||
if (child.$el !== this.$el && child.$el.classList.contains('md-list-item-expand')) {
|
||||
child.active = false;
|
||||
}
|
||||
});
|
||||
},
|
||||
calculatePadding() {
|
||||
window.requestAnimationFrame(() => {
|
||||
this.height = -this.$el.scrollHeight + 'px';
|
||||
|
||||
window.setTimeout(() => {
|
||||
this.transitionOff = false;
|
||||
});
|
||||
});
|
||||
},
|
||||
toggleExpandList() {
|
||||
this.resetSiblings();
|
||||
this.calculatePadding();
|
||||
this.active = !this.active;
|
||||
},
|
||||
recalculateAfterChange() {
|
||||
this.transitionOff = true;
|
||||
this.calculatePadding();
|
||||
},
|
||||
observeChildChanges() {
|
||||
this.contentObserver = new MutationObserver(this.recalculateAfterChange);
|
||||
this.contentObserver.observe(this.$refs.expand, {
|
||||
childList: true,
|
||||
characterData: true,
|
||||
subtree: true
|
||||
});
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.$nextTick(() => {
|
||||
this.parentList = getClosestVueParent(this.$parent, 'md-list');
|
||||
this.calculatePadding();
|
||||
this.observeChildChanges();
|
||||
window.addEventListener('resize', this.recalculateAfterChange);
|
||||
});
|
||||
},
|
||||
beforeDestroy() {
|
||||
if (this.contentObserver) {
|
||||
this.contentObserver.disconnect();
|
||||
}
|
||||
|
||||
window.removeEventListener('resize', this.recalculateAfterChange);
|
||||
}
|
||||
};
|
||||
</script>
|
||||
27
src/components/mdList/mdListItemLink.vue
Normal file
27
src/components/mdList/mdListItemLink.vue
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
<template>
|
||||
<li class="md-list-item" :class="classes">
|
||||
<a class="md-list-item-container md-button" :href="href" :target="target" :disabled="disabled">
|
||||
<slot />
|
||||
</a>
|
||||
|
||||
<md-ink-ripple :disabled="disabled" />
|
||||
</li>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'md-list-item',
|
||||
props: {
|
||||
href: String,
|
||||
target: Boolean,
|
||||
disabled: Boolean
|
||||
},
|
||||
computed: {
|
||||
classes() {
|
||||
return {
|
||||
'md-disabled': this.disabled
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
22
src/components/mdList/mdListItemRouter.vue
Normal file
22
src/components/mdList/mdListItemRouter.vue
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
<template>
|
||||
<li class="md-list-item" :class="classes" :disabled="disabled">
|
||||
<slot />
|
||||
<md-ink-ripple :disabled="disabled" />
|
||||
</li>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'md-list-item',
|
||||
props: {
|
||||
disabled: Boolean
|
||||
},
|
||||
computed: {
|
||||
classes() {
|
||||
return {
|
||||
'md-disabled': this.disabled
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
@ -27,8 +27,13 @@ body {
|
|||
@extend .md-body-1;
|
||||
}
|
||||
|
||||
[tabindex='-1']:focus {
|
||||
outline: none;
|
||||
|
||||
|
||||
/* Fluid Media
|
||||
========================================================================== */
|
||||
|
||||
ul:not(.md-list) > li + li {
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue