refactor(rate): ts

This commit is contained in:
07akioni 2021-01-18 23:45:11 +08:00
parent 93eea42184
commit d2e9b016ad
12 changed files with 171 additions and 131 deletions

View File

@ -1,2 +0,0 @@
/* istanbul ignore file */
export { default as NRate } from './src/Rate.vue'

2
src/rate/index.ts Normal file
View File

@ -0,0 +1,2 @@
/* istanbul ignore file */
export { default as NRate } from './src/Rate'

133
src/rate/src/Rate.tsx Normal file
View File

@ -0,0 +1,133 @@
import {
h,
toRef,
ref,
computed,
defineComponent,
renderList,
VNode,
PropType,
CSSProperties
} from 'vue'
import { useMergedState } from 'vooks'
import { NBaseIcon } from '../../_base'
import { useTheme, useFormItem } from '../../_mixins'
import type { ThemeProps } from '../../_mixins'
import { call } from '../../_utils'
import type { MaybeArray } from '../../_utils'
import { rateLight } from '../styles'
import type { RateTheme } from '../styles'
import style from './styles/index.cssr'
import StarIcon from './StarIcon'
export default defineComponent({
name: 'Rate',
components: {
NBaseIcon,
StarIcon
},
props: {
...(useTheme.props as ThemeProps<RateTheme>),
count: {
type: Number,
default: 5
},
value: {
type: Number,
default: undefined
},
defaultValue: {
type: Number,
default: 0
},
size: {
type: String as PropType<'small' | 'medium' | 'large'>,
default: 'medium'
},
// eslint-disable-next-line vue/prop-name-casing
'onUpdate:value': {
type: [Function, Array] as PropType<MaybeArray<(value: number) => void>>,
default: undefined
}
},
setup (props) {
const themeRef = useTheme('Rate', 'Rate', style, rateLight, props)
const controlledValueRef = toRef(props, 'value')
const uncontrolledValueRef = ref(props.defaultValue)
const hoverIndexRef = ref<number | null>(null)
const formItem = useFormItem(props)
function doUpdateValue (value: number): void {
const { 'onUpdate:value': onUpdateValue } = props
const { nTriggerFormChange, nTriggerFormInput } = formItem
if (onUpdateValue) {
call(onUpdateValue, value)
}
uncontrolledValueRef.value = value
nTriggerFormChange()
nTriggerFormInput()
}
function handleMouseEnter (index: number): void {
hoverIndexRef.value = index
}
function handleMouseLeave (): void {
hoverIndexRef.value = null
}
function handleClick (index: number): void {
doUpdateValue(index + 1)
}
return {
mergedValue: useMergedState(controlledValueRef, uncontrolledValueRef),
hoverIndex: hoverIndexRef,
handleMouseEnter,
handleClick,
handleMouseLeave,
cssVars: computed(() => {
const {
common: { cubicBezierEaseInOut },
self: { itemColor, itemColorActive, itemSize }
} = themeRef.value
return {
'--bezier': cubicBezierEaseInOut,
'--item-color': itemColor,
'--item-color-active': itemColorActive,
'--item-size': itemSize
}
})
}
},
render () {
const { hoverIndex, mergedValue } = this
return (
<div
class="n-rate"
style={this.cssVars as CSSProperties}
onMouseleave={this.handleMouseLeave}
>
{renderList(
this.count,
(_, index) =>
(
<div
key={index}
class={[
'n-rate__item',
{
'n-rate__item--active':
hoverIndex !== null
? index <= hoverIndex
: index < mergedValue
}
]}
onClick={() => this.handleClick(index)}
onMouseenter={() => this.handleMouseEnter(index)}
>
<n-base-icon>
<star-icon />
</n-base-icon>
</div>
) as VNode
)}
</div>
)
}
})

View File

