refactor(base-slot-machine): ts

This commit is contained in:
07akioni 2021-01-18 22:11:12 +08:00
parent 6882035fee
commit d16015b229
9 changed files with 219 additions and 206 deletions

View File

@ -1,12 +0,0 @@
export { default as NIconSwitchTransition } from './icon-switch-transition'
export { default as NFadeInExpandTransition } from './fade-in-expand-transition'
export { default as NBaseClose } from './close'
export { default as NBaseIcon } from './icon'
export { default as NBaseFocusDetector } from './focus-detector'
export { default as NBaseLoading } from './loading'
export { default as NBaseSelectMenu } from './select-menu'
export { default as NBaseWave } from './wave'
export { default as NBaseMenuMask } from './menu-mask'
export { default as NBaseSelection } from './selection'
export { default as NBaseSlotMachine } from './slot-machine'
export { default as NBaseClear } from './clear'

View File

@ -1 +0,0 @@
export { default } from './src/SlotMachine.vue'

View File

@ -0,0 +1 @@
export { default } from './src/SlotMachine'

View File

@ -0,0 +1,101 @@
import {
h,
defineComponent,
TransitionGroup,
computed,
ref,
watch,
toRef,
Ref
} from 'vue'
import NFadeInExpandTransition from '../../fade-in-expand-transition'
import { useStyle } from '../../../_mixins'
import SlotMachineNumber from './SlotMachineNumber'
import style from './styles/index.cssr'
export default defineComponent({
name: 'BaseSlotMachine',
components: {
NFadeInExpandTransition,
SlotMachineNumber
},
props: {
value: {
type: [Number, String],
default: 0
},
max: {
type: Number,
default: undefined
},
appeared: {
type: Boolean,
required: true
}
},
setup (props) {
useStyle('BaseSlotMachine', style)
const oldValueRef = ref<number>()
const newValueRef = ref<number>()
const numbersRef = computed(() => {
if (typeof props.value === 'string') return []
if (props.value < 1) return [0]
const numbers = []
let value = props.value
if (props.max !== undefined) {
value = Math.min(props.max, value)
}
while (value >= 1) {
numbers.push(value % 10)
value /= 10
value = Math.floor(value)
}
numbers.reverse()
return numbers
})
watch(toRef(props, 'value') as Ref<string | number>, (value, oldValue) => {
if (typeof value === 'string') {
newValueRef.value = undefined
oldValueRef.value = undefined
} else {
if (typeof oldValue === 'string') {
newValueRef.value = value
oldValueRef.value = undefined
} else {
newValueRef.value = value
oldValueRef.value = oldValue
}
}
})
return () => {
const { value } = props
return typeof value === 'number' ? (
<span class="n-base-slot-machine">
<TransitionGroup name="n-fade-up-width-expand-transition" tag="span">
{{
default: () =>
numbersRef.value.map((number, i) => (
<SlotMachineNumber
key={numbersRef.value.length - i - 1}
oldOriginalNumber={oldValueRef.value}
newOriginalNumber={newValueRef.value}
value={number}
/>
))
}}
</TransitionGroup>
<NFadeInExpandTransition key="+" width>
{{
default: () =>
props.max !== undefined && props.max < value ? (
<SlotMachineNumber value="+" />
) : null
}}
</NFadeInExpandTransition>
</span>
) : (
<span class="n-base-slot-machine">{value}</span>
)
}
}
})

View File

@ -1,87 +0,0 @@
<template>
<span v-if="valueIsNumber" class="n-base-slot-machine">
<transition-group name="n-fade-up-width-expand-transition" tag="span">
<slot-machine-number
v-for="(number, i) in numbers"
:key="numbers.length - i - 1"
:old-original-number="oldValue"
:new-original-number="newValue"
:value="number"
/>
</transition-group>
<n-fade-in-expand-transition key="+" width>
<slot-machine-number v-if="max && max < value" :value="'+'" />
</n-fade-in-expand-transition>
</span>
<span v-else class="n-base-slot-machine">
{{ value }}
</span>
</template>
<script>
import { defineComponent } from 'vue'
import NFadeInExpandTransition from '../../fade-in-expand-transition'
import { useStyle } from '../../../_mixins'
import SlotMachineNumber from './SlotMachineNumber.vue'
import style from './styles/index.cssr.js'
export default defineComponent({
name: 'BaseSlotMachine',
components: {
NFadeInExpandTransition,
SlotMachineNumber
},
props: {
value: {
type: [Number, String],
default: 0
},
max: {
type: Number,
default: null
},
appeared: {
type: Boolean,
required: true
}
},
setup (props) {
useStyle('BaseSlotMachine', style)
},
data () {
return {
oldValue: null,
newValue: this.value
}
},
computed: {
valueIsString () {
return typeof this.value === 'string'
},
valueIsNumber () {
return typeof this.value === 'number'
},
numbers () {
if (this.value < 1) return [0]
const numbers = []
let value = this.value
if (this.max) {
value = Math.min(this.max, value)
}
while (value >= 1) {
numbers.push(value % 10)
value /= 10
value = Math.floor(value)
}
numbers.reverse()
return numbers
}
},
watch: {
value (value, oldValue) {
this.newValue = value
this.oldValue = oldValue
}
}
})
</script>

View File

