mirror of
https://github.com/tusen-ai/naive-ui.git
synced 2025-01-12 12:25:16 +08:00
refactor(rate): ts
This commit is contained in:
parent
93eea42184
commit
d2e9b016ad
@ -1,2 +0,0 @@
|
||||
/* istanbul ignore file */
|
||||
export { default as NRate } from './src/Rate.vue'
|
2
src/rate/index.ts
Normal file
2
src/rate/index.ts
Normal file
@ -0,0 +1,2 @@
|
||||
/* istanbul ignore file */
|
||||
export { default as NRate } from './src/Rate'
|
133
src/rate/src/Rate.tsx
Normal file
133
src/rate/src/Rate.tsx
Normal 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>
|
||||
)
|
||||
}
|
||||
})
|
@ -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>
|
7
src/rate/src/StarIcon.tsx
Normal file
7
src/rate/src/StarIcon.tsx
Normal 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>
|
||||
)
|
@ -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>
|
@ -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
|
@ -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
3
src/rate/styles/index.ts
Normal file
@ -0,0 +1,3 @@
|
||||
export { default as rateDark } from './dark'
|
||||
export { default as rateLight } from './light'
|
||||
export type { RateTheme, RateThemeVars } from './light'
|
@ -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
22
src/rate/styles/light.ts
Normal 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
|
Loading…
Reference in New Issue
Block a user