feat(loading-bar): clsPrefix

This commit is contained in:
07akioni 2021-04-18 20:01:19 +08:00
parent c67ac4690c
commit 9b12b11a5b
7 changed files with 144 additions and 110 deletions

View File

@ -12,7 +12,8 @@
</template>
<script>
import { onMounted, inject } from 'vue'
import { onMounted } from 'vue'
import { useLoadingBar } from 'naive-ui'
import SiteHeader from './SiteHeader.vue'
import { loadingBarApiRef } from './routes/router'
import { useIsXs } from './utils/composables'
@ -23,7 +24,7 @@ export default {
SiteHeader
},
setup () {
const loadingBar = inject('loadingBar')
const loadingBar = useLoadingBar()
const isXsRef = useIsXs()
onMounted(() => {
loadingBarApiRef.value = loadingBar

View File

@ -1,3 +1,6 @@
/* istanbul ignore file */
export { default as NLoadingBarProvider } from './src/LoadingBarProvider'
export type {
LoadingBarProviderInst,
LoadingBarProviderProps
} from './src/LoadingBarProvider'
export { useLoadingBar } from './src/use-loading-bar'

View File

@ -10,22 +10,26 @@ import {
ref,
nextTick
} from 'vue'
import { ThemePropsReactive, useTheme } from '../../_mixins'
import { useTheme } from '../../_mixins'
import { loadingBarLight } from '../styles'
import type { LoadingBarTheme } from '../styles'
import { loadingBarProviderInjectionKey } from './LoadingBarProvider'
import style from './styles/index.cssr'
function createClassName (status: 'error' | 'finishing' | 'starting'): string {
return `n-loading-bar n-loading-bar--${status}`
function createClassName (
status: 'error' | 'finishing' | 'starting',
clsPrefix: string
): string {
return `${clsPrefix}-loading-bar ${clsPrefix}-loading-bar--${status}`
}
export default defineComponent({
name: 'LoadingBar',
setup () {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const loadingBarProps = inject<ThemePropsReactive<LoadingBarTheme>>(
'NLoadingBarProps'
)!
const {
props: providerProps,
cPrefixRef
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
} = inject(loadingBarProviderInjectionKey)!
const loadingBarRef = ref<HTMLElement | null>(null)
const enteringRef = ref(false)
const loadingRef = ref(false)
@ -51,7 +55,7 @@ export default defineComponent({
el.style.maxWidth = `${fromProgress}%`
el.style.transition = 'none'
void el.offsetWidth
el.className = createClassName(status)
el.className = createClassName(status, cPrefixRef.value)
el.style.transition = ''
el.style.maxWidth = `${toProgress}%`
}
@ -62,7 +66,7 @@ export default defineComponent({
finishing = true
const el = loadingBarRef.value
if (!el) return
el.className = createClassName('finishing')
el.className = createClassName('finishing', cPrefixRef.value)
void el.offsetWidth
loadingRef.value = false
})
@ -70,7 +74,7 @@ export default defineComponent({
finishing = true
const el = loadingBarRef.value
if (!el) return
el.className = createClassName('finishing')
el.className = createClassName('finishing', cPrefixRef.value)
el.style.maxWidth = '100%'
void el.offsetWidth
loadingRef.value = false
@ -83,7 +87,7 @@ export default defineComponent({
erroring = true
const el = loadingBarRef.value
if (!el) return
el.className = createClassName('error')
el.className = createClassName('error', cPrefixRef.value)
void el.offsetWidth
loadingRef.value = false
})
@ -91,7 +95,7 @@ export default defineComponent({
erroring = true
const el = loadingBarRef.value
if (!el) return
el.className = createClassName('error')
el.className = createClassName('error', cPrefixRef.value)
el.style.maxWidth = '100%'
void el.offsetWidth
loadingRef.value = false
@ -111,9 +115,11 @@ export default defineComponent({
'LoadingBar',
style,
loadingBarLight,
loadingBarProps
providerProps,
cPrefixRef
)
return {
cPrefix: cPrefixRef,
loadingBarRef,
loading: loadingRef,
entering: enteringRef,
@ -136,6 +142,7 @@ export default defineComponent({
}
},
render () {
const { cPrefix } = this
return (
<Transition
name="n-fade-in-transition"
@ -152,10 +159,10 @@ export default defineComponent({
{{
default: () =>
withDirectives(
<div class="n-loading-bar-container">
<div class={`${cPrefix}-loading-bar-container`}>
<div
ref="loadingBarRef"
class="n-loading-bar"
class={`${cPrefix}-loading-bar`}
style={this.cssVars as CSSProperties}
/>
</div>,

View File

@ -1,84 +0,0 @@
import {
Fragment,
h,
ref,
Teleport,
defineComponent,
provide,
nextTick,
PropType
} from 'vue'
import { useIsMounted } from 'vooks'
import { ThemePropsReactive, useTheme } from '../../_mixins'
import type { ThemeProps } from '../../_mixins'
import NLoadingBar from './LoadingBar'
import type { LoadingBarTheme } from '../styles'
import { LoadingBarApiInjection } from './interface'
interface LoadingBarRef {
start: () => void
error: () => void
finish: () => void
}
export default defineComponent({
name: 'LoadingBarProvider',
props: {
...(useTheme.props as ThemeProps<LoadingBarTheme>),
to: {
type: [String, Object] as PropType<string | HTMLElement>,
default: undefined
}
},
setup (props, { slots }) {
const isMountedRef = useIsMounted()
const loadingBarRef = ref<LoadingBarRef | null>(null)
const methods = {
start () {
if (isMountedRef.value) {
loadingBarRef.value?.start()
} else {
void nextTick(() => {
loadingBarRef.value?.start()
})
}
},
error () {
if (isMountedRef.value) {
loadingBarRef.value?.error()
} else {
void nextTick(() => {
loadingBarRef.value?.error()
})
}
},
finish () {
if (isMountedRef.value) {
loadingBarRef.value?.finish()
} else {
void nextTick(() => {
loadingBarRef.value?.finish()
})
}
}
}
provide<LoadingBarApiInjection>('loadingBar', methods)
provide<ThemePropsReactive<LoadingBarTheme>>('NLoadingBarProps', props)
return () => {
return h(Fragment, null, [
h(
Teleport,
{
to: props.to ?? 'body'
},
[
h(NLoadingBar, {
ref: loadingBarRef
})
]
),
slots.default?.()
])
}
}
})

View File

@ -0,0 +1,111 @@
import {
Fragment,
h,
ref,
Teleport,
defineComponent,
provide,
nextTick,
PropType,
ExtractPropTypes,
InjectionKey,
renderSlot,
Ref
} from 'vue'
import { useIsMounted } from 'vooks'
import { useConfig, useTheme } from '../../_mixins'
import type { ThemeProps } from '../../_mixins'
import NLoadingBar from './LoadingBar'
import type { LoadingBarTheme } from '../styles'
import type { ExtractPublicPropTypes } from '../../_utils'
interface LoadingBarInst {
start: () => void
error: () => void
finish: () => void
}
export type LoadingBarProviderInst = LoadingBarInst
export type LoadingBarApiInjection = LoadingBarInst
const loadingBarProps = {
...(useTheme.props as ThemeProps<LoadingBarTheme>),
to: {
type: [String, Object] as PropType<string | HTMLElement>,
default: undefined
}
}
export type LoadingBarProviderProps = ExtractPublicPropTypes<
typeof loadingBarProps
>
export type LoadingBarProviderSetupProps = ExtractPropTypes<
typeof loadingBarProps
>
export const loadingBarProviderInjectionKey: InjectionKey<{
props: LoadingBarProviderSetupProps
cPrefixRef: Ref<string>
}> = Symbol('loadingBar')
export const loadingBarApiInjectionKey: InjectionKey<LoadingBarApiInjection> = Symbol(
'loadingBarApi'
)
export default defineComponent({
name: 'LoadingBarProvider',
props: loadingBarProps,
setup (props) {
const isMountedRef = useIsMounted()
const loadingBarRef = ref<LoadingBarInst | null>(null)
const methods: LoadingBarProviderInst = {
start () {
if (isMountedRef.value) {
loadingBarRef.value?.start()
} else {
void nextTick(() => {
loadingBarRef.value?.start()
})
}
},
error () {
if (isMountedRef.value) {
loadingBarRef.value?.error()
} else {
void nextTick(() => {
loadingBarRef.value?.error()
})
}
},
finish () {
if (isMountedRef.value) {
loadingBarRef.value?.finish()
} else {
void nextTick(() => {
loadingBarRef.value?.finish()
})
}
}
}
const { mergedClsPrefix } = useConfig(props)
provide(loadingBarApiInjectionKey, methods)
provide(loadingBarProviderInjectionKey, {
props,
cPrefixRef: mergedClsPrefix
})
return Object.assign(methods, {
loadingBarRef
})
},
render () {
return (
<>
<Teleport to={this.to ?? 'body'}>
<NLoadingBar ref="loadingBarRef" />
</Teleport>
{renderSlot(this.$slots, 'default')}
</>
)
}
})

View File

@ -1,5 +0,0 @@
export interface LoadingBarApiInjection {
start: () => void
finish: () => void
error: () => void
}

View File

@ -1,6 +1,7 @@
import { inject } from 'vue'
import { LoadingBarApiInjection } from './interface'
import { loadingBarApiInjectionKey } from './LoadingBarProvider'
import type { LoadingBarApiInjection } from './LoadingBarProvider'
export function useLoadingBar (): LoadingBarApiInjection | undefined {
return inject('loadingBar')
return inject(loadingBarApiInjectionKey)
}