Merge branch 'main' into feat

This commit is contained in:
07akioni 2021-06-11 18:32:10 +08:00 committed by GitHub
commit 7dc0f40dc6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 205 additions and 140 deletions

1
.husky/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
_

4
.husky/pre-commit Executable file
View File

@ -0,0 +1,4 @@
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
npx lint-staged

View File

@ -5,7 +5,16 @@
### Feats
- `n-spin`'s `size` prop support number.
- `n-date-picker` add `footer` slot
- `n-date-picker` add `footer` slot.
### Fixes
- Fix `n-slider` doesn't support touch events
- Fix `n-button` causes crash when it's imported in script inside head tag. [#68](https://github.com/TuSimple/naive-ui/pull/68)
- Fix `n-spin` animation shifts.
- Fix `n-menu` lack `on-update-value` and `on-update-expanded-keys` props.
- Fix `n-popconfirm` icon slot not working.
- Fix `n-tabs` logs useless info.
## 2.11.5 (2021-06-10)

View File

@ -7,6 +7,15 @@
- `n-spin``size` 属性支持 number 类型
- `n-date-picker` 支持 `footer` 插槽
### Fixes
- 修正 `n-slider` 不支持触摸事件
- 修正 `n-button` 在 head 内部的 script 被引入造成崩溃 [#68](https://github.com/TuSimple/naive-ui/pull/68)
- 修正 `n-spin` 动画闪烁
- 修正 `n-menu` 缺少 `on-update-value``on-update-expanded-keys` 属性
- 修正 `n-popconfirm` icon slot 不生效
- 修正 `n-tabs` 在控制台输出无用信息
## 2.11.5 (2021-06-10)
### Feats

View File

@ -23,13 +23,13 @@ What's more, they are all treeshakable.
### Customizable Themes
We provide an advanced type safe theme system that built Uses TypeScript. All you need is to provide a theme overrides object in JS. Then all the stuffs will be done by us.
We provide an advanced type safe theme system built using TypeScript. All you need is to provide a theme overrides object in JS. Then all the stuff will be done by us.
What's more, no less/sass/css variables, no webpack loaders are required.
### Uses TypeScript
All the staff in Naive UI is written in TypeScript. It can work with your typescript project seamlessly.
All the stuff in Naive UI is written in TypeScript. It can work with your typescript project seamlessly.
What's more, you don't need to import any CSS to use the components.

View File

@ -23,7 +23,8 @@
"test:watch": "cross-env NODE_ENV=test jest ---watch --verbose --coverage",
"gen-version": "node scripts/gen-version",
"post-changelog": "node scripts/post-changelog",
"build:site:ts": "./scripts/pre-build-site/pre-build-site.sh && cross-env TUSIMPLE=true NODE_ENV=production NODE_OPTIONS=--max-old-space-size=4096 vite build && ./scripts/post-build-site/post-build-site.sh"
"build:site:ts": "./scripts/pre-build-site/pre-build-site.sh && cross-env TUSIMPLE=true NODE_ENV=production NODE_OPTIONS=--max-old-space-size=4096 vite build && ./scripts/post-build-site/post-build-site.sh",
"prepare": "husky install"
},
"author": "07akioni",
"license": "MIT",
@ -96,8 +97,8 @@
"eslint-plugin-vue": "^7.6.0",
"express": "^4.17.1",
"fs-extra": "^10.0.0",
"husky": "^4.3.5",
"inquirer": "^6.5.2",
"husky": "^6.0.0",
"inquirer": "^8.1.0",
"jest": "^27.0.4",
"lint-staged": "^11.0.0",
"marked": "^2.0.1",
@ -114,7 +115,7 @@
"css-render": "^0.15.2",
"date-fns": "^2.19.0",
"evtd": "^0.2.2",
"highlight.js": "^10.7.1",
"highlight.js": "^11.0.1",
"lodash": "^4.17.21",
"lodash-es": "^4.17.21",
"seemly": "^0.3.1",
@ -126,11 +127,6 @@
"vue-router": "^4.0.5",
"vueuc": "^0.4.7"
},
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
},
"sideEffects": false,
"homepage": "https://www.naiveui.com",
"repository": {

View File

@ -3,6 +3,10 @@ import { useStyle } from '../../../_mixins'
import NIconSwitchTransition from '../../icon-switch-transition'
import style from './styles/index.cssr'
const duration = '1.6s'
// The loading svg dom comes from https://codepen.io/FezVrasta/pen/oXrgdR
export default defineComponent({
name: 'BaseLoading',
props: {
@ -35,33 +39,62 @@ export default defineComponent({
useStyle('BaseLoading', style, toRef(props, 'clsPrefix'))
},
render () {
const { clsPrefix } = this
const { clsPrefix, radius, strokeWidth, stroke, scale } = this
const scaledRadius = radius / scale
return (
<div
class={`${clsPrefix}-base-loading`}
style={{ stroke: this.stroke }}
role="img"
aria-label="loading"
>
<div class={`${clsPrefix}-base-loading`} role="img" aria-label="loading">
<NIconSwitchTransition>
{{
default: () =>
this.show ? (
<svg
key="loading"
class={`${clsPrefix}-base-loading-circular ${clsPrefix}-base-loading__icon`}
viewBox={`0 0 ${(this.radius * 2) / this.scale} ${
(this.radius * 2) / this.scale
}`}
class={`${clsPrefix}-base-loading__icon`}
viewBox={`0 0 ${2 * scaledRadius} ${2 * scaledRadius}`}
xmlns="http://www.w3.org/2000/svg"
style={{ color: stroke }}
>
<circle
style={{ strokeWidth: this.strokeWidth }}
class={`${clsPrefix}-base-loading-circular-path`}
cx={this.radius / this.scale}
cy={this.radius / this.scale}
fill="none"
r={this.radius - this.strokeWidth / 2}
/>
<g>
<animateTransform
attributeName="transform"
type="rotate"
values={`0 ${scaledRadius} ${scaledRadius};270 ${scaledRadius} ${scaledRadius}`}
begin="0s"
dur={duration}
fill="freeze"
repeatCount="indefinite"
/>
<circle
fill="none"
stroke="currentColor"
stroke-width={strokeWidth}
stroke-linecap="round"
cx={scaledRadius}
cy={scaledRadius}
r={radius - strokeWidth / 2}
stroke-dasharray={5.67 * radius}
stroke-dashoffset={18.48 * radius}
>
<animateTransform
attributeName="transform"
type="rotate"
values={`0 ${scaledRadius} ${scaledRadius};135 ${scaledRadius} ${scaledRadius};450 ${scaledRadius} ${scaledRadius}`}
begin="0s"
dur={duration}
fill="freeze"
repeatCount="indefinite"
/>
<animate
attributeName="stroke-dashoffset"
values={`${5.67 * radius};${1.42 * radius};${
5.67 * radius
}`}
begin="0s"
dur={duration}
fill="freeze"
repeatCount="indefinite"
/>
</circle>
</g>
</svg>
) : (
<div

View File

@ -1,65 +1,25 @@
import { c, cB, cE } from '../../../../_utils/cssr'
import { cB, cE } from '../../../../_utils/cssr'
import iconSwitchTransition from '../../../../_styles/transitions/icon-switch.cssr'
const dashOffset = 500
export default c([
cB('base-loading', `
position: relative;
line-height: 0;
width: 1em;
height: 1em;
`, [
cE('placeholder', {
position: 'absolute',
export default cB('base-loading', `
position: relative;
line-height: 0;
width: 1em;
height: 1em;
`, [
cE('placeholder', {
position: 'absolute',
left: '50%',
top: '50%',
transform: 'translateX(-50%) translateY(-50%)'
}, [
iconSwitchTransition({
left: '50%',
top: '50%',
transform: 'translateX(-50%) translateY(-50%)'
}, [
iconSwitchTransition({
left: '50%',
top: '50%',
originalTransform: 'translateX(-50%) translateY(-50%)'
})
]),
cE('icon', [
iconSwitchTransition()
]),
cB('base-loading-circular', `
stroke: currentColor;
height: 100%;
width: 100%;
animation: n-base-loading-rotate 1.5s linear infinite;
transform-origin: center;
`, [
cB('base-loading-circular-path', `
transform-origin: center;
animation: n-base-loading-dash 1.5s ease-in-out infinite;
stroke-dasharray: ${dashOffset};
stroke-dashoffset: 0;
stroke-linecap: round;
`)
])
originalTransform: 'translateX(-50%) translateY(-50%)'
})
]),
c('@keyframes n-base-loading-rotate', `
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(270deg);
}
`),
c('@keyframes n-base-loading-dash', `
0% {
stroke-dashoffset: ${dashOffset};
}
50% {
stroke-dashoffset: ${dashOffset / 4};
transform: rotate(135deg);
}
100% {
stroke-dashoffset: ${dashOffset};
transform: rotate(450deg);
}
`)
cE('icon', [
iconSwitchTransition()
])
])

View File

@ -32,8 +32,8 @@ export default defineComponent({
<NBaseLoading
clsPrefix={clsPrefix}
class={`${clsPrefix}-base-selection__mark`}
strokeWidth={20}
scale={0.8}
strokeWidth={24}
scale={0.85}
show={props.loading}
>
{{

View File

@ -1,5 +1,5 @@
import { inject, computed, ComputedRef } from 'vue'
import type { highlight, getLanguage } from 'highlight.js'
import type { HLJSApi } from 'highlight.js'
import { configProviderInjectionKey } from '../config-provider/src/ConfigProvider'
import { warn } from '../_utils'
@ -9,8 +9,8 @@ interface UseHljsProps {
}
export interface Hljs {
highlight: typeof highlight
getLanguage: typeof getLanguage
highlight: HLJSApi['highlight']
getLanguage: HLJSApi['getLanguage']
}
export default function useHljs (
props: UseHljsProps

View File

@ -437,7 +437,7 @@ const Button = defineComponent({
clsPrefix={mergedClsPrefix}
key="loading"
class={`${mergedClsPrefix}-icon-slot`}
strokeWidth={24}
strokeWidth={20}
/>
) : (
<div

View File

@ -154,7 +154,7 @@ export default c([
animationName: 'button-wave-spread, button-wave-opacity'
})
]),
(typeof window !== 'undefined' && 'MozBoxSizing' in document.body.style)
(typeof window !== 'undefined' && 'MozBoxSizing' in document.createElement('div').style)
? c('&::moz-focus-inner', {
border: 0
})

View File

@ -176,8 +176,8 @@ export default defineComponent({
[`${mergedClsPrefix}-cascader-option--pending`]:
this.keyboardPending || this.hoverPending,
[`${mergedClsPrefix}-cascader-option--disabled`]: this.disabled,
[`${mergedClsPrefix}-cascader-option--show-prefix`]: this
.showCheckbox
[`${mergedClsPrefix}-cascader-option--show-prefix`]:
this.showCheckbox
}
]}
onMouseenter={this.mergedHandleMouseEnter}
@ -206,8 +206,8 @@ export default defineComponent({
{!this.isLeaf ? (
<NBaseLoading
clsPrefix={mergedClsPrefix}
scale={0.8}
strokeWidth={20}
scale={0.85}
strokeWidth={24}
show={this.isLoading}
class={`${mergedClsPrefix}-cascader-option-icon`}
>

View File

@ -19,7 +19,7 @@ export default defineComponent({
const { clsPrefix } = this
return (
<div class={`${clsPrefix}-log-loader`}>
<NBaseLoading clsPrefix={clsPrefix} strokeWidth={24} />
<NBaseLoading clsPrefix={clsPrefix} strokeWidth={24} scale={0.85} />
<span class={`${clsPrefix}-log-loader__content`}>
{this.locale.loading}
</span>

View File

@ -88,11 +88,11 @@ const menuProps = {
},
disabled: Boolean,
inverted: Boolean,
// eslint-disable-next-line vue/prop-name-casing
'onUpdate:expandedKeys': [Function, Array] as PropType<
MaybeArray<OnUpdateKeys>
>,
// eslint-disable-next-line vue/prop-name-casing
onUpdateExpandedKeys: [Function, Array] as PropType<MaybeArray<OnUpdateKeys>>,
onUpdateValue: [Function, Array] as PropType<MaybeArray<OnUpdateValue>>,
'onUpdate:value': [Function, Array] as PropType<MaybeArray<OnUpdateValue>>,
// deprecated
onOpenNamesChange: {
@ -233,10 +233,17 @@ export default defineComponent({
toggleExpand
})
function doSelect (value: Key, item: MenuOption): void {
const { 'onUpdate:value': onUpdateValue, onSelect } = props
const {
'onUpdate:value': _onUpdateValue,
onUpdateValue,
onSelect
} = props
if (onUpdateValue) {
call(onUpdateValue as OnUpdateValueImpl, value, item)
}
if (_onUpdateValue) {
call(_onUpdateValue as OnUpdateValueImpl, value, item)
}
if (onSelect) {
call(onSelect as OnUpdateValueImpl, value, item)
}
@ -244,10 +251,14 @@ export default defineComponent({
}
function doUpdateExpandedKeys (value: Key[]): void {
const {
'onUpdate:expandedKeys': onUpdateExpandedKeys,
'onUpdate:expandedKeys': _onUpdateExpandedKeys,
onUpdateExpandedKeys,
onExpandedNamesChange,
onOpenNamesChange
} = props
if (_onUpdateExpandedKeys) {
call(_onUpdateExpandedKeys as OnUpdateKeysImpl, value)
}
if (onUpdateExpandedKeys) {
call(onUpdateExpandedKeys as OnUpdateKeysImpl, value)
}

View File

@ -35,22 +35,19 @@ export type MenuGroupOption =
export type TmNode = TreeNode<MenuOption, MenuGroupOption>
export type OnUpdateValue = <T extends string & number & (string | number)>(
value: T,
export type OnUpdateValue = (
value: string & number & (string | number),
item: MenuOption
) => void
export type OnUpdateKeys = <
T extends string[] & number[] & Array<string | number>
>(
keys: T
) => void
export type OnUpdateValueImpl = <T extends string | number | (string | number)>(
value: T,
export type OnUpdateKeys = (
keys: string[] & number[] & Array<string | number>
) => void
export type OnUpdateValueImpl = (
value: string | number | (string | number),
item: MenuOption
) => void
export type OnUpdateKeysImpl = <
T extends string[] | number[] | Array<string | number>
>(
keys: T
export type OnUpdateKeysImpl = (
keys: string[] | number[] | Array<string | number>
) => void

View File

@ -5,4 +5,30 @@ describe('n-menu', () => {
it('should work with import on demand', () => {
mount(NMenu)
})
it('props.onUpdateValue type', () => {
const stringCb = (v: string): void => {}
const numberCb = (v: number): void => {}
const snCb = (v: string | number): void => {}
const stringArrCb = (v: string[]): void => {}
const numberArrCb = (v: number[]): void => {}
const snArrCb = (v: Array<string | number>): void => {}
mount(NMenu, {
props: {
onUpdateValue: stringCb,
onUpdateExpandedKeys: stringArrCb
}
})
mount(NMenu, {
props: {
onUpdateValue: numberCb,
onUpdateExpandedKeys: numberArrCb
}
})
mount(NMenu, {
props: {
onUpdateValue: snCb,
onUpdateExpandedKeys: snArrCb
}
})
})
})

View File

@ -165,7 +165,11 @@ function createIconVNode (
{{
default: () =>
type === 'loading' ? (
<NBaseLoading clsPrefix={clsPrefix} scale={0.85} />
<NBaseLoading
clsPrefix={clsPrefix}
strokeWidth={24}
scale={0.85}
/>
) : (
iconMap[type]
)

View File

@ -72,32 +72,32 @@ export default defineComponent({
}
},
render () {
const { mergedClsPrefix } = this
const { mergedClsPrefix, $slots } = this
return (
<div style={this.cssVars as CSSProperties}>
<div class={`${mergedClsPrefix}-popconfirm__body`}>
{this.showIcon ? (
<div class={`${mergedClsPrefix}-popconfirm__icon`}>
<slot name="icon">
{renderSlot($slots, 'icon', undefined, () => [
<NBaseIcon clsPrefix={mergedClsPrefix}>
{{ default: () => <WarningIcon /> }}
</NBaseIcon>
</slot>
])}
</div>
) : null}
{renderSlot(this.$slots, 'default')}
{renderSlot($slots, 'default')}
</div>
<div class={`${mergedClsPrefix}-popconfirm__action`}>
{renderSlot(this.$slots, 'action', undefined, () => [
{renderSlot($slots, 'action', undefined, () => [
<NButton size="small" onClick={this.handleNegativeClick}>
{this.localizedNegativeText}
{{ default: () => this.localizedNegativeText }}
</NButton>,
<NButton
size="small"
type="primary"
onClick={this.handlePositiveClick}
>
{this.localizedPositiveText}
{{ default: () => this.localizedPositiveText }}
</NButton>
])}
</div>

View File

@ -28,7 +28,6 @@ processing
| indicator-text-color | `string` | `undefined` | |
| percentage | `number \| Array<number>` | `0` | |
| processing | `boolean` | `false` | |
| processing | `boolean` | `false` | |
| rail-color | `string \| string[]` | `undefined` | |
| rail-style | `string \| CSS \| Array<string \| CSS>` | `undefined` | |
| show-indicator | `boolean` | `true` | |

View File

@ -28,7 +28,6 @@ processing
| indicator-text-color | `string` | `undefined` | |
| percentage | `number \| Array<number>` | `0` | |
| processing | `boolean` | `false` | |
| processing | `boolean` | `false` | |
| rail-color | `string \| string[]` | `undefined` | |
| rail-style | `string \| CSS \| Array<string \| CSS>` | `undefined` | |
| show-indicator | `boolean` | `true` | |

View File

@ -295,14 +295,18 @@ export default defineComponent({
}
}
}
function handleHandleMouseMove (e: MouseEvent, handleIndex: 0 | 1): void {
function handleHandleMouseMove (
e: MouseEvent | TouchEvent,
handleIndex: 0 | 1
): void {
if (!handleRef1.value || !railRef.value) return
const x = 'touches' in e ? e.touches[0].clientX : e.clientX
const { width: handleWidth } = handleRef1.value.getBoundingClientRect()
const { width: railWidth, left: railLeft } =
railRef.value.getBoundingClientRect()
const { min, max, range } = props
const offsetRatio =
(e.clientX - railLeft - handleWidth / 2) / (railWidth - handleWidth)
(x - railLeft - handleWidth / 2) / (railWidth - handleWidth)
const newValue = min + (max - min) * offsetRatio
if (range) {
if (handleIndex === 0) {
@ -468,7 +472,9 @@ export default defineComponent({
}
doUpdateShow(true, false)
handleClicked1Ref.value = true
on('touchend', document, handleHandleMouseUp)
on('mouseup', document, handleHandleMouseUp)
on('touchmove', document, handleFirstHandleMouseMove)
on('mousemove', document, handleFirstHandleMouseMove)
}
function handleSecondHandleMouseDown (): void {
@ -477,19 +483,25 @@ export default defineComponent({
}
doUpdateShow(false, true)
handleClicked2Ref.value = true
on('touchend', document, handleHandleMouseUp)
on('mouseup', document, handleHandleMouseUp)
on('touchmove', document, handleSecondHandleMouseMove)
on('mousemove', document, handleSecondHandleMouseMove)
}
function handleHandleMouseUp (e: MouseEvent): void {
function handleHandleMouseUp (e: MouseEvent | TouchEvent): void {
if (
!handleRef1.value?.contains(e.target as Node) &&
(props.range ? !handleRef2.value?.contains(e.target as Node) : true)
(window.TouchEvent && e instanceof window.TouchEvent) ||
(!handleRef1.value?.contains(e.target as Node) &&
(props.range ? !handleRef2.value?.contains(e.target as Node) : true))
) {
doUpdateShow(false, false)
}
handleClicked2Ref.value = false
handleClicked1Ref.value = false
off('touchend', document, handleHandleMouseUp)
off('mouseup', document, handleHandleMouseUp)
off('touchmove', document, handleFirstHandleMouseMove)
off('touchmove', document, handleSecondHandleMouseMove)
off('mousemove', document, handleFirstHandleMouseMove)
off('mousemove', document, handleSecondHandleMouseMove)
}
@ -540,10 +552,10 @@ export default defineComponent({
}
}
}
function handleFirstHandleMouseMove (e: MouseEvent): void {
function handleFirstHandleMouseMove (e: MouseEvent | TouchEvent): void {
handleHandleMouseMove(e, 0)
}
function handleSecondHandleMouseMove (e: MouseEvent): void {
function handleSecondHandleMouseMove (e: MouseEvent | TouchEvent): void {
handleHandleMouseMove(e, 1)
}
function handleFirstHandleMouseEnter (): void {
@ -652,8 +664,11 @@ export default defineComponent({
})
})
onBeforeUnmount(() => {
off('touchmove', document, handleFirstHandleMouseMove)
off('touchmove', document, handleSecondHandleMouseMove)
off('mousemove', document, handleFirstHandleMouseMove)
off('mousemove', document, handleSecondHandleMouseMove)
off('touchend', document, handleHandleMouseUp)
off('mouseup', document, handleHandleMouseUp)
})
return {
@ -829,6 +844,7 @@ export default defineComponent({
style={this.firstHandleStyle}
onFocus={this.handleHandleFocus1}
onBlur={this.handleHandleBlur1}
onTouchstart={this.handleFirstHandleMouseDown}
onMousedown={this.handleFirstHandleMouseDown}
onMouseenter={this.handleFirstHandleMouseEnter}
onMouseleave={this.handleFirstHandleMouseLeave}
@ -883,6 +899,7 @@ export default defineComponent({
style={this.secondHandleStyle}
onFocus={this.handleHandleFocus2}
onBlur={this.handleHandleBlur2}
onTouchstart={this.handleSecondHandleMouseDown}
onMousedown={this.handleSecondHandleMouseDown}
onMouseenter={this.handleSecondHandleMouseEnter}
onMouseleave={this.handleSecondHandleMouseLeave}

View File

@ -116,8 +116,9 @@ export default defineComponent({
const barElRef = ref<HTMLElement | null>(null)
const scrollWrapperElRef = ref<HTMLElement | null>(null)
const addTabInstRef = ref<ComponentPublicInstance | null>(null)
const xScrollInstRef =
ref<(VXScrollInst & ComponentPublicInstance) | null>(null)
const xScrollInstRef = ref<(VXScrollInst & ComponentPublicInstance) | null>(
null
)
const leftReachedRef = ref(true)
const rightReachedRef = ref(true)
@ -511,7 +512,6 @@ function filterMapTabPanes (
if (vNode.key !== undefined) {
vNode.key = name
}
console.log(vNode.props)
if (useVShow) {
children.push(withDirectives(vNode, [[vShow, show]]))
} else if (show) {