@ -0,0 +1,116 @@
import {
defineComponent,
h,
nextTick,
ref,
computed,
PropType,
watch,
toRef,
Ref
} from 'vue'
export default defineComponent({
name: 'SlotMachineNumber',
props: {
value: {
// could be '+', 1, 2, ...
type: [Number, String] as PropType<string | number>,
required: true
},
oldOriginalNumber: {
type: Number,
default: undefined
},
newOriginalNumber: {
type: Number,
default: undefined
}
},
setup (props) {
const numberRef = ref<HTMLElement | null>(null)
const oldNumberRef = ref<number | string>(props.value)
const newNumberRef = ref<number | string>(props.value)
const scrollAnimationDirectionRef = ref<'up' | 'down'>('up')
const activeRef = ref(false)
const newNumberScrollAnimationClassRef = computed(() => {
return activeRef.value
? `n-base-slot-machine-current-number--${scrollAnimationDirectionRef.value}-scroll`
: null
})
const oldNumberScrollAnimationClassRef = computed(() => {
return activeRef.value
? `n-base-slot-machine-old-number--${scrollAnimationDirectionRef.value}-scroll`
: null
})
// BUG: may be typescript bug
watch(toRef(props, 'value') as Ref<string | number>, (value, oldValue) => {
oldNumberRef.value = oldValue
newNumberRef.value = value
void nextTick(scroll)
})
function scroll (): void {
const newOriginalNumber = props.newOriginalNumber
const oldOriginalNumber = props.oldOriginalNumber
if (oldOriginalNumber === undefined || newOriginalNumber === undefined) { return }
if (newOriginalNumber > oldOriginalNumber) {
scrollByDir('up')
} else if (oldOriginalNumber > newOriginalNumber) {
scrollByDir('down')
}
}
function scrollByDir (dir: 'up' | 'down'): void {
scrollAnimationDirectionRef.value = dir
activeRef.value = false
void nextTick(() => {
void numberRef.value?.offsetWidth
activeRef.value = true
})
}
return () => {
return (
<span ref={numberRef} class="n-base-slot-machine-number">
{oldNumberRef.value !== null ? (
<span
class={[
'n-base-slot-machine-old-number n-base-slot-machine-old-number--top',
oldNumberScrollAnimationClassRef.value
]}
>
{oldNumberRef.value}
</span>
) : null}
<span
class={[
'n-base-slot-machine-current-number',
newNumberScrollAnimationClassRef.value
]}
>
<span
ref="numberWrapper"
class={[
'n-base-slot-machine-current-number__inner',
{
'n-base-slot-machine-current-number__inner--not-number':
typeof props.value !== 'number'
}
]}
>
{newNumberRef.value}
</span>
</span>
{oldNumberRef.value !== null ? (
<span
class={[
'n-base-slot-machine-old-number n-base-slot-machine-old-number--bottom',
oldNumberScrollAnimationClassRef.value
]}
>
{oldNumberRef.value}
</span>
) : null}
</span>
)
}
}
})

View File

@ -1,104 +0,0 @@
<template>
<span ref="numbers" class="n-base-slot-machine-number">
<span
v-if="oldNumber !== null"
class="n-base-slot-machine-old-number n-base-slot-machine-old-number--top"
:class="oldNumberScrollAnimationClass"
>{{ oldNumber }}</span>
<span
class="n-base-slot-machine-current-number"
:class="newNumberScrollAnimationClass"
>
<span
ref="numberWrapper"
class="n-base-slot-machine-current-number__inner"
:class="{
'n-base-slot-machine-current-number__inner--not-number': isNotNumber
}"
>{{ newNumber }}</span>
</span>
<span
v-if="oldNumber !== null"
class="n-base-slot-machine-old-number n-base-slot-machine-old-number--bottom"
:class="oldNumberScrollAnimationClass"
>{{ oldNumber }}</span>
</span>
</template>
<script>
export default {
name: 'SlotMachineNumber',
props: {
value: {
type: [Number, String],
required: true
},
oldOriginalNumber: {
type: Number,
default: null
},
newOriginalNumber: {
type: Number,
default: null
}
},
data () {
return {
oldNumber: null,
newNumber: this.value,
scrollAnimationDirection: null,
active: false
}
},
computed: {
newNumberScrollAnimationClass () {
return this.active
? `n-base-slot-machine-current-number--${this.scrollAnimationDirection}-scroll`
: null
},
oldNumberScrollAnimationClass () {
return this.active
? `n-base-slot-machine-old-number--${this.scrollAnimationDirection}-scroll`
: null
},
isNotNumber () {
return !(typeof this.value === 'number')
}
},
watch: {
value (value, oldValue) {
this.oldNumber = oldValue
this.newNumber = value
this.$nextTick(this.scroll)
}
},
methods: {
scroll () {
const newOriginalNumber = this.newOriginalNumber
const oldOriginalNumber = this.oldOriginalNumber
if (oldOriginalNumber === null && newOriginalNumber === null) return
if (oldOriginalNumber === null || newOriginalNumber > oldOriginalNumber) {
this.scrollUp()
} else if (oldOriginalNumber > newOriginalNumber) {
this.scrollDown()
}
},
scrollUp () {
this.scrollAnimationDirection = 'up'
this.active = false
this.$nextTick(() => {
void this.$el.offsetWidth
this.active = true
})
},
scrollDown () {
this.scrollAnimationDirection = 'down'
this.active = false
this.$nextTick(() => {
void this.$el.offsetWidth
this.active = true
})
}
}
}
</script>

View File

@ -55,8 +55,7 @@ export default cB('alert', `
width: 26px;
height: 26px;
font-size: 26px;
`
),
`),
cE('close', `
transition: color .3s var(--bezier);
position: absolute;