@ -1,105 +0,0 @@
<template>
<div class="n-rate" :style="cssVars" @mouseleave="handleMouseLeave(index)">
<div
v-for="index in count"
:key="index"
class="n-rate__item"
:class="{
'n-rate__item--active':
hoverIndex !== null ? index <= hoverIndex : index < mergedValue
}"
@click="handleClick(index)"
@mouseenter="handleMouseEnter(index)"
>
<n-base-icon>
<star-icon />
</n-base-icon>
</div>
</div>
</template>
<script>
import { toRef, ref, computed, defineComponent } from 'vue'
import { useMergedState } from 'vooks'
import { NBaseIcon } from '../../_base'
import { useTheme, useFormItem } from '../../_mixins'
import { call } from '../../_utils'
import { rateLight } from '../styles'
import style from './styles/index.cssr.js'
import StarIcon from './StarIcon.vue'
export default defineComponent({
name: 'Rate',
components: {
NBaseIcon,
StarIcon
},
props: {
...useTheme.props,
count: {
type: Number,
default: 5
},
value: {
type: Number,
default: undefined
},
defaultValue: {
type: Number,
default: 0
},
// eslint-disable-next-line vue/prop-name-casing
'onUpdate:value': {
type: [Function, Array],
default: undefined
}
},
setup (props) {
const themeRef = useTheme('Rate', 'Rate', style, rateLight, props)
const controlledValueRef = toRef(props, 'value')
const uncontrolledValueRef = ref(props.defaultValue)
return {
...useFormItem(props),
mergedValue: useMergedState(controlledValueRef, uncontrolledValueRef),
uncontrolledValue: uncontrolledValueRef,
hoverIndex: ref(null),
cssVars: computed(() => {
const {
common: { cubicBezierEaseInOut },
self: { itemColor, itemColorActive, itemSize }
} = themeRef.value
return {
'--bezier': cubicBezierEaseInOut,
'--item-color': itemColor,
'--item-color-active': itemColorActive,
'--item-size': itemSize
}
})
}
},
methods: {
doUpdateValue (value) {
const {
'onUpdate:value': onUpdateValue,
nTriggerFormChange,
nTriggerFormInput
} = this
if (onUpdateValue) {
call(onUpdateValue, value)
}
this.uncontrolledValue = value
nTriggerFormChange()
nTriggerFormInput()
},
handleMouseEnter (index) {
this.hoverIndex = index
},
handleMouseLeave (index) {
this.hoverIndex = null
},
handleClick (index) {
this.doUpdateValue(index + 1)
}
}
})
</script>

View File

@ -0,0 +1,7 @@
import { h } from 'vue'
export default (
<svg viewBox="0 0 512 512">
<path d="M394 480a16 16 0 01-9.39-3L256 383.76 127.39 477a16 16 0 01-24.55-18.08L153 310.35 23 221.2a16 16 0 019-29.2h160.38l48.4-148.95a16 16 0 0130.44 0l48.4 149H480a16 16 0 019.05 29.2L359 310.35l50.13 148.53A16 16 0 01394 480z" />
</svg>
)

View File

@ -1,7 +0,0 @@
<template>
<svg viewBox="0 0 512 512">
<path
d="M394 480a16 16 0 01-9.39-3L256 383.76 127.39 477a16 16 0 01-24.55-18.08L153 310.35 23 221.2a16 16 0 019-29.2h160.38l48.4-148.95a16 16 0 0130.44 0l48.4 149H480a16 16 0 019.05 29.2L359 310.35l50.13 148.53A16 16 0 01394 480z"
/>
</svg>
</template>

View File

@ -1,6 +1,7 @@
import { commonDark } from '../../_styles/new-common'
import { RateTheme } from './light'
export default {
const rateDark: RateTheme = {
name: 'Rate',
common: commonDark,
self (vars) {
@ -12,3 +13,5 @@ export default {
}
}
}
export default rateDark

View File

@ -1,2 +0,0 @@
export { default as rateDark } from './dark.js'
export { default as rateLight } from './light.js'

3
src/rate/styles/index.ts Normal file
View File

@ -0,0 +1,3 @@
export { default as rateDark } from './dark'
export { default as rateLight } from './light'
export type { RateTheme, RateThemeVars } from './light'

View File

@ -1,14 +0,0 @@
import { commonLight } from '../../_styles/new-common'
export default {
name: 'Rate',
common: commonLight,
self (vars) {
const { railColor } = vars
return {
itemColor: railColor,
itemColorActive: '#FFCC33',
itemSize: '20px'
}
}
}

22
src/rate/styles/light.ts Normal file
View File

@ -0,0 +1,22 @@
import { commonLight } from '../../_styles/new-common'
import type { ThemeCommonVars } from '../../_styles/new-common'
const self = (vars: ThemeCommonVars) => {
const { railColor } = vars
return {
itemColor: railColor,
itemColorActive: '#FFCC33',
itemSize: '20px'
}
}
export type RateThemeVars = ReturnType<typeof self>
const themeLight = {
name: 'Rate',
common: commonLight,
self
}
export default themeLight
export type RateTheme = typeof themeLight