Merge pull request #115 from TuSimple/freestyle

Freestyle
This commit is contained in:
07akioni 2020-04-28 23:04:05 +08:00 committed by GitHub Enterprise
commit a85ae5ded4
18 changed files with 434 additions and 63 deletions

View File

@ -1,4 +1,11 @@
# CHANGELOG
## 1.0.10 (2020-04-28)
### Features
- Add `arrow-placement` prop on `n-collapse`.
- Add `arrow` slot on `n-collapsed-item`.
### Fixes
- Fix the problem that detachable components detached in wrong place when nested like `modal > drawer > component`.
## 1.0.9 (2020-04-23)
### Features
- Add `autofocus` prop on `n-input`.

View File

@ -1,4 +1,11 @@
# CHANGELOG
## 1.0.10 (2020-04-28)
### Features
- 为 `n-collapse` 增加了 `arrow-placement` 属性
- 为 `n-collapsed-item` 增加了`arrow` slot
### Fixes
- 解决了可卸载组件在嵌套成 `modal > drawer > component` 样子的时候会被卸载到错误位置的问题
## 1.0.9 (2020-04-23)
### Features
- 为 `n-input` 增加了 `autofocus` 选项

View File

@ -0,0 +1,27 @@
# Arrow Placement
Use `arrow-placement` to set the placement of arrow.
```html
<n-collapse
v-model="activeNames"
arrow-placement="right"
>
<n-collapse-item title="right" name="1">
<div>good</div>
</n-collapse-item>
<n-collapse-item title="right" name="2">
<div>nice</div>
</n-collapse-item>
<n-collapse-item title="right" name="3">
<div>very good</div>
</n-collapse-item>
</n-collapse>
```
```js
export default {
data() {
return {
activeNames: []
}
}
}
```

View File

@ -3,6 +3,7 @@ I saw it appears in many side control panels.
## Demos
```demo
basic
arrow-placement
accordion
nested
item-header-click
@ -16,14 +17,16 @@ item-header-click
### Collapse
|Name|Type|Default|Description|
|-|-|-|-|
|theme|`'light' \| 'dark'`|`null`||
|expanded-names|`Array`|`null`||
|accordion|`boolean`|`false`||
|arrow-placement|`'left' \| 'right'`|`'left'`||
|expanded-names|`Array<string \| number>`|`null`||
|theme|`'light' \| 'dark'`|`null`||
### Collapse Item
|Name|Type|Default|Description|
|-|-|-|-|
|title|`string \| number`|`null`||
|title|`string`|`null`||
|name|`string \| number`||**required**|
## Slots
@ -37,6 +40,7 @@ item-header-click
|-|-|-|
|default|`()`||
|header|`()`||
|arrow|`({ collapsed: boolean })`||
## Event
### Collapse Event

View File

@ -0,0 +1,27 @@
# 箭头位置
使用 `arrow-placement` 来设定箭头的位置。
```html
<n-collapse
v-model="activeNames"
arrow-placement="right"
>
<n-collapse-item title="青铜" name="1">
<div>可以</div>
</n-collapse-item>
<n-collapse-item title="白银" name="2">
<div>很好</div>
</n-collapse-item>
<n-collapse-item title="黄金" name="3">
<div>真棒</div>
</n-collapse-item>
</n-collapse>
```
```js
export default {
data() {
return {
activeNames: []
}
}
}
```

View File

@ -3,6 +3,7 @@
## 演示
```demo
basic
arrow-placement
accordion
nested
item-header-click
@ -16,15 +17,17 @@ item-header-click
### Collapse Props
|名称|类型|默认值|说明|
|-|-|-|-|
|theme|`'light' \| 'dark'`|`null`||
|expanded-names|`Array`|`null`||
|accordion|`boolean`|`false`||
|arrow-placement|`'left' \| 'right'`|`'left'`||
|expanded-names|`Array<string \| number>`|`null`||
|theme|`'light' \| 'dark'`|`null`||
### Collapse Item Props
|名称|类型|默认值|说明|
|-|-|-|-|
|title|`string \| number`|`null`||
|name|`string \| number`||**必需**|
|title|`string`|`null`||
## Slots
### Collapse Slots
@ -37,6 +40,7 @@ item-header-click
|-|-|-|
|default|`()`||
|header|`()`||
|arrow|`({ collapsed: boolean })`||
## Event
### Collapse Event

