refactor(mixins, utils, styles, index): typescript

This commit is contained in:
07akioni 2021-01-13 23:14:58 +08:00
parent 187381b175
commit a0921fab1b
58 changed files with 413 additions and 248 deletions

View File

@ -66,6 +66,7 @@
"@rollup/plugin-node-resolve": "^10.0.0",
"@rollup/plugin-replace": "^2.3.4",
"@types/jest": "^26.0.15",
"@types/lodash-es": "^4.17.4",
"@vitejs/plugin-vue": "^1.0.4",
"@vue/compiler-sfc": "^3.0.5",
"@vue/eslint-config-standard": "^5.1.2",
@ -93,7 +94,7 @@
"rollup-plugin-terser": "^7.0.2",
"rollup-plugin-vue": "^6.0.0-beta.11",
"tinycolor2": "^1.4.2",
"typescript": "^4.0.5",
"typescript": "^4.1.3",
"vite": "^2.0.0-beta.23",
"vue-jest": "^5.0.0-alpha.5",
"vue-router": "^4.0.0-rc.1"

View File

@ -1,46 +0,0 @@
import { cB, c, cE } from '../../../../_utils/cssr'
import createIconSwitchTransition from '../../../../_styles/transitions/icon-switch'
// vars:
// --bezier
// --color
// --size
// --color-hover
// --color-pressed
export default cB('base-clear', {
flexShrink: 0,
height: '1em',
width: '1em',
position: 'relative'
}, [
c('>', [
cE('clear', {
fontSize: 'var(--size)',
cursor: 'pointer',
color: 'var(--color)',
transition: 'color .3s var(--bezier)'
}, [
c('&:hover', {
color: 'var(--color-hover)!important'
}),
c('&:active', {
color: 'var(--color-pressed)!important'
})
]),
cE('placeholder', {
display: 'flex'
}),
cE('clear, placeholder', {
position: 'absolute',
left: '50%',
top: '50%',
transform: 'translateX(-50%) translateY(-50%)'
}, [
createIconSwitchTransition({
originalTransform: 'translateX(-50%) translateY(-50%)',
left: '50%',
top: '50%'
})
])
])
])

View File

@ -1,14 +0,0 @@
import { inject, computed } from 'vue'
export default function useConfig (props) {
const NConfigProvider = inject('NConfigProvider', null)
return {
NConfigProvider,
mergedBordered: computed(() => {
const { bordered } = props
if (bordered !== undefined) return bordered
return NConfigProvider?.mergedBordered || true
}),
namespace: computed(() => NConfigProvider?.namespace)
}
}

19
src/_mixins/use-config.ts Normal file
View File

@ -0,0 +1,19 @@
import { inject, computed } from 'vue'
import { ConfigProviderInjection } from '../config-provider'
interface UseConfigProps {
bordered?: boolean
}
export default function useConfig (props: UseConfigProps) {
const NConfigProvider = inject<ConfigProviderInjection | null>('NConfigProvider', null)
return {
NConfigProvider,
mergedBordered: computed(() => {
const { bordered } = props
if (bordered !== undefined) return bordered
return NConfigProvider?.mergedBordered || true
}),
namespace: computed(() => NConfigProvider?.mergedNamespace)
}
}

View File

