mirror of
https://github.com/tusen-ai/naive-ui.git
synced 2025-01-18 12:34:25 +08:00
feat(collapse): light theme
This commit is contained in:
parent
d4a3cc71a4
commit
325a96ddf7
@ -38,6 +38,7 @@ import themeable from '../../../mixins/themeable'
|
||||
import hollowoutable from '../../../mixins/hollowoutable'
|
||||
import CheckMark from './CheckMark'
|
||||
import LineMark from './LineMark'
|
||||
import registerable from '../../../mixins/registerable'
|
||||
|
||||
export default {
|
||||
name: 'NCheckbox',
|
||||
@ -53,7 +54,8 @@ export default {
|
||||
mixins: [
|
||||
withapp,
|
||||
themeable,
|
||||
hollowoutable
|
||||
hollowoutable,
|
||||
registerable('NCheckboxGroup', 'collectedCheckboxValues')
|
||||
],
|
||||
model: {
|
||||
prop: 'checked',
|
||||
@ -89,23 +91,6 @@ export default {
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
value (value, oldValue) {
|
||||
if (this.NCheckboxGroup) {
|
||||
this.registerValue(value, oldValue)
|
||||
}
|
||||
}
|
||||
},
|
||||
created () {
|
||||
if (this.NCheckboxGroup) {
|
||||
this.registerValue(this.value)
|
||||
}
|
||||
},
|
||||
beforeDestroy () {
|
||||
if (this.NCheckboxGroup) {
|
||||
this.registerValue(undefined, this.value)
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
registerValue (value = undefined, oldValue = undefined) {
|
||||
if (this.NCheckboxGroup) {
|
||||
|
@ -2,12 +2,15 @@
|
||||
<div
|
||||
class="n-collapse-item"
|
||||
:class="{
|
||||
'n-collapse-item--active': value
|
||||
'n-collapse-item--active': !collapse,
|
||||
}"
|
||||
>
|
||||
<div
|
||||
class="n-collapse-item__title"
|
||||
@click="handleTitleClick"
|
||||
:class="{
|
||||
'n-collapse-item__title--active': !collapse
|
||||
}"
|
||||
@click="handleClick"
|
||||
>
|
||||
<n-icon type="ios-arrow-forward" />{{ title }}
|
||||
</div>
|
||||
@ -18,7 +21,7 @@
|
||||
@leave="handleLeave"
|
||||
>
|
||||
<div
|
||||
v-if="value"
|
||||
v-if="!collapse"
|
||||
ref="contentContainer"
|
||||
class="n-collapse-item__content-wrapper"
|
||||
>
|
||||
@ -35,12 +38,19 @@
|
||||
|
||||
<script>
|
||||
import NIcon from '../../Icon'
|
||||
import registerable from '../../../mixins/registerable'
|
||||
|
||||
export default {
|
||||
name: 'NCollapseItem',
|
||||
components: {
|
||||
NIcon
|
||||
},
|
||||
mixins: [registerable('NCollapse', 'collectedItemNames', 'name')],
|
||||
inject: {
|
||||
NCollapse: {
|
||||
default: null
|
||||
}
|
||||
},
|
||||
props: {
|
||||
title: {
|
||||
type: String,
|
||||
@ -55,6 +65,14 @@ export default {
|
||||
default: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
collapse () {
|
||||
if (this.NCollapse && Array.isArray(this.NCollapse.value)) {
|
||||
return !~this.NCollapse.value.findIndex(name => name === this.name)
|
||||
}
|
||||
return true
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleEnter () {
|
||||
this.$refs.contentContainer.style.maxHeight = 0
|
||||
@ -69,9 +87,10 @@ export default {
|
||||
this.$el.getBoundingClientRect()
|
||||
this.$refs.contentContainer.style.maxHeight = 0
|
||||
},
|
||||
handleTitleClick () {
|
||||
const newValue = !this.value
|
||||
this.$emit('input', newValue, this.name)
|
||||
handleClick () {
|
||||
if (this.NCollapse) {
|
||||
this.NCollapse.toggleItem(this.collapse, this.name)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,32 +1,19 @@
|
||||
<script>
|
||||
function mapSlot (slot, activeNames, isAccordion, handleInput, self) {
|
||||
const names = []
|
||||
for (const vNode of slot) {
|
||||
if (vNode.componentOptions && (vNode.componentOptions.tag === 'NCollapseItem' || vNode.componentOptions.tag === 'n-collapse-item')) {
|
||||
const name = vNode.componentOptions.propsData.name
|
||||
names.push(name)
|
||||
vNode.componentOptions.listeners = {
|
||||
...vNode.componentOptions.listeners,
|
||||
input: handleInput
|
||||
}
|
||||
if (isAccordion) {
|
||||
console.log(name, activeNames)
|
||||
if (name === activeNames) {
|
||||
vNode.componentOptions.propsData.value = true
|
||||
}
|
||||
} else {
|
||||
if (Array.isArray(activeNames) && activeNames.includes(name)) {
|
||||
vNode.componentOptions.propsData.value = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
self.memorizedNames = names
|
||||
return slot
|
||||
}
|
||||
import intersection from 'lodash/intersection'
|
||||
import withapp from '../../../mixins/withapp'
|
||||
import themeable from '../../../mixins/themeable'
|
||||
|
||||
export default {
|
||||
name: 'NCollapse',
|
||||
provide () {
|
||||
return {
|
||||
NCollapse: this
|
||||
}
|
||||
},
|
||||
mixins: [
|
||||
withapp,
|
||||
themeable
|
||||
],
|
||||
props: {
|
||||
value: {
|
||||
type: [Array, String],
|
||||
@ -39,22 +26,22 @@ export default {
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
memorizedNames: null
|
||||
collectedItemNames: []
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleInput (value, name) {
|
||||
toggleItem (collapse, name) {
|
||||
if (this.accordion) {
|
||||
if (value) {
|
||||
this.$emit('input', name)
|
||||
if (collapse) {
|
||||
this.$emit('input', [name])
|
||||
} else {
|
||||
this.$emit('input', null)
|
||||
this.$emit('input', [])
|
||||
}
|
||||
} else {
|
||||
if (!Array.isArray(this.value)) {
|
||||
this.$emit('input', [name])
|
||||
} else {
|
||||
const activeNames = Array.from(new Set(this.value.filter(v => this.memorizedNames.includes(v))))
|
||||
const activeNames = intersection(this.value, this.collectedItemNames)
|
||||
const index = activeNames.findIndex(activeName => name === activeName)
|
||||
if (~index) {
|
||||
activeNames.splice(index, 1)
|
||||
@ -69,8 +56,11 @@ export default {
|
||||
},
|
||||
render (h) {
|
||||
return h('div', {
|
||||
staticClass: 'n-collapse'
|
||||
}, mapSlot(this.$slots.default, this.value, this.accordion, this.handleInput, this))
|
||||
staticClass: 'n-collapse',
|
||||
class: {
|
||||
[`n-${this.synthesizedTheme}-theme`]: this.synthesizedTheme
|
||||
}
|
||||
}, this.$slots.default)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
35
packages/mixins/registerable.js
Normal file
35
packages/mixins/registerable.js
Normal file
@ -0,0 +1,35 @@
|
||||
export default function (
|
||||
inject,
|
||||
collectionProperty,
|
||||
registerProperty = 'value'
|
||||
) {
|
||||
return {
|
||||
watch: {
|
||||
[registerProperty]: function (value, oldValue) {
|
||||
if (this[inject]) {
|
||||
this.registerValue(value, oldValue)
|
||||
}
|
||||
}
|
||||
},
|
||||
created () {
|
||||
if (this[inject]) {
|
||||
this.registerValue(this[registerProperty])
|
||||
}
|
||||
},
|
||||
beforeDestroy () {
|
||||
if (this[inject]) {
|
||||
this.registerValue(undefined, this[registerProperty])
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
registerValue (value = undefined, oldValue = undefined) {
|
||||
if (this[inject]) {
|
||||
const values = new Set(this[inject][collectionProperty])
|
||||
if (oldValue !== undefined) values.delete(oldValue)
|
||||
if (value !== undefined) values.add(value)
|
||||
this[inject][collectionProperty] = Array.from(values)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -5,48 +5,66 @@
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
@include b(collapse-item) {
|
||||
overflow: hidden;
|
||||
font-size: 14px;
|
||||
border-bottom: 1px solid rgba(255, 255, 255, 0.2);
|
||||
padding-top: 16px;
|
||||
&:first-child {
|
||||
padding-top: 0px;
|
||||
}
|
||||
&:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
@include b(collapse-item) {
|
||||
margin-left: 18px;
|
||||
}
|
||||
&.n-collapse-item--active {
|
||||
.n-collapse-item__title {
|
||||
.n-icon {
|
||||
transform: rotate(90deg);
|
||||
@include themes-mixin {
|
||||
@include b(collapse) {
|
||||
@include b(collapse-item) {
|
||||
@include once {
|
||||
overflow: hidden;
|
||||
font-size: 14px;
|
||||
transition: border-color .3s $default-cubic-bezier;
|
||||
margin-top: 16px;
|
||||
&:first-child {
|
||||
margin-top: 0px;
|
||||
}
|
||||
&:first-child > {
|
||||
@include e(title) {
|
||||
padding-top: 0px;
|
||||
}
|
||||
}
|
||||
@include b(collapse-item) {
|
||||
margin-left: 32px;
|
||||
}
|
||||
@include e(content-wrapper) {
|
||||
@include fade-in-height-expand-transition($duration: .15s);
|
||||
overflow: hidden;
|
||||
}
|
||||
@include m(active) {
|
||||
@include e(title) {
|
||||
@include m(active) {
|
||||
@include b(icon) {
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
&:not(:first-child) {
|
||||
border-top: 1px solid $--n-border-color;
|
||||
}
|
||||
@include e(title) {
|
||||
@include once {
|
||||
transition: color .3s $default-cubic-bezier;
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
margin-left: 18px;
|
||||
padding: 16px 0 0 0;
|
||||
@include b(icon) {
|
||||
transition: transform .15s $default-cubic-bezier;
|
||||
font-size: 16px;
|
||||
position: absolute;
|
||||
left: -18px;
|
||||
bottom: 0px;
|
||||
}
|
||||
}
|
||||
color: $--n-text-color;
|
||||
}
|
||||
@include e(content-inner) {
|
||||
@include once {
|
||||
transition: color .3s $default-cubic-bezier;
|
||||
padding-top: 16px;
|
||||
}
|
||||
color: $--n-secondary-text-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
.n-collapse-item__title {
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
.n-icon {
|
||||
transition: transform .3s $default-cubic-bezier;
|
||||
font-size: 16px;
|
||||
position: absolute;
|
||||
left: -18px;
|
||||
bottom: 0;
|
||||
}
|
||||
color: rgba(233, 233, 236, 1);
|
||||
margin-left: 18px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
.n-collapse-item__content-wrapper {
|
||||
@include fade-in-height-expand-transition($duration: .15s);
|
||||
overflow: hidden;
|
||||
// transition: max-height .3s $default-cubic-bezier;
|
||||
}
|
||||
.n-collapse-item__content-inner {
|
||||
color: rgba(233, 233, 236, .7);
|
||||
padding-bottom: 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -154,9 +154,6 @@ $layout-nav-height: 64px;
|
||||
}
|
||||
}
|
||||
@include m(is-group-header) {
|
||||
// span {
|
||||
// transition: color 0.3s $default-cubic-bezier;
|
||||
// }
|
||||
&::after { // down arrow
|
||||
content: '';
|
||||
height: 6px;
|
||||
@ -170,11 +167,11 @@ $layout-nav-height: 64px;
|
||||
transform-origin: 25% 25%;
|
||||
transition: transform 0.3s $default-cubic-bezier, opacity 0.3s $default-cubic-bezier;
|
||||
}
|
||||
@include m(group-item-is-choosed) {
|
||||
span {
|
||||
color: #63E2B7;
|
||||
}
|
||||
}
|
||||
// @include m(group-item-is-choosed) {
|
||||
// span {
|
||||
// color: #63E2B7;
|
||||
// }
|
||||
// }
|
||||
@include m(collapsed) {
|
||||
&::after {
|
||||
transform: rotate(225deg) ;
|
||||
|
@ -361,11 +361,11 @@ $default-cubic-bezier: cubic-bezier(.4, 0, .2, 1);
|
||||
}
|
||||
&.#{$namespace}-#{$block}-leave-active {
|
||||
overflow: hidden;
|
||||
transition: max-height $duration $default-cubic-bezier, opacity $duration $slow-out-cubic-bezier;
|
||||
transition: max-height $duration $default-cubic-bezier, opacity $duration $fast-in-cubic-bezier;
|
||||
}
|
||||
&.#{$namespace}-#{$block}-enter-active {
|
||||
overflow: hidden;
|
||||
transition: max-height $duration $default-cubic-bezier, opacity $duration $fast-in-cubic-bezier;
|
||||
transition: max-height $duration $default-cubic-bezier, opacity $duration $slow-out-cubic-bezier;
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user