refactor(base-select-menu): use cssr

This commit is contained in:
07akioni 2020-09-03 12:20:19 +08:00
parent 00e4940ecf
commit d3d7f368b9
21 changed files with 562 additions and 186 deletions

View File

@ -19,6 +19,7 @@ action
fallback-option
change-debug
placeholder-debug
menu-debug
```
## V-model
|prop|event|

View File

@ -0,0 +1,98 @@
# Menu Debug
```html
<n-select
debug
v-model="value"
:options="options"
/>
<n-select
v-model="value"
disabled
:options="options"
/>
<n-select
debug
v-model="value1"
multiple
:options="options"
/>
<n-select
v-model="value1"
multiple
disabled
:options="options"
/>
```
```js
export default {
data () {
return {
value: 'song0',
value1: ['song0', 'song1'],
options: [
{
label: "Everybody's Got Something to Hide Except Me and My Monkey",
value: 'song0',
disabled: true
},
{
label: 'Drive My Car',
value: 'song1'
},
{
label: 'Norwegian Wood',
value: 'song2'
},
{
label: 'You Won\'t See',
value: 'song3',
disabled: true
},
{
label: 'Nowhere Man',
value: 'song4'
},
{
label: 'Think For Yourself',
value: 'song5'
},
{
label: 'The Word',
value: 'song6'
},
{
label: 'Michelle',
value: 'song7',
disabled: true
},
{
label: 'What goes on',
value: 'song8'
},
{
label: 'Girl',
value: 'song9'
},
{
label: 'I\'m looking through you',
value: 'song10'
},
{
label: 'In My Life',
value: 'song11'
},
{
label: 'Wait',
value: 'song12'
}
]
}
}
}
```
```css
.n-select {
width: 180px;
margin: 0 12px 8px 0;
}
```

View File

@ -120,10 +120,13 @@ import {
OPTION_TYPE
} from '../../../_utils/component/select'
import formatLength from '../../../_utils/css/formatLength'
import { itemSize } from '../../../_styles-in-js/common.js'
import depx from '../../../_utils/css/depx'
import { createKey } from '../../../_utils/cssr'
import usecssr from '../../../_mixins/usecssr'
import styles from './styles'
export default {
name: 'NBaseSelectMenu',
name: 'BaseSelectMenu',
provide () {
return {
NBaseSelectMenu: this
@ -138,6 +141,12 @@ export default {
RecycleScroller,
render
},
mixins: [
usecssr(styles, {
themeKey: 'theme',
injectCssrProps: true
})
],
props: {
theme: {
type: String,
@ -222,7 +231,7 @@ export default {
return flattenedOptions && flattenedOptions.length === 0
},
itemSize () {
return itemSize[this.size]
return depx(this.cssrProps.$local[createKey('optionHeight', this.size)])
},
pendingOptionValue () {
const pendingWrappedOption = this.pendingWrappedOption

View File

@ -0,0 +1,20 @@
import baseStyle from './themed-base.js'
import sizeStyle from './themed-size'
export default [
{
key: 'theme',
watch: [
'theme'
],
CNode: baseStyle
},
{
key: 'size',
watch: [
'size',
'theme'
],
CNode: sizeStyle
}
]

View File

@ -0,0 +1,133 @@
import { cTB, c, cB, cE, cM, cNotM } from '../../../../_utils/cssr'
export default c([
({ props }) => {
const {
easeInOutCubicBezier
} = props.$base
const {
borderRadius,
color,
boxShadow,
groupHeaderTextColor,
actionDividerColor,
optionTextColorPressed,
optionTextColor,
optionTextColorDisabled,
optionTextColorSelected,
optionOpacityDisabled,
optionCheckColor,
actionTextColor
} = props.$local
return cTB('base-select-menu', {
raw: `
outline: none;
margin-top: 4px;
margin-bottom: 4px;
z-index: 0;
position: relative;
border-radius: ${borderRadius};
transition: ${easeInOutCubicBezier};
overflow: hidden;
background-color: ${color};
box-shadow: ${boxShadow};
`
}, [
cB('base-select-menu-option-wrapper', {
position: 'relative',
width: '100%'
}),
cE('action', {
padding: '8px 14px',
fontSize: '14px',
transition: `
color .3s ${easeInOutCubicBezier},
border-color .3s ${easeInOutCubicBezier}
`,
borderTop: `1px solid ${actionDividerColor}`,
color: actionTextColor
}),
cB('base-select-group-header', {
cursor: 'default',
padding: '0 14px',
color: groupHeaderTextColor
}),
cB('base-select-option', {
raw: `
cursor: pointer;
position: relative;
padding: 0 14px;
white-space: nowrap;
transition:
color .3s ${easeInOutCubicBezier},
opacity .3s ${easeInOutCubicBezier};
text-overflow: ellipsis;
overflow: hidden;
box-sizing: border-box;
color: ${optionTextColor};
opacity: 1;
`
}, [
c('&:active', {
color: optionTextColorPressed
}),
cM('grouped', {
padding: '0 21px'
}),
cM('selected', {
color: optionTextColorSelected
}),
cM('disabled', {
cursor: 'not-allowed'
}, [
cNotM('selected', {
color: optionTextColorDisabled
}),
cM('selected', {
opacity: optionOpacityDisabled
})
])
]),
cM('no-tracking-rect', [
cB('base-select-option', [
cNotM('disabled', [
c('&:hover', {
color: optionTextColorSelected
})
])
])
]),
cM('multiple', [
cB('base-select-option', {
position: 'relative',
transition: `color .3s ${easeInOutCubicBezier}`,
paddingRight: '28px'
}, [
cM('selected', [
c('&::after', {
opacity: 1,
transform: 'rotate(45deg) scale(1)'
})
]),
c('&::after', {
raw: `
content: '';
height: 6px;
width: 3px;
position: absolute;
right: 14px;
transform: rotate(45deg) scale(.5);
top: calc(50% - 4px);
opacity: 0;
transition:
transform .3s ${easeInOutCubicBezier},
opacity .3s ${easeInOutCubicBezier};
border-right: 1px solid ${optionCheckColor};
border-bottom: 1px solid ${optionCheckColor};
`
})
])
])
])
}
])

View File

@ -0,0 +1,43 @@
import { cTB, c, cB, cM, createKey } from '../../../../_utils/cssr'
import depx from '../../../../_utils/css/depx'
import pxfy from '../../../../_utils/css/pxfy'
export default c([
({ props }) => {
const size = props.$instance.size
const fontSize = props.$local[createKey('optionFontSize', size)]
const optionHeight = props.$local[createKey('optionHeight', size)]
const groupHeaderFontSize = pxfy(depx(fontSize) - 2)
const menuHeight = pxfy(depx(optionHeight) * 7.6)
return cTB('base-select-menu', [
cM(size + '-size', [
cB('virtual-scroller', {
raw: `
height: 100%;
max-height: ${menuHeight};
scrollbar-width: none;
-moz-scrollbar-width: none;
`
}, [
c('&::-webkit-scrollbar', {
width: 0,
height: 0
})
]),
cB('scrollbar-container', {
maxHeight: menuHeight
}),
cB('base-select-option', {
height: optionHeight,
lineHeight: optionHeight,
fontSize: fontSize
}),
cB('base-select-group-header', {
height: optionHeight,
lineHeight: optionHeight,
fontSize: groupHeaderFontSize
})
])
])
}
])

View File

@ -0,0 +1,10 @@
export default {
optionFontSizeSmall: '14px',
optionFontSizeMedium: '14px',
optionFontSizeLarge: '15px',
optionFontSizeHuge: '16px',
optionHeightSmall: '28px',
optionHeightMedium: '34px',
optionHeightLarge: '40px',
optionHeightHuge: '48px'
}

View File

@ -0,0 +1,24 @@
import create from '../../../styles/_utils/create-component-base'
import commonVariables from './_common'
export default create({
name: 'BaseSelectMenu',
theme: 'dark',
getDerivedVariables ({ base, derived }) {
return {
...commonVariables,
borderRadius: base.borderRadius,
color: derived.popoverBackgroundColor,
boxShadow: derived.popoverBoxShadow,
groupHeaderTextColor: derived.tertiaryTextOverlayColor,
actionDividerColor: derived.dividerOverlayColor,
optionTextColor: derived.secondaryTextOverlayColor,
optionTextColorPressed: derived.primaryActiveColor,
optionTextColorDisabled: derived.disabledTextOverlayColor,
optionTextColorSelected: derived.primaryColor,
optionOpacityDisabled: derived.disabledOpacity,
optionCheckColor: derived.primaryColor,
actionTextColor: derived.secondaryTextOverlayColor
}
}
})

View File

@ -0,0 +1,24 @@
import create from '../../../styles/_utils/create-component-base'
import commonVariables from './_common'
export default create({
name: 'BaseSelectMenu',
theme: 'light',
getDerivedVariables ({ base, derived }) {
return {
...commonVariables,
borderRadius: base.borderRadius,
color: derived.popoverBackgroundColor,
boxShadow: derived.popoverBoxShadow,
groupHeaderTextColor: derived.tertiaryTextColor,
actionDividerColor: derived.dividerOverlayColor,
optionTextColor: derived.secondaryTextColor,
optionTextColorPressed: derived.primaryActiveColor,
optionTextColorDisabled: derived.disabledTextColor,
optionTextColorSelected: derived.primaryColor,
optionOpacityDisabled: derived.disabledOpacity,
optionCheckColor: derived.primaryColor,
actionTextColor: derived.secondaryTextColor
}
}
})

View File

@ -1,13 +0,0 @@
import commonStyle from './common.scss'
function extractLength (length) {
return Number(length.match(/^\d+/)[0])
}
export const itemSize = {
tiny: extractLength(commonStyle.tinySize),
small: extractLength(commonStyle.smallSize),
medium: extractLength(commonStyle.mediumSize),
large: extractLength(commonStyle.largeSize),
huge: extractLength(commonStyle.hugeSize)
}

View File

@ -1,9 +0,0 @@
@import '../_styles/themes/common.scss';
:export {
tinySize: map-get($--n-height, 'tiny');
smallSize: map-get($--n-height, 'small');
mediumSize: map-get($--n-height, 'medium');
largeSize: map-get($--n-height, 'large');
hugeSize: map-get($--n-height, 'huge');
}

View File

@ -1,159 +1,160 @@
@import './mixins/mixins.scss';
// @import './mixins/mixins.scss';
@mixin base-select-size-mixin ($size) {
@include m($size + '-size') {
@include b(virtual-scroller) {
height: 100%;
max-height: map-get($--n-height, $size) * 7.6;
scrollbar-width: none;
-moz-scrollbar-width: none;
&::-webkit-scrollbar {
width: 0;
height: 0;
}
}
@include b(scrollbar-container) {
max-height: map-get($--n-height, $size) * 7.6;
}
@include b(base-select-option) {
height: map-get($--n-height, $size);
line-height: map-get($--n-height, $size);
font-size: map-get($--n-font-size, $size);
}
@include b(base-select-group-header) {
height: map-get($--n-height, $size);
line-height: map-get($--n-height, $size);
font-size: map-get($--n-font-size, $size) - 2px;
}
}
}
// @mixin base-select-size-mixin ($size) {
// @include m($size + '-size') {
// @include b(virtual-scroller) {
// height: 100%;
// max-height: map-get($--n-height, $size) * 7.6;
// scrollbar-width: none;
// -moz-scrollbar-width: none;
// &::-webkit-scrollbar {
// width: 0;
// height: 0;
// }
// }
// @include b(scrollbar-container) {
// max-height: map-get($--n-height, $size) * 7.6;
// }
// @include b(base-select-option) {
// height: map-get($--n-height, $size);
// line-height: map-get($--n-height, $size);
// font-size: map-get($--n-font-size, $size);
// }
// @include b(base-select-group-header) {
// height: map-get($--n-height, $size);
// line-height: map-get($--n-height, $size);
// font-size: map-get($--n-font-size, $size) - 2px;
// }
// }
// }
@include themes-mixin {
@include b(base-select-menu) {
@include once {
@include base-select-size-mixin("small");
@include base-select-size-mixin("medium");
@include base-select-size-mixin("large");
@include base-select-size-mixin("huge");
outline: none;
margin-top: 4px;
margin-bottom: 4px;
z-index: 0;
position: relative;
border-radius: $--n-base-select-menu-border-radius;
transition: background-color .3s $--n-ease-in-out-cubic-bezier;
overflow: hidden;
@include b(base-select-menu-option-wrapper) {
position: relative;
width: 100%;
}
@include e(action) {
padding: 8px 14px;
font-size: 14px;
}
}
background-color: $--base-select-menu-background-color;
box-shadow: $--base-select-menu-box-shadow;
@include b(base-select-group-header) {
@include once {
cursor: default;
padding: 0 14px;
}
color: map-get($--base-select-menu-group-header-text-color, 'default');
}
@include b(base-select-option) {
@include once {
cursor: pointer;
position: relative;
padding: 0 14px;
white-space: nowrap;
transition: color .3s $--n-ease-in-out-cubic-bezier;
text-overflow: ellipsis;
overflow: hidden;
box-sizing: border-box;
@include m(grouped) {
padding: 0 21px;
}
}
color: map-get($--base-select-menu-option-color, "default");
@include m(selected) {
color: map-get($--base-select-menu-option-color, "selected");
}
@include m(disabled) {
color: map-get($--base-select-menu-option-color, "disabled");
@include once {
&::after {
display: none;
}
}
@include m(selected) {
color: map-get($--base-select-menu-option-color, "disabled-selected");
&::after {
border-right: 1px solid map-get($--base-select-menu-option-color, "disabled-selected");
border-bottom: 1px solid map-get($--base-select-menu-option-color, "disabled-selected");
@include once {
display: block;
}
}
}
@include once {
cursor: not-allowed;
}
}
}
@include e(action) {
@include once {
transition:
color .3s $--n-ease-in-out-cubic-bezier,
border-color .3s $--n-ease-in-out-cubic-bezier;
}
border-top: 1px solid $--base-select-menu-action-divider-color;
color: $--base-select-menu-action-text-color;
}
@include m(no-tracking-rect) {
@include b(base-select-option) {
@include not-m(disabled) {
&:hover {
color: map-get($--base-select-menu-option-color, "selected");
}
}
}
}
@include m(multiple) {
@include b(base-select-option) {
@include once {
position: relative;
transition: color .3s $--n-ease-in-out-cubic-bezier;
padding-right: 28px;
@include m(selected) {
background: none;
&::after {
opacity: 1;
transform: rotate(45deg) scale(1);
}
}
}
&::after {
@include once {
content: '';
height: 6px;
width: 3px;
position: absolute;
right: 14px;
transform: rotate(45deg) scale(.5);
top: calc(50% - 4px);
opacity: 0;
transition:
transform .3s $--n-ease-in-out-cubic-bezier,
opacity .3s $--n-ease-in-out-cubic-bezier;
}
border-right: 1px solid $--base-select-menu-option-check-mark-color;
border-bottom: 1px solid $--base-select-menu-option-check-mark-color;
}
&:active {
color: map-get($--base-select-menu-option-color, "active");
}
}
}
}
}
// @include themes-mixin {
// @include b(base-select-menu) {
// // @include base-select-size-mixin("small");
// // @include base-select-size-mixin("medium");
// // @include base-select-size-mixin("large");
// // @include base-select-size-mixin("huge");
// // @include once {
// // outline: none;
// // margin-top: 4px;
// // margin-bottom: 4px;
// // z-index: 0;
// // position: relative;
// // border-radius: $--n-base-select-menu-border-radius;
// // transition: background-color .3s $--n-ease-in-out-cubic-bezier;
// // overflow: hidden;
// // @include b(base-select-menu-option-wrapper) {
// // position: relative;
// // width: 100%;
// // }
// // @include e(action) {
// // padding: 8px 14px;
// // font-size: 14px;
// // }
// // }
// // background-color: $--base-select-menu-background-color;
// // box-shadow: $--base-select-menu-box-shadow;
// // @include b(base-select-group-header) {
// // @include once {
// // cursor: default;
// // padding: 0 14px;
// // }
// // color: map-get($--base-select-menu-group-header-text-color, 'default');
// // }
// // @include b(base-select-option) {
// // @include once {
// // cursor: pointer;
// // position: relative;
// // padding: 0 14px;
// // white-space: nowrap;
// // transition: color .3s $--n-ease-in-out-cubic-bezier;
// // text-overflow: ellipsis;
// // overflow: hidden;
// // box-sizing: border-box;
// // @include m(grouped) {
// // padding: 0 21px;
// // }
// // }
// // color: map-get($--base-select-menu-option-color, "default");
// // @include m(selected) {
// // color: map-get($--base-select-menu-option-color, "selected");
// // }
// // @include m(disabled) {
// // color: map-get($--base-select-menu-option-color, "disabled");
// // @include once {
// // &::after {
// // display: none;
// // }
// // }
// // @include m(selected) {
// // color: map-get($--base-select-menu-option-color, "disabled-selected");
// // &::after {
// // border-right: 1px solid map-get($--base-select-menu-option-color, "disabled-selected");
// // border-bottom: 1px solid map-get($--base-select-menu-option-color, "disabled-selected");
// // @include once {
// // display: block;
// // }
// // }
// // }
// // @include once {
// // cursor: not-allowed;
// // }
// // }
// // }
// // @include e(action) {
// // @include once {
// // transition:
// // color .3s $--n-ease-in-out-cubic-bezier,
// // border-color .3s $--n-ease-in-out-cubic-bezier;
// // }
// // border-top: 1px solid $--base-select-menu-action-divider-color;
// // color: $--base-select-menu-action-text-color;
// // }
// // @include m(no-tracking-rect) {
// // @include b(base-select-option) {
// // @include not-m(disabled) {
// // &:hover {
// // color: map-get($--base-select-menu-option-color, "selected");
// // }
// // }
// // }
// // }
// // @include m(multiple) {
// // @include b(base-select-option) {
// // @include once {
// // position: relative;
// // transition: color .3s $--n-ease-in-out-cubic-bezier;
// // padding-right: 28px;
// // @include m(selected) {
// // background: none;
// // &::after {
// // opacity: 1;
// // transform: rotate(45deg) scale(1);
// // }
// // }
// // }
// // &::after {
// // @include once {
// // content: '';
// // height: 6px;
// // width: 3px;
// // position: absolute;
// // right: 14px;
// // transform: rotate(45deg) scale(.5);
// // top: calc(50% - 4px);
// // opacity: 0;
// // transition:
// // transform .3s $--n-ease-in-out-cubic-bezier,
// // opacity .3s $--n-ease-in-out-cubic-bezier;
// // }
// // border-right: 1px solid $--base-select-menu-option-check-mark-color;
// // border-bottom: 1px solid $--base-select-menu-option-check-mark-color;
// // }
// // &:active {
// // color: map-get($--base-select-menu-option-color, "active");
// // }
// // }
// // }
// }
// }

View File

@ -5,7 +5,6 @@
@import './BaseLoading.scss';
@import './BaseMenuMask.scss';
@import './BaseSelectMenu.scss';
@import './BaseTrackingRect.scss';
@import './Descriptions.scss';
@import './Form.scss';

View File

@ -1,8 +1,14 @@
import create from '../../styles/_utils/create-component-base'
import baseSelectMenuStyle from '../../_base/select-menu/styles/dark'
import inputStyle from '../../input/styles/dark'
export default create({
theme: 'dark',
name: 'AutoComplete',
peer: [
baseSelectMenuStyle,
inputStyle
],
getDerivedVariables ({ base, derived }) {
return {}
}

View File

@ -1,8 +1,14 @@
import create from '../../styles/_utils/create-component-base'
import baseSelectMenuStyle from '../../_base/select-menu/styles/light'
import inputStyle from '../../input/styles/light'
export default create({
theme: 'light',
name: 'AutoComplete',
peer: [
baseSelectMenuStyle,
inputStyle
],
getDerivedVariables ({ base, derived }) {
return {}
}

View File

@ -127,7 +127,10 @@ export default {
themeable,
asformitem(),
locale('Cascader'),
usecssr(styles)
usecssr(styles, {
themeKey: 'syntheticTheme',
injectCssrProps: true
})
],
model: {
prop: 'value',

View File

@ -50,7 +50,7 @@ import NCascaderOption from './CascaderOption.vue'
import NScrollbar from '../../scrollbar'
import NBaseTrackingRect from '../../_base/tracking-rect'
import debounce from 'lodash-es/debounce'
import { itemSize } from '../../_styles-in-js/common'
import depx from '../../_utils/css/depx'
export default {
name: 'NCascaderSubmenu',
@ -92,7 +92,8 @@ export default {
return this.NCascader.syntheticTheme
},
itemSize () {
return itemSize[this.size] || itemSize.medium
const localCssrProps = this.NCascader.cssrProps.$local
return depx(localCssrProps.height[this.size])
}
},
methods: {

View File

@ -1,8 +1,12 @@
import create from '../../styles/_utils/create-component-base'
import selectMenuStyle from '../../_base/select-menu/styles/dark'
export default create({
name: 'Popselect',
theme: 'dark',
peer: [
selectMenuStyle
],
getDerivedVariables ({ base, derived }) {
return {

View File

@ -1,8 +1,12 @@
import create from '../../styles/_utils/create-component-base'
import selectMenuStyle from '../../_base/select-menu/styles/light'
export default create({
name: 'Popselect',
theme: 'light',
peer: [
selectMenuStyle
],
getDerivedVariables ({ base, derived }) {
return {

View File

@ -1,8 +1,14 @@
import create from '../../styles/_utils/create-component-base'
import baseSelectionStyle from '../../_base/selection/styles/dark'
import baseSelectMenuStyle from '../../_base/select-menu/styles/dark'
export default create({
name: 'Select',
theme: 'dark',
peer: [
baseSelectionStyle,
baseSelectMenuStyle
],
getDerivedVariables ({ derived, base }) {
return {}
}

View File

@ -1,8 +1,14 @@
import create from '../../styles/_utils/create-component-base'
import baseSelectionStyle from '../../_base/selection/styles/light'
import baseSelectMenuStyle from '../../_base/select-menu/styles/light'
export default create({
name: 'Select',
theme: 'light',
peer: [
baseSelectionStyle,
baseSelectMenuStyle
],
getDerivedVariables ({ derived, base }) {
return {}
}