@ -1,8 +1,26 @@
import { computed, inject, provide, onBeforeUnmount } from 'vue'
export default function useFormItem (props, options = {}) {
const { defaultSize = 'medium', mergedSize } = options
const NFormItem = inject('NFormItem', null)
interface UseFormItemOptions {
defaultSize?: string
mergedSize?: (formItem: FormItemInjection | null) => string
}
interface FormItemInjection {
size: string | undefined
mergedSize: string
restoreValidation: () => void
handleContentBlur: () => void
handleContentFocus: () => void
handleContentInput: () => void
handleContentChange: () => void
}
interface UseFormItemProps {
size?: string
}
export default function useFormItem (props: UseFormItemProps, { defaultSize = 'medium', mergedSize }: UseFormItemOptions = {}) {
const NFormItem = inject<FormItemInjection | null>('NFormItem', null)
provide('NFormItem', null)
const mergedSizeRef = computed(
mergedSize

View File

@ -1,18 +0,0 @@
import { inject, getCurrentInstance, computed } from 'vue'
import { warn } from '../_utils'
export default function useHljs (props) {
const NConfigProvider = inject('NConfigProvider', {})
const vm = getCurrentInstance().proxy
if (
__DEV__ &&
!props.hljs &&
!NConfigProvider.mergedHljs &&
!vm.$naive.hljs
) {
warn('code', 'hljs is not set.')
}
return computed(() => {
return props.hljs || NConfigProvider.mergedHljs || vm.$naive.hljs
})
}

23
src/_mixins/use-hljs.ts Normal file
View File

@ -0,0 +1,23 @@
import { inject, getCurrentInstance, computed } from 'vue'
import { ConfigProviderInjection } from '../config-provider'
import { warn } from '../_utils'
interface UseHljsProps {
hljs?: any
}
export default function useHljs (props: UseHljsProps) {
const NConfigProvider = inject<ConfigProviderInjection | null>('NConfigProvider', null)
const vm = getCurrentInstance()?.proxy as any
if (
__DEV__ &&
!props.hljs &&
!NConfigProvider?.mergedHljs &&
!vm.$naive.hljs
) {
warn('code', 'hljs is not set.')
}
return computed(() => {
return props.hljs || NConfigProvider?.mergedHljs || vm.$naive.hljs
})
}

View File

@ -1,25 +1,26 @@
import { inject, computed, getCurrentInstance } from 'vue'
import { enUS, dateEnUS } from '../locales'
import { ConfigProviderInjection } from '../config-provider'
export default function createLocaleMixin (ns) {
const vm = getCurrentInstance().proxy
const NConfigProvider = inject('NConfigProvider', {})
export default function createLocaleMixin (ns: keyof typeof enUS) {
const vm = getCurrentInstance()?.proxy
const NConfigProvider = inject<ConfigProviderInjection | null>('NConfigProvider', null)
const localeRef = computed(() => {
const { mergedLocale } = NConfigProvider
const { mergedLocale } = NConfigProvider || {}
if (mergedLocale) return mergedLocale[ns]
const { mergedLanguage } = NConfigProvider
const { mergedLanguage } = NConfigProvider || {}
if (mergedLanguage) {
// legacy start
const {
$naive: { locales = [], fallbackLocale }
} = vm
} = vm as any
return locales[mergedLanguage ?? fallbackLocale][ns]
} else {
return enUS[ns]
}
})
const dateLocaleRef = computed(() => {
const { mergedDateLocale } = NConfigProvider
const { mergedDateLocale } = NConfigProvider || {}
return mergedDateLocale ?? dateEnUS
})
return {

View File

@ -1,3 +1,4 @@
import { CNode } from 'css-render'
import { onBeforeMount } from 'vue'
import globalStyle from '../_styles/global/index.cssr.js'
@ -5,7 +6,7 @@ globalStyle.mount({
id: 'naive-ui-global'
})
export default function useStyle (mountId, style) {
export default function useStyle (mountId: string, style: CNode) {
onBeforeMount(() => {
style.mount({
id: mountId

View File

@ -1,11 +1,20 @@
import { inject, computed, onBeforeMount } from 'vue'
import { merge } from 'lodash-es'
import globalStyle from '../_styles/global/index.cssr.js'
import { CNode } from 'css-render'
import { ConfigProviderInjection, Theme, ThemeOverrides } from '../config-provider/index.js'
globalStyle.mount({
id: 'naive-ui-global'
})
function useTheme (resolveId, mountId, style, defaultTheme, props) {
interface UseThemeProps {
unstableTheme: Theme
unstableThemeOverrides: ThemeOverrides
builtinThemeOverrides: ThemeOverrides
}
function useTheme (resolveId: string, mountId: string, style: CNode | undefined, defaultTheme: Theme, props: UseThemeProps) {
if (style) {
onBeforeMount(() => {
style.mount({
@ -13,7 +22,7 @@ function useTheme (resolveId, mountId, style, defaultTheme, props) {
})
})
}
const NConfigProvider = inject('NConfigProvider', {})
const NConfigProvider = inject<ConfigProviderInjection | null>('NConfigProvider', null)
const mergedThemeRef = computed(() => {
// keep props to make theme overrideable
const {
@ -27,18 +36,18 @@ function useTheme (resolveId, mountId, style, defaultTheme, props) {
} = selfOverrides
const {
mergedUnstableTheme: {
common: injectedGlobalCommon,
common: injectedGlobalCommon = undefined,
[resolveId]: {
common: injectedCommon,
self: injectedSelf,
common: injectedCommon = undefined,
self: injectedSelf = undefined,
peers: injectedPeers = {}
} = {}
} = {},
mergedUnstableThemeOverrides: {
common: injectedGlobalCommonOverrides,
common: injectedGlobalCommonOverrides = undefined,
[resolveId]: injectedSelfOverrides = {}
} = {}
} = NConfigProvider
} = NConfigProvider || {}
const {
common: injectedCommonOverrides,
peers: injectedPeersOverrides = {}

View File

@ -16,7 +16,7 @@ const base = {
alpha4: '0.38',
alpha5: '0.28',
alphaClose: '0.52',
alphaClose: 0.52,
alphaDisabled: '0.6',
alphaDisabledInput: '0.06',
@ -78,7 +78,7 @@ function overlay (alpha) {
function neutral (alpha) {
const overlayRgba = Array.from(baseInvertBackgroundRgb)
overlayRgba[3] = Number(alpha)
return composite(baseBackgroundRgb, overlayRgba)
return composite(baseBackgroundRgb, overlayRgba as any)
}
const derived = {
...commonVariables,
@ -147,17 +147,17 @@ const derived = {
borderColorOverlay: overlay(base.alphaBorder),
// close
closeColorHover: neutral(base.alphaClose * 1.25),
closeColorHoverOverlay: overlay(base.alphaClose * 1.25),
closeColor: neutral(base.alphaClose),
closeColorOverlay: overlay(base.alphaClose),
closeColorPressed: neutral(base.alphaClose * 0.8),
closeColorPressedOverlay: overlay(base.alphaClose * 0.8),
closeColorHover: neutral(Number(base.alphaClose) * 1.25),
closeColorHoverOverlay: overlay(Number(base.alphaClose) * 1.25),
closeColor: neutral(Number(base.alphaClose)),
closeColorOverlay: overlay(Number(base.alphaClose)),
closeColorPressed: neutral(Number(base.alphaClose) * 0.8),
closeColorPressedOverlay: overlay(Number(base.alphaClose) * 0.8),
closeColorDisabled: neutral(base.alpha4),
closeColorDisabledOverlay: overlay(base.alpha4),
closeOpacity: base.alphaClose,
closeOpacityHover: base.alphaClose * 1.25,
closeOpacityPressed: base.alphaClose * 0.8,
closeOpacity: Number(base.alphaClose),
closeOpacityHover: Number(base.alphaClose) * 1.25,
closeOpacityPressed: Number(base.alphaClose) * 0.8,
scrollbarColorOverlay: overlay(base.alphaScrollbar),
scrollbarColorHoverOverlay: overlay(base.alphaScrollbarHover),

View File

@ -80,7 +80,7 @@ function overlay (alpha) {
function neutral (alpha) {
const overlayRgba = Array.from(baseInvertBackgroundRgb)
overlayRgba[3] = Number(alpha)
return composite(baseBackgroundRgb, overlayRgba)
return composite(baseBackgroundRgb, overlayRgba as any)
}
const derived = {
...commonVariables,
@ -149,17 +149,17 @@ const derived = {
borderColorOverlay: overlay(base.alphaBorder),
// close
closeColorHover: neutral(base.alphaClose * 0.8),
closeColorHoverOverlay: overlay(base.alphaClose * 0.8),
closeColor: neutral(base.alphaClose),
closeColorOverlay: overlay(base.alphaClose),
closeColorPressed: neutral(base.alphaClose * 1.25),
closeColorPressedOverlay: overlay(base.alphaClose * 1.25),
closeColorHover: neutral(Number(base.alphaClose) * 0.8),
closeColorHoverOverlay: overlay(Number(base.alphaClose) * 0.8),
closeColor: neutral(Number(base.alphaClose)),
closeColorOverlay: overlay(Number(base.alphaClose)),
closeColorPressed: neutral(Number(base.alphaClose) * 1.25),
closeColorPressedOverlay: overlay(Number(base.alphaClose) * 1.25),
closeColorDisabled: neutral(base.alpha4),
closeColorDisabledOverlay: overlay(base.alpha4),
closeOpacity: base.alphaClose,
closeOpacityHover: base.alphaClose * 0.8,
closeOpacityPressed: base.alphaClose * 1.25,
closeOpacity: Number(base.alphaClose),
closeOpacityHover: Number(base.alphaClose) * 0.8,
closeOpacityPressed: Number(base.alphaClose) * 1.25,
scrollbarColorOverlay: overlay(base.alphaScrollbar),
scrollbarColorHoverOverlay: overlay(base.alphaScrollbarHover),

View File

@ -3,6 +3,15 @@ import commonVariables from '../new-common/_common'
const { cubicBezierEaseInOut } = commonVariables
interface FadeDownTransitionOptions {
name?: string
fromOffset?: string
enterDuration?: string
leaveDuration?: string
enterCubicBezier?: string
leaveCubicBezier?: string
}
export default function ({
name = 'fade-down',
fromOffset = '-4px',
@ -10,7 +19,7 @@ export default function ({
leaveDuration = '.3s',
enterCubicBezier = cubicBezierEaseInOut,
leaveCubicBezier = cubicBezierEaseInOut
} = {}) {
}: FadeDownTransitionOptions = {}) {
return [
c(
`&.${namespace}-${name}-transition-enter-from, &.${namespace}-${name}-transition-leave-to`,

View File

@ -7,6 +7,16 @@ const {
cubicBezierEaseIn
} = commonVariables
interface FadeInHeightExpandTransitionOption {
overflow?: string
duration?: string
originalTransition?: string
leavingDelay?: string
foldPadding?: boolean
enterToProps?: Record<string, string | number> | null
leaveToProps?: Record<string, string | number> | null
}
export default function ({
overflow = 'hidden',
duration = '.3s',
@ -15,7 +25,7 @@ export default function ({
foldPadding = false,
enterToProps = null,
leaveToProps = null
} = {}) {
}: FadeInHeightExpandTransitionOption = {}) {
return [
c(
`&.${namespace}-fade-in-height-expand-transition-leave-from, &.${namespace}-fade-in-height-expand-transition-enter-to`,

View File

@ -7,13 +7,21 @@ const {
transformDebounceScale
} = commonVariables
interface FadeInScaleUpTransitionOptions {
transformOrigin?: string
duration?: string
enterScale?: string
originalTransform?: string
originalTransition?: string
}
export default function ({
transformOrigin = 'inherit',
duration = '.2s',
enterScale = '.9',
originalTransform = '',
originalTransition = ''
} = {}) {
}: FadeInScaleUpTransitionOptions = {}) {
return [
c(`&.${namespace}-fade-in-scale-up-transition-leave-active`, {
transformOrigin,

View File

@ -3,7 +3,12 @@ import commonVariables from '../new-common/_common'
const { cubicBezierEaseInOut } = commonVariables
export default function ({ duration = '.2s', delay = '.1s' } = {}) {
interface FadeInWidthExpandTransition {
duration?: string
delay?: string
}
export default function ({ duration = '.2s', delay = '.1s' }: FadeInWidthExpandTransition = {}) {
return [
c(
`&.${namespace}-fade-in-width-expand-transition-leave-from, &.${namespace}-fade-in-width-expand-transition-enter-to`,

View File

@ -3,13 +3,21 @@ import commonVariables from '../new-common/_common'
const { cubicBezierEaseInOut } = commonVariables
interface FadeInTransitionOptions {
name?: string
enterDuration?: string
leaveDuration?: string
enterCubicBezier?: string
leaveCubicBezier?: string
}
export default function ({
name = 'fade-in',
enterDuration = '0.2s',
leaveDuration = '0.2s',
enterCubicBezier = cubicBezierEaseInOut,
leaveCubicBezier = cubicBezierEaseInOut
} = {}) {
}: FadeInTransitionOptions = {}) {
return [
c(`&.${namespace}-${name}-transition-enter-active`, {
transition: `all ${enterDuration} ${enterCubicBezier}!important`

View File

@ -3,7 +3,11 @@ import commonVariables from '../new-common/_common'
const { cubicBezierEaseOut } = commonVariables
export default function fadeUpWidthExpandTransition ({ duration = '.2s' } = {}) {
interface FadeUpWidthExpandTransition {
duration?: string
}
export default function fadeUpWidthExpandTransition ({ duration = '.2s' }: FadeUpWidthExpandTransition = {}) {
return [
c(`&.${namespace}-fade-up-width-expand-transition-leave-active`, {
transition: `

View File

@ -1,12 +1,19 @@
import { c, namespace } from '../../_utils/cssr'
import commonVariables from '../new-common/_common'
interface IconSwitchTransitionOptions {
originalTransform?: string
left?: string | number
top?: string | number
transition?: string
}
export default function ({
originalTransform = '',
left = 0,
top = 0,
transition = `all .3s ${commonVariables.cubicBezierEaseInOut} !important`
} = {}) {
}: IconSwitchTransitionOptions = {}) {
return [
c(
`&.${namespace}-icon-switch-transition-enter-from, &.${namespace}-icon-switch-transition-leave-to`,

View File

@ -3,11 +3,17 @@ import commonVariables from '../new-common/_common'
const { cubicBezierEaseIn, cubicBezierEaseOut } = commonVariables
interface SlideInFromBottomTransitionOptions {
duration?: string
leaveDuration?: string
name?: String
}
export default function ({
duration = '0.3s',
leaveDuration = '0.2s',
name = 'slide-in-from-bottom'
} = {}) {
}: SlideInFromBottomTransitionOptions = {}) {
return [
c(`&.${namespace}-${name}-transition-leave-active`, {
transition: `transform ${leaveDuration} ${cubicBezierEaseIn}`

View File

@ -3,11 +3,17 @@ import commonVariables from '../new-common/_common'
const { cubicBezierEaseIn, cubicBezierEaseOut } = commonVariables
interface SlideInFromLeftTransitionOptions {
duration?: string
leaveDuration?: string
name?: String
}
export default function ({
duration = '0.3s',
leaveDuration = '0.2s',
name = 'slide-in-from-left'
} = {}) {
}: SlideInFromLeftTransitionOptions = {}) {
return [
c(`&.${namespace}-${name}-transition-leave-active`, {
transition: `transform ${leaveDuration} ${cubicBezierEaseIn}`

View File

@ -3,11 +3,17 @@ import commonVariables from '../new-common/_common'
const { cubicBezierEaseIn, cubicBezierEaseOut } = commonVariables
interface SlideInFromRightTransitionOptions {
duration?: string
leaveDuration?: string
name?: String
}
export default function ({
duration = '0.3s',
leaveDuration = '0.2s',
name = 'slide-in-from-right'
} = {}) {
}: SlideInFromRightTransitionOptions = {}) {
return [
c(`&.${namespace}-${name}-transition-leave-active`, {
transition: `transform ${leaveDuration} ${cubicBezierEaseIn}`

View File

@ -3,11 +3,17 @@ import commonVariables from '../new-common/_common'
const { cubicBezierEaseIn, cubicBezierEaseOut } = commonVariables
interface SlideInFromTopTransitionOptions {
duration?: string
leaveDuration?: string
name?: String
}
export default function ({
duration = '0.3s',
leaveDuration = '0.2s',
name = 'slide-in-from-top'
} = {}) {
}: SlideInFromTopTransitionOptions = {}) {
return [
c(`&.${namespace}-${name}-transition-leave-active`, {
transition: `transform ${leaveDuration} ${cubicBezierEaseIn}`

View File

@ -1,9 +1,9 @@
import { composite } from 'seemly'
export function createHoverColor (rgb) {
export function createHoverColor (rgb: string) {
return composite(rgb, [255, 255, 255, 0.16])
}
export function createPressedColor (rgb) {
export function createPressedColor (rgb: string) {
return composite(rgb, [0, 0, 0, 0.12])
}

View File

@ -3,43 +3,41 @@ import {
watch,
onMounted,
inject,
toRef,
Ref,
getCurrentInstance,
onBeforeUnmount
} from 'vue'
export function useInjectionRef (injectionName, key, fallback) {
const injection = inject(injectionName)
if (!injection && arguments.length > 2) return fallback
return toRef(injection, key)
}
// injection.collection {
// key1: [insta, instb]
// key2: [instc]
// }
export function useInjectionInstanceCollection (
injectionName,
collectionKey,
registerKeyRef
injectionName: string,
collectionKey: string,
registerKeyRef: Ref<any>
) {
const injection = inject(injectionName, null)
const injection = inject<any | null>(injectionName, null)
if (injection === null) return
const vm = getCurrentInstance().proxy
const vm = getCurrentInstance()?.proxy
watch(registerKeyRef, registerInstance)
registerInstance(registerKeyRef.value)
onBeforeUnmount(() => {
registerInstance(undefined, registerKeyRef.value)
})
function registerInstance (key, oldKey) {
function registerInstance (key?: string, oldKey?: string) {
const collection = injection[collectionKey]
if (oldKey !== undefined) removeInstance(collection, oldKey)
if (key !== undefined) addInstance(collection, key)
}
function removeInstance (collection, key) {
function removeInstance (collection: Record<string, any[]>, key: string) {
if (!collection[key]) collection[key] = []
collection[key].splice(
collection[key].findIndex((instance) => instance === vm),
1
)
}
function addInstance (collection, key) {
function addInstance (collection: Record<string, any[]>, key: string) {
if (!collection[key]) collection[key] = []
if (!~collection[key].findIndex((instance) => instance === vm)) {
collection[key].push(vm)
@ -47,8 +45,12 @@ export function useInjectionInstanceCollection (
}
}
export function useInjectionCollection (injectionName, collectionKey, valueRef) {
const injection = inject(injectionName, null)
// injection.collection {
// key1: [insta.value, instb.value]
// key2: [instc.value]
// }
export function useInjectionCollection (injectionName: string, collectionKey: string, valueRef: Ref<any>) {
const injection = inject<Record<any, any[]> | null>(injectionName, null)
if (injection === null) return
if (!(collectionKey in injection)) {
injection[collectionKey] = []
@ -71,23 +73,26 @@ export function useInjectionCollection (injectionName, collectionKey, valueRef)
})
}
// injection.collection {
// key1: [insta.$el, instb.$el]
// key2: [instc.$el]
// }
export function useInjectionElementCollection (
injectionName,
collectionKey,
getElement
injectionName: string,
collectionKey: string,
getElement: () => Element
) {
const injection = inject(injectionName)
const injection = inject<Record<string, any[]> | null>(injectionName, null)
if (injection === null) return
if (!(collectionKey in injection)) {
injection[collectionKey] = []
}
onMounted(() => {
const currentInstance = getCurrentInstance().proxy
injection[collectionKey].push(getElement(currentInstance))
injection[collectionKey].push(getElement())
})
onBeforeUnmount(() => {
const collectionArray = injection[collectionKey]
const currentInstance = getCurrentInstance().proxy
const element = getElement(currentInstance)
const element = getElement()
const index = collectionArray.findIndex(
(collectionElement) => collectionElement === element
)
@ -95,17 +100,17 @@ export function useInjectionElementCollection (
})
}
export function useDeferredTrue (valueRef, delay, shouldDelayRef) {
export function useDeferredTrue (valueRef: Ref<any>, delay: number, shouldDelayRef: Ref<boolean>): Ref<boolean> {
if (!delay) return valueRef
const delayedRef = ref(valueRef.value)
let timerId = null
let timerId: number | null = null
watch(valueRef, (value) => {
if (timerId !== null) clearTimeout(timerId)
if (timerId !== null) window.clearTimeout(timerId)
if (value === true) {
if (shouldDelayRef && shouldDelayRef.value === false) {
delayedRef.value = true
} else {
timerId = setTimeout(() => {
timerId = window.setTimeout(() => {
delayedRef.value = true
}, delay)
}

View File

@ -1,14 +0,0 @@
import { useMemo } from 'vooks'
import { inject } from 'vue'
export function useAdjustedTo (props) {
const modal = inject('NModalBody', null)
const drawer = inject('NDrawerBody', null)
return useMemo(() => {
const { to } = props
if (to !== undefined) return to
if (modal) return modal.bodyRef
if (drawer) return drawer.bodyRef
return to ?? 'body'
})
}

View File

@ -0,0 +1,26 @@
import { useMemo } from 'vooks'
import { inject } from 'vue'
interface UseAdjustedToProps {
to?: string
}
interface ModalInjection {
bodyRef: Element
}
interface DrawerInjection {
bodyRef: Element
}
export function useAdjustedTo (props: UseAdjustedToProps) {
const modal = inject<ModalInjection | null>('NModalBody', null)
const drawer = inject<DrawerInjection | null>('NDrawerBody', null)
return useMemo(() => {
const { to } = props
if (to !== undefined) return to
if (modal) return modal.bodyRef
if (drawer) return drawer.bodyRef
return to ?? 'body'
})
}

View File

@ -1,21 +1,19 @@
const pureNumberRegex = /^(\d|\.)+$/
const numberRegex = /(\d|\.)+/
export default function formatLength (length, options = {}) {
const { c = 1, offset = 0, attachPx = true } = options
const type = typeof length
if (type === 'number') {
export default function formatLength (length: number | string, { c = 1, offset = 0, attachPx = true } = {}): string {
if (typeof length === 'number') {
const result = (length + offset) * c
if (result === 0) return '0'
return `${result}px`
} else if (type === 'string') {
} else if (typeof length === 'string') {
if (pureNumberRegex.test(length)) {
const result = (Number(length) + offset) * c
if (attachPx) {
if (result === 0) return '0'
return `${result}px`
} else {
return result
return `${result}`
}
} else {
const result = numberRegex.exec(length)
@ -23,4 +21,5 @@ export default function formatLength (length, options = {}) {
return length.replace(numberRegex, '' + (Number(result[0]) + offset) * c)
}
}
return length
}

View File

@ -1,4 +1,4 @@
import CSSRender from 'css-render'
import CSSRender, { CNode } from 'css-render'
import BEMPlugin from '@css-render/plugin-bem'
const namespace = 'n'
@ -18,7 +18,7 @@ context.theme = null
context.palette = null
const { cB, cE, cM, cNotM } = plugin
function insideFormItem (status, style) {
function insideFormItem (status: string | null, style: CNode) {
if (status === null) return style
return c(`${prefix}form-item`, [
c(`${prefix}form-item-blank`, [
@ -27,11 +27,11 @@ function insideFormItem (status, style) {
])
}
function insideModal (style) {
function insideModal (style: CNode) {
return c(`${prefix}modal, ${prefix}drawer`, [style])
}
function createKey (keyPrefix, ...suffixs) {
function createKey (keyPrefix: string, ...suffixs: string[]) {
return (
keyPrefix +
suffixs
@ -43,11 +43,11 @@ function createKey (keyPrefix, ...suffixs) {
)
}
function cRB (selector, ...rest) {
return c(`${prefix}${selector}`, ...rest)
function cRB (selector: string, ...rest: any[]): CNode {
return (c as any)(`${prefix}${selector}`, ...rest)
}
function withPrefix (selector) {
function withPrefix (selector: string) {
return `${prefix}${selector}`
}

View File

@ -1,11 +1,11 @@
const warnedMessages = new Set()
export function warnOnce (location, message) {
export function warnOnce (location: string, message: string): void {
const mergedMessage = `[naive/${location}]: ${message}`
if (warnedMessages.has(mergedMessage)) return
warnedMessages.add(mergedMessage)
}
export function warn (location, message) {
export function warn (location: string, message: string): void {
console.error(`[naive/${location}]: ${message}`)
}

View File

@ -1,4 +1,5 @@
export function call (funcs, ...args) {
export function call<A extends any[]> (funcs: Function[] | Function, ...args: A): void {
if (Array.isArray(funcs)) funcs.forEach((func) => call(func, ...args))
else return funcs(...args)
}

View File

@ -1,13 +0,0 @@
import { Fragment } from 'vue'
// o(n) flatten
export function flatten (vNodes, result = []) {
vNodes.forEach((vNode) => {
if (vNode.type === Fragment) {
flatten(vNode.children, result)
} else {
result.push(vNode)
}
})
return result
}

26
src/_utils/vue/flatten.ts Normal file
View File

@ -0,0 +1,26 @@
import { Fragment, VNodeChild } from 'vue'
// o(n) flatten
export function flatten (vNodes: VNodeChild[], result: VNodeChild[] = []) {
vNodes.forEach((vNode) => {
if (vNode === null) return
if (typeof vNode !== 'object') {
result.push(vNode)
return
}
if (Array.isArray(vNode)) {
flatten(vNode, result)
return
}
if (vNode.type === Fragment) {
if (vNode.children === null) return
if (Array.isArray(vNode.children)) {
flatten(vNode.children, result)
}
// rawSlot
} else {
result.push(vNode)
}
})
return result
}

View File

@ -1,4 +0,0 @@
export function getSlot (instance, slotName = 'default', fallback = []) {
const slots = instance.$slots
return (slots[slotName] && slots[slotName]()) || fallback
}

View File

@ -0,0 +1,8 @@
import { ComponentPublicInstance, VNode } from "vue"
export function getSlot (instance: ComponentPublicInstance, slotName = 'default', fallback: VNode[] = []) {
const slots = instance.$slots
const slot = slots[slotName]
if (slot === undefined) return fallback
return slot()
}

View File

@ -1,4 +0,0 @@
export function getVNodeChildren (vNode, slotName = 'default', fallback = []) {
const children = vNode.children
return (children[slotName] && children[slotName]()) || fallback
}

View File

@ -0,0 +1,12 @@
import { VNode } from "vue"
export function getVNodeChildren (vNode: VNode, slotName = 'default', fallback: VNode[] = []): VNode[] {
const { children } = vNode
if (children !== null && typeof children === 'object' && !Array.isArray(children)) {
const slot = children[slotName]
if (typeof slot === 'function') {
return slot()
}
}
return fallback
}

View File

@ -1,7 +0,0 @@
export function keep (object, keys = [], rest = {}) {
const keepedObject = {}
keys.forEach((key) => {
keepedObject[key] = object[key]
})
return Object.assign(keepedObject, rest)
}

7
src/_utils/vue/keep.ts Normal file
View File

@ -0,0 +1,7 @@
export function keep<T, K extends keyof T, R> (object: T, keys: K[] = [], rest: R): Pick<T, K> & R {
const keepedObject: any = {}
keys.forEach((key) => {
keepedObject[key] = object[key]
})
return Object.assign(keepedObject, rest)
}

View File

@ -1,10 +0,0 @@
export function omit (object, keys = [], rest = {}) {
const omitedObject = {}
const originalKeys = Object.getOwnPropertyNames(object)
originalKeys.forEach((originalKey) => {
if (!keys.includes(originalKey)) {
omitedObject[originalKey] = object[originalKey]
}
})
return Object.assign(omitedObject, rest)
}

14
src/_utils/vue/omit.ts Normal file
View File

@ -0,0 +1,14 @@
export function omit <T, K extends keyof T, R> (
object: T,
keys: K[] = [],
rest: R
): Pick<T, Exclude<keyof T, K>> & R {
const omitedObject: any = {}
const originalKeys = Object.getOwnPropertyNames(object)
originalKeys.forEach((originalKey) => {
if (!(keys as string[]).includes(originalKey)) {
omitedObject[originalKey] = object[originalKey as keyof T]
}
})
return Object.assign(omitedObject, rest) as any
}

View File

@ -1,14 +1,16 @@
import { createTextVNode } from 'vue'
import { defineComponent, createTextVNode, PropType, } from 'vue'
export const render = {
export const render = defineComponent({
name: 'Render',
props: {
render: {
type: [String, Number, Function],
default: () => {}
type: [String, Number, Function] as PropType<string | number | null | undefined | Function>,
default: undefined
}
},
render () {
const { render } = this
if (render === undefined || render === null) return null
if (typeof render === 'function') {
return render()
} else if (typeof render === 'string') {
@ -19,4 +21,4 @@ export const render = {
return JSON.stringify(render)
}
}
}
})

View File

@ -1,15 +1,38 @@
import { App } from 'vue'
import version from './version'
import { warn } from './_utils'
import { Hljs, NaiveLocale } from './config-provider'
function setHljs (hljs) {
type ComponentType = any
interface NaiveUIInstance {
version: string
install (app: App): void
use (plugin: { install: (naive: NaiveUIInstance) => void }): void
componentPrefix: string
hljs: any
setHljs (hljs: any): void
setHighlightjs (hljs: any): void
locales: Record<string, NaiveLocale>
fallbackLocale: NaiveLocale
}
interface NaiveUICreateOptions {
componentPrefix?: string
components?: ComponentType[]
locales?: NaiveLocale[]
hljs?: Hljs
}
function setHljs (this: NaiveUIInstance, hljs: any) {
this.hljs = hljs
}
function createLocalesObject (locales) {
function createLocalesObject (locales: NaiveLocale[]) {
return (
locales &&
locales.reduce((localeMap, locale) => {
localeMap[locale._name] = locale
localeMap[locale.name] = locale
return localeMap
}, {})
)
@ -19,14 +42,14 @@ function create ({
componentPrefix = 'N',
components = [],
locales = [],
hljs
} = {}) {
hljs = undefined
}: NaiveUICreateOptions = {}) {
const fallbackLocale = locales[0]
if (!fallbackLocale) warn('create', '`locales` is empty.')
const installTargets = []
const naive = {
const installTargets: App[] = []
const naive: NaiveUIInstance = {
version,
use (plugin) {
use (plugin: any) {
plugin.install(naive)
},
install,
@ -38,13 +61,13 @@ function create ({
locales: createLocalesObject(locales),
fallbackLocale
}
function registerComponent (app, name, component) {
function registerComponent (app: App, name: string, component: ComponentType) {
const registered = app.component(componentPrefix + name)
if (!registered) {
app.component(componentPrefix + name, component)
}
}
function install (app) {
function install (app: App) {
if (installTargets.includes(app)) return
installTargets.push(app)
app.config.globalProperties.$naive = naive
@ -52,7 +75,7 @@ function create ({
const { name, alias } = component
registerComponent(app, name, component)
if (alias) {
alias.forEach((aliasName) => {
alias.forEach((aliasName: string) => {
registerComponent(app, aliasName, component)
})
}

5
src/global.d.ts vendored Normal file
View File

@ -0,0 +1,5 @@
export {}
declare global {
var __DEV__: boolean
}

View File

@ -3,17 +3,15 @@ import { enUS, zhCN } from './locales'
// deprecated
import { NServiceLayout } from './_deprecated/nimbus-service-layout/index'
import styleScheme from './_deprecated/style-scheme'
import create from './create'
export default create({
components: [
...Object.keys(components).map((key) => components[key]),
...Object.keys(components).map((key) => components[key as keyof typeof components]),
// Deprecated
NServiceLayout
],
// deprecated
locales: [enUS, zhCN],
styleSchemes: styleScheme
locales: [enUS, zhCN]
})

5
src/shims-vue.d.ts vendored Normal file
View File

@ -0,0 +1,5 @@
declare module "*.vue" {
import { defineComponent } from "vue";
const component: ReturnType<typeof defineComponent>;
export default component;
}

17
tsconfig.json Normal file
View File

@ -0,0 +1,17 @@
{
"include": ["src/**/*"],
"exclude": ["src/_deprecated/icons/**/*", "src/**/*.spec.js"],
"compilerOptions": {
"strict": true,
"strictNullChecks": true,
"allowJs": true,
"checkJs": true,
"module": "ES6",
"moduleResolution": "Node",
"target": "ES6",
"lib": [
"ESNext",
"DOM"
]
}
}