View File

@ -78,7 +78,12 @@ Accept all props from form-item & [Col](n-row#Col-Props)
About AsyncValidatorOptions, see <n-a href="https://github.com/yiminghe/async-validator">async-validator</n-a>.
## Slots
### Form, Form Item, Form Item Row, Form Item Col Methods
### Form, Form Item, Form Item Row, Form Item Col Slots
|Name|Parameters|Description|
|-|-|-|
|default|`()`||
|default|`()`||
### Form Item, Form Item Row, Form Item Col Slots
|Name|Parameters|Description|
|-|-|-|
|label|`()`||

View File

@ -78,7 +78,12 @@ validator-debug
关于 AsyncValidatorOptions参考 <n-a href="https://github.com/yiminghe/async-validator">async-validator</n-a>
## Slots
### Form, Form Item, Form Item Row, Form Item Col Methods
### Form, Form Item, Form Item Row, Form Item Col Slots
|名称|参数|说明|
|-|-|-|
|default|`()`||
|default|`()`||
### Form Item, Form Item Row, Form Item Col Slots
|名称|参数|说明|
|-|-|-|
|label|`()`||

View File

@ -0,0 +1,255 @@
# Drawer Debug
```html
<n-button @click="modalActive = !modalActive">Toggle</n-button>
<n-modal
title="Dark Modal Debug"
preset="card"
v-model="modalActive"
:overlay-style="{ marginTop: '24px', marginBottom: '24px', width: '800px' }"
>
<n-button @click="drawerActive = !drawerActive">Open Drawer</n-button>
<n-drawer v-model="drawerActive">
<n-radio-group v-model="size" name="top-size" style="margin-bottom: 12px;">
<n-radio-button value="small"></n-radio-button>
<n-radio-button value="medium" ></n-radio-button>
<n-radio-button value="large"></n-radio-button>
</n-radio-group>
<n-form
:model="model"
:rules="rules"
:size="size"
ref="form"
label-placement="top"
>
<n-row :gutter="24">
<n-form-item-col :span="12" label="Input" path="inputValue">
<n-input placeholder="Input" v-model="model.inputValue" />
</n-form-item-col :span="12">
<n-form-item-col :span="12" label="Textarea" path="textareaValue">
<n-input placeholder="Textarea" v-model="model.textareaValue" type="textarea"
:autosize="{
minRows: 3,
maxRows: 5
}"
/>
</n-form-item-col>
</n-row>
<n-row :gutter="24">
<n-form-item-col :span="12" label="Select" path="selectValue">
<n-select placeholder="Select" :options="generalOptions" v-model="model.selectValue"/>
</n-form-item-col>
<n-form-item-col :span="12" label="Multiple Select" path="multipleSelectValue">
<n-select placeholder="Select" :options="generalOptions" v-model="model.multipleSelectValue" multiple/>
</n-form-item-col>
</n-row>
<n-row :gutter="24">
<n-form-item-col :span="12" label="Datetime" path="datetimeValue">
<n-date-picker type="datetime" v-model="model.datetimeValue"/>
</n-form-item-col>
<n-form-item-col :span="12" label="Switch" path="switchValue">
<n-switch v-model="model.switchValue" />
</n-form-item-col>
</n-row>
<n-row :gutter="24">
<n-form-item-col :span="12" label="Checkbox Group" path="checkboxGroupValue">
<n-checkbox-group v-model="model.checkboxGroupValue">
<n-checkbox value="Option 1">Option 1</n-checkbox>
<n-checkbox value="Option 2">Option 2</n-checkbox>
<n-checkbox value="Option 3">Option 3</n-checkbox>
</n-checkbox-group>
</n-form-item-col>
<n-form-item-col :span="12" label="Radio Group" path="radioGroupValue">
<n-radio-group v-model="model.radioGroupValue" name="radiogroup1">
<n-radio value="Radio 1">Radio 1</n-radio>
<n-radio value="Radio 2">Radio 2</n-radio>
<n-radio value="Radio 3">Radio 3</n-radio>
</n-radio-group>
</n-form-item-col>
</n-row>
<n-row :gutter="24">
<n-form-item-col :span="12" label="Radio Button Group" path="radioGroupValue">
<n-radio-group v-model="model.radioGroupValue" name="radiogroup2">
<n-radio-button value="Radio 1">Radio 1</n-radio-button>
<n-radio-button value="Radio 2">Radio 2</n-radio-button>
<n-radio-button value="Radio 3">Radio 3</n-radio-button>
</n-radio-group>
</n-form-item-col>
<n-form-item-col :span="12" label="Input Number" path="inputNumberValue">
<n-input-number v-model="model.inputNumberValue"/>
</n-form-item-col>
</n-row>
<n-row :gutter="24">
<n-form-item-col :span="12" label="Time Picker" path="timePickerValue">
<n-time-picker v-model="model.timePickerValue" />
</n-form-item-col>
<n-form-item-col :span="12" label="Slider" path="sliderValue">
<n-slider v-model="model.sliderValue" :step="5"/>
</n-form-item-col>
</n-row>
<n-row :gutter="24">
<n-form-item-col :span="14" label="Transfer" path="transferValue">
<n-transfer
style="width: 100%;"
v-model="model.transferValue"
:options="generalOptions"
/>
</n-form-item-col>
<n-form-item-col :span="5" label="Nested Path" path="nestedValue.path1">
<n-cascader placeholder="Nested Path 1" v-model="model.nestedValue.path1" :options="cascaderOptions"/>
</n-form-item-col>
<n-form-item-col :span="5" path="nestedValue.path2">
<n-select placeholder="Nested Path 2" :options="generalOptions" v-model="model.nestedValue.path2"/>
</n-form-item-col>
</n-row>
<n-row>
<n-col :span="24">
<div style="display: flex; justify-content: flex-end;">
<n-button @click="handleValidateButtonClick" round type="primary">验证</n-button>
</div>
</n-col>
</n-row>
</n-form>
</n-drawer>
</n-modal>
```
```js
export default {
data () {
return {
drawerActive: false,
modalActive: false,
size: 'medium',
model: {
inputValue: null,
textareaValue: null,
selectValue: null,
multipleSelectValue: null,
datetimeValue: null,
nestedValue: {
path1: null,
path2: null
},
switchValue: false,
checkboxGroupValue: null,
radioGroupValue: null,
radioButtonGroupValue: null,
inputNumberValue: null,
timePickerValue: null,
sliderValue: 0,
transferValue: null
},
generalOptions: [
'groode',
'veli good',
'emazing',
'lidiculous'
].map(v => ({
label: v,
value: v
})),
cascaderOptions: [
{
label: 'groode',
value: 'groode',
children: [
{
label: 'veli good',
value: 'veli good'
}
]
}
],
rules: {
inputValue: {
required: true,
trigger: ['blur', 'input'],
message: '请输入 inputValue'
},
textareaValue: {
required: true,
trigger: ['blur', 'input'],
message: '请输入 textareaValue'
},
selectValue: {
required: true,
trigger: ['blur', 'change'],
message: '请选择 selectValue'
},
multipleSelectValue: {
type: 'array',
required: true,
trigger: ['blur', 'change'],
message: '请选择 multipleSelectValue'
},
datetimeValue: {
type: 'number',
required: true,
trigger: ['blur', 'change'],
message: '请输入 datetimeValue'
},
nestedValue: {
path1: {
required: true,
trigger: ['blur', 'input'],
message: '请输入 nestedValue.path1'
},
path2: {
required: true,
trigger: ['blur', 'change'],
message: '请输入 nestedValue.path2'
}
},
checkboxGroupValue: {
type: 'array',
required: true,
trigger: 'change',
message: '请选择 checkboxGroupValue'
},
radioGroupValue: {
required: true,
trigger: 'change',
message: '请选择 radioGroupValue'
},
radioButtonGroupValue: {
required: true,
trigger: 'change',
message: '请选择 radioButtonGroupValue'
},
inputNumberValue: {
type: 'number',
required: true,
trigger: ['blur', 'change'],
message: '请输入 inputNumberValue'
},
timePickerValue: {
type: 'number',
required: true,
trigger: ['blur', 'change'],
message: '请输入 timePickerValue'
},
sliderValue: 0,
transferValue: {
type: 'array',
required: true,
trigger: 'change',
message: '请输入 transferValue'
}
}
}
},
methods: {
handleValidateButtonClick (e) {
e.preventDefault()
this.$refs.form.validate(errors => {
if (!errors) {
this.$NMessage.success('验证成功')
} else {
console.log(errors)
this.$NMessage.error('验证失败')
}
})
}
}
}
```

View File

@ -13,6 +13,7 @@ dark1-debug
dark2-debug
dark3-debug
dark4-debug
drawer-debug
```
## V-model
|Prop|Event|

View File

@ -1,6 +1,6 @@
{
"name": "naive-ui",
"version": "1.0.9",
"version": "1.0.10",
"description": "A Vue UI Framework. Caring About Styles, Themed, Batteries Included.",
"main": "lib/index.js",
"module": "es/index.js",

View File

@ -23,6 +23,12 @@ export default {
type: [Array, String],
default: null
},
arrowPlacement: {
validator (value) {
return ['left', 'right'].includes(value)
},
default: 'left'
},
accordion: {
type: Boolean,
default: false

View File

@ -2,25 +2,34 @@
<div
class="n-collapse-item"
:class="{
'n-collapse-item--active': !collapse,
'n-collapse-item--active': !collapsed,
[`n-collapse-item--${arrowPlacement}-arrow-placement`]: true
}"
>
<div
class="n-collapse-item__header"
:class="{
'n-collapse-item__header--active': !collapse
'n-collapse-item__header--active': !collapsed
}"
@click="handleClick"
>
<n-icon type="ios-arrow-forward">
<ios-arrow-forward />
</n-icon><slot name="header">
<slot v-if="arrowPlacement === 'right'" name="header">
{{ title }}
</slot>
<div class="n-collapse-item-arrow">
<slot name="arrow" :collapsed="collapsed">
<n-icon type="ios-arrow-forward">
<ios-arrow-forward />
</n-icon>
</slot>
</div>
<slot v-if="arrowPlacement === 'left'" name="header">
{{ title }}
</slot>
</div>
<fade-in-height-expand-transition>
<div
v-if="!collapse"
v-if="!collapsed"
class="n-collapse-item__content-wrapper"
>
<div
@ -64,7 +73,10 @@ export default {
}
},
computed: {
collapse () {
arrowPlacement () {
return this.NCollapse.arrowPlacement
},
collapsed () {
const NCollapse = this.NCollapse
if (NCollapse && Array.isArray(NCollapse.expandedNames)) {
const itemName = this.name
@ -77,7 +89,7 @@ export default {
handleClick (e) {
const NCollapse = this.NCollapse
if (NCollapse) {
NCollapse.toggleItem(this.collapse, this.name, e)
NCollapse.toggleItem(this.collapsed, this.name, e)
}
}
}

View File

@ -97,6 +97,7 @@ document.documentElement.addEventListener('click', (e) => {
}, true)
export default {
name: 'NModalContent',
components: {
NScrollbar,
NConfirm,

View File

@ -1,3 +1,5 @@
import { getPortalTarget } from '../../../_utils/component/portal'
function cleanUp (content, target) {
if (content && target && target.contains(content)) {
target.removeChild(content)
@ -6,14 +8,6 @@ function cleanUp (content, target) {
export default {
name: 'NBasePortal',
inject: {
NModal: {
default: null
},
NDrawer: {
default: null
}
},
props: {
onMounted: {
type: Function,
@ -22,15 +16,7 @@ export default {
transferTarget: {
type: Function,
default: function () {
const NModal = this.NModal
if (NModal) {
return NModal.getDetachTarget()
}
const NDrawer = this.NDrawer
if (NDrawer) {
return NDrawer.getDetachTarget()
}
return document.body
return getPortalTarget(this)
}
}
},
@ -47,7 +33,7 @@ export default {
* Since content may be detached in modal, waiting animation done is
* important. A more elegant solution is needed.
*/
if (this.NModal || this.NDrawer) {
if (getPortalTarget(this, true)) {
setTimeout(() => {
cleanUp(content, target)
}, 300)

View File

@ -1,4 +1,5 @@
import withapp from './withapp'
import { getPortalTarget } from '../_utils/component/portal'
function cleanUp (content, target) {
if (content && target && target.contains(content)) {
@ -16,27 +17,11 @@ function cleanUp (content, target) {
*/
export default {
mixins: [ withapp ],
inject: {
NModal: {
default: null
},
NDrawer: {
default: null
}
},
props: {
detachTarget: {
type: Function,
default: function () {
const NModal = this.NModal
if (NModal) {
return NModal.getDetachTarget()
}
const NDrawer = this.NDrawer
if (NDrawer) {
return NDrawer.getDetachTarget()
}
return document.body
return getPortalTarget(this)
}
},
detachable: {
@ -103,7 +88,7 @@ export default {
* Since content may be detached in modal, waiting animation done is
* important. A more elegant solution is needed.
*/
if (this.NModal || this.NDrawer) {
if (getPortalTarget(this, true)) {
setTimeout(() => {
cleanUp(content, target)
}, 300)

View File

@ -0,0 +1,19 @@
/**
* @param {VueComponentInstance} instance
* @param {boolean} returnBoolean if set to true, it returns whether the instance
* is inside a modal or a drawer
*/
export function getPortalTarget (instance, returnBoolean = false) {
let cursor = instance.$parent
while (cursor) {
const componentName = cursor.$options.name
if (
componentName === 'NModalContent' ||
componentName === 'NDrawerContent'
) {
return returnBoolean ? true : cursor.getDetachTarget()
}
cursor = cursor.$parent
}
return returnBoolean ? false : document.body
}

View File

@ -19,6 +19,20 @@
padding-top: 0px;
}
}
@include m(left-arrow-placement) {
@include e(header) {
@include b(collapse-item-arrow) {
margin-right: 4px;
}
}
}
@include m(right-arrow-placement) {
@include e(header) {
@include b(collapse-item-arrow) {
margin-left: 4px;
}
}
}
@include b(collapse-item) {
margin-left: 32px;
}
@ -29,8 +43,10 @@
@include m(active) {
@include e(header) {
@include m(active) {
@include b(icon) {
transform: rotate(90deg);
@include b(collapse-item-arrow) {
@include b(icon) {
transform: rotate(90deg);
}
}
}
}
@ -48,15 +64,19 @@
position: relative;
cursor: pointer;
padding: 16px 0 0 0;
@include b(icon) {
transition: transform .15s $--n-ease-in-out-cubic-bezier, $--n-icon-transition;
font-size: 16px;
margin-right: 4px;
@include b(collapse-item-arrow) {
display: flex;
@include b(icon) {
transition: transform .15s $--n-ease-in-out-cubic-bezier, $--n-icon-transition;
font-size: 16px;
}
}
}
color: $--collapse-header-text-color;
@include b(icon) {
fill: $--collapse-header-text-color;
@include b(collapse-item-arrow) {
@include b(icon) {
fill: $--collapse-header-text-color;
}
}
}
@include e(content-inner) {