Skip to content

Commit

Permalink
feat: add rate component
Browse files Browse the repository at this point in the history
  • Loading branch information
baiwusanyu-c committed Sep 17, 2022
1 parent 156224e commit 5e3b88c
Show file tree
Hide file tree
Showing 13 changed files with 233 additions and 67 deletions.
1 change: 1 addition & 0 deletions packages/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@ export * from './checkbox'
export * from './badge'
export * from './tag'
export * from './message'
export * from './rate'
5 changes: 5 additions & 0 deletions packages/components/rate/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { withInstall } from '@onu-ui/utils'
import Rate from './src/index.vue'

export const ORate = withInstall(Rate)
export default ORate
68 changes: 68 additions & 0 deletions packages/components/rate/src/index.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
<script lang="ts" setup name="O-Rate">
import { computed } from 'vue'
import OIcon from '../../icon/src/index.vue'
import { rateProps } from './props'
const props = defineProps(rateProps)
const emits = defineEmits(['update:modelValue', 'change'])
const curVal = ref(props.modelValue)
const isAtLeftHalf = ref(false)
const setCurValue = (item:number, e:MouseEvent) => {
if (props.readonly) return
if (props.allowHalf) {
const target = e.target as HTMLElement
isAtLeftHalf.value = e.offsetX * 2 <= target.clientWidth
}
curVal.value = isAtLeftHalf.value ? item - 0.5 : item
}
const resetCurValue = () => {
if (props.readonly) return
curVal.value = props.modelValue
}
watch(() => props.modelValue, () => {
resetCurValue()
},
{ immediate: true })
const selectVal = () => {
if (props.readonly) return
emits('update:modelValue', curVal.value)
emits('change', curVal.value)
}
const showFilledIcon = computed(() => {
return function(val, item) {
return !(Math.round(val) < item)
}
})
const showHalfIcon = computed(() => {
return function(val, item) {
return (Math.round(val) === item) && val < item
}
})
</script>

<template>
<div class="o-rate">
<span
v-for="(item, key) in maxValue"
:key="key"
@mousemove="setCurValue(item, $event)"
@mouseleave="resetCurValue"
@click="selectVal"
>
<o-icon
v-show="showFilledIcon(curVal, item)"
:class="showHalfIcon(curVal, item) ? 'o-rate-half' : ''"
name="o-rate-icon i-carbon-star-filled"
:o="color"
/>
<o-icon v-show="!showFilledIcon(curVal, item)" name="o-rate-icon i-carbon-star" :o="voidColor" />
</span>
<span class="o-rate-text">{{ text }}</span>
</div>
</template>
31 changes: 31 additions & 0 deletions packages/components/rate/src/props.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import type { ExtractPropTypes } from 'vue'

export const rateProps = {
modelValue: {
type: Number,
default: 0,
},
maxValue: {
type: Number,
default: 5,
},
readonly: Boolean,
text: {
type: String,
default: '',
},
color: {
type: String,
default: 'warning',
},
voidColor: {
type: String,
default: '',
},
allowHalf: {
type: Boolean,
default: false,
},
} as const

export type ORateProps = ExtractPropTypes<typeof rateProps>
1 change: 1 addition & 0 deletions packages/preset/src/rules/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,5 @@ export default [
['o-dashed', { 'border-style': 'dashed' }],
['o-solid', { 'background-color': 'rgba(var(--onu-c-context), 1) !important', 'border-color': 'rgba(var(--onu-c-context), 1)', 'color': 'white !important' }],
['o-disabled', { opacity: 0.4, cursor: 'not-allowed !important' }],
['o-bg-clip-half', { 'clip-path': 'polygon(0% 0%, 50% 0, 50% 50%, 50% 100%, 0% 100%)' }],
] as Rule<Theme>[]
3 changes: 3 additions & 0 deletions packages/preset/src/shortcuts/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { iconShortcuts } from './icon'
import { messageDynamicShortcuts, messageShortcuts } from './message'
import { switchShortcuts } from './switch'
import { tagShortcuts } from './tag'
import { rateShortcuts } from './rate'

import type { Theme } from '@unocss/preset-uno'
import type { UserShortcuts } from 'unocss'
Expand Down Expand Up @@ -40,4 +41,6 @@ export default [
switchShortcuts,
// tag
tagShortcuts,
// rate
rateShortcuts,
] as UserShortcuts<Theme>
7 changes: 7 additions & 0 deletions packages/preset/src/shortcuts/rate.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export const rateShortcuts: Record<string, string> = {
// Rate
'o-rate': 'f-c cursor-pointer',
'o-rate-icon': 'text-xl m-1 !w-5 !h-5',
'o-rate-text': 'leading-5',
'o-rate-half': 'o-bg-clip-half',
}
2 changes: 2 additions & 0 deletions playground/src/auto-imports.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ declare global {
const OCheckbox: typeof import('onu-ui')['OCheckbox']
const OIcon: typeof import('onu-ui')['OIcon']
const OMessage: typeof import('onu-ui')['OMessage']
const ORate: typeof import('onu-ui')['ORate']
const OSwitch: typeof import('onu-ui')['OSwitch']
const OTag: typeof import('onu-ui')['OTag']
const asyncComputed: typeof import('@vueuse/core')['asyncComputed']
Expand Down Expand Up @@ -282,6 +283,7 @@ declare module '@vue/runtime-core' {
readonly OCheckbox: UnwrapRef<typeof import('onu-ui')['OCheckbox']>
readonly OIcon: UnwrapRef<typeof import('onu-ui')['OIcon']>
readonly OMessage: UnwrapRef<typeof import('onu-ui')['OMessage']>
readonly ORate: UnwrapRef<typeof import('onu-ui')['ORate']>
readonly OSwitch: UnwrapRef<typeof import('onu-ui')['OSwitch']>
readonly OTag: UnwrapRef<typeof import('onu-ui')['OTag']>
readonly asyncComputed: UnwrapRef<typeof import('@vueuse/core')['asyncComputed']>
Expand Down
2 changes: 2 additions & 0 deletions playground/src/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ declare module '@vue/runtime-core' {
OCard: typeof import('onu-ui')['OCard']
OCheckbox: typeof import('onu-ui')['OCheckbox']
OIcon: typeof import('onu-ui')['OIcon']
ORate: typeof import('onu-ui')['ORate']
OSwitch: typeof import('onu-ui')['OSwitch']
OTag: typeof import('onu-ui')['OTag']
RouterLink: typeof import('vue-router')['RouterLink']
Expand All @@ -29,6 +30,7 @@ declare module '@vue/runtime-core' {
TheHeader: typeof import('./components/layout/TheHeader.vue')['default']
TheIcon: typeof import('./components/TheIcon.vue')['default']
TheMessage: typeof import('./components/TheMessage.vue')['default']
TheRate: typeof import('./components/TheRate.vue')['default']
TheSwitch: typeof import('./components/TheSwitch.vue')['default']
TheTag: typeof import('./components/TheTag.vue')['default']
}
Expand Down
14 changes: 14 additions & 0 deletions playground/src/components/TheRate.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<script lang="ts" setup>
const rate = ref(2.5)
</script>

<template>
<OCard o-white title="Rate">
<div space-y-2>
<div fsc gap-4>
{{ rate }}
<o-rate v-model="rate" :max-value="10" text="123123" allow-half />
</div>
</div>
</OCard>
</template>
1 change: 1 addition & 0 deletions playground/src/pages/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,6 @@
<TheBadge />
<TheTag />
<TheMessage />
<TheRate />
</div>
</template>
Loading

0 comments on commit 5e3b88c

Please sign in to comment.