feat: enhance the divider dialogbox treemenu function (#2758)
This commit is contained in:
parent
6e29e24dc3
commit
5f35800f62
|
@ -246,6 +246,36 @@ export default {
|
|||
mode: ['pc'],
|
||||
pcDemo: 'dialog-width'
|
||||
},
|
||||
{
|
||||
name: 'custom-style',
|
||||
type: 'string',
|
||||
defaultValue: ``,
|
||||
desc: {
|
||||
'zh-CN': '自定义实现双层抽屉',
|
||||
'en-US': 'Custom Styles'
|
||||
},
|
||||
meta: {
|
||||
stable: '3.21.0'
|
||||
},
|
||||
mode: ['pc', 'mobile-first'],
|
||||
pcDemo: 'double-dialog-height',
|
||||
mfDemo: 'double-dialog-height'
|
||||
},
|
||||
{
|
||||
name: 'no-animation',
|
||||
type: 'string',
|
||||
defaultValue: ``,
|
||||
desc: {
|
||||
'zh-CN': '是否开启动画',
|
||||
'en-US': 'Indicates whether to enable animation'
|
||||
},
|
||||
meta: {
|
||||
stable: '3.21.0'
|
||||
},
|
||||
mode: ['pc', 'mobile-first'],
|
||||
pcDemo: 'double-dialog-height',
|
||||
mfDemo: 'double-dialog-height'
|
||||
},
|
||||
{
|
||||
name: 'dialog-transition',
|
||||
type: 'string',
|
||||
|
|
|
@ -10,11 +10,13 @@ export default {
|
|||
type: 'string',
|
||||
defaultValue: "'solid'",
|
||||
desc: {
|
||||
'zh-CN': '设置分隔线的样式,该属性的可选值为 solid / dashed',
|
||||
'en-US': 'Set the style of the separator line, with optional values of solid/dashed for this property'
|
||||
'zh-CN': '设置分隔线的样式,该属性的可选值为 solid / dashed / dotted',
|
||||
'en-US':
|
||||
'Set the style of the separator line, with optional values of solid/dashed/dotted for this property'
|
||||
},
|
||||
mode: ['pc'],
|
||||
pcDemo: 'custom-style'
|
||||
mode: ['pc', 'mobile-first'],
|
||||
pcDemo: 'custom-style',
|
||||
mfDemo: 'type'
|
||||
},
|
||||
{
|
||||
name: 'color',
|
||||
|
@ -24,8 +26,9 @@ export default {
|
|||
'zh-CN': '设置分隔线的颜色',
|
||||
'en-US': 'Set the color of the divider.'
|
||||
},
|
||||
mode: ['pc'],
|
||||
pcDemo: 'custom-style'
|
||||
mode: ['pc', 'mobile-first'],
|
||||
pcDemo: 'custom-style',
|
||||
mfDemo: 'color'
|
||||
},
|
||||
{
|
||||
name: 'content-background-color',
|
||||
|
@ -58,8 +61,9 @@ export default {
|
|||
'en-US':
|
||||
'Set the position of the separator text, with optional values of left/center/right for this attribute'
|
||||
},
|
||||
mode: ['pc'],
|
||||
pcDemo: 'content-position'
|
||||
mode: ['pc', 'mobile-first'],
|
||||
pcDemo: 'content-position',
|
||||
mfDemo: 'content-position'
|
||||
},
|
||||
{
|
||||
name: 'direction',
|
||||
|
@ -70,8 +74,83 @@ export default {
|
|||
'en-US':
|
||||
'Set the direction of the divider; the possible values for this property are "horizontal" or "vertical"'
|
||||
},
|
||||
mode: ['pc', 'mobile-first'],
|
||||
pcDemo: 'direction',
|
||||
mfDemo: 'vertical'
|
||||
},
|
||||
{
|
||||
name: 'margin',
|
||||
type: 'string',
|
||||
defaultValue: '',
|
||||
desc: {
|
||||
'zh-CN': '设置分割线上下左右的边距',
|
||||
'en-US': 'Sets the margins of the split line'
|
||||
},
|
||||
meta: {
|
||||
stable: '3.21.0'
|
||||
},
|
||||
mode: ['pc', 'mobile-first'],
|
||||
pcDemo: 'custom-style',
|
||||
mfDemo: 'divider-margin'
|
||||
},
|
||||
{
|
||||
name: 'offset',
|
||||
type: 'string',
|
||||
defaultValue: '',
|
||||
desc: {
|
||||
'zh-CN': '设置文本位置偏移量,需同时配合`text-position`属性使用,以确定偏移的方向',
|
||||
'en-US':
|
||||
'Sets the text position offset. This parameter must be used together with the `text-position` attribute to determine the offset direction'
|
||||
},
|
||||
meta: {
|
||||
stable: '3.21.0'
|
||||
},
|
||||
mode: ['pc', 'mobile-first'],
|
||||
pcDemo: 'content-position',
|
||||
mfDemo: 'offset'
|
||||
},
|
||||
{
|
||||
name: 'height',
|
||||
type: 'string',
|
||||
defaultValue: '',
|
||||
desc: {
|
||||
'zh-CN': '设置整体的高度',
|
||||
'en-US': 'Sets the overall height'
|
||||
},
|
||||
meta: {
|
||||
stable: '3.21.0'
|
||||
},
|
||||
mode: ['pc'],
|
||||
pcDemo: 'direction'
|
||||
pcDemo: 'custom-style'
|
||||
},
|
||||
{
|
||||
name: 'font-size',
|
||||
type: 'string',
|
||||
defaultValue: '14px',
|
||||
desc: {
|
||||
'zh-CN': '文本字体大小',
|
||||
'en-US': 'Text font size'
|
||||
},
|
||||
meta: {
|
||||
stable: '3.21.0'
|
||||
},
|
||||
mode: ['pc'],
|
||||
pcDemo: 'custom-style'
|
||||
},
|
||||
{
|
||||
name: 'status',
|
||||
type: 'string',
|
||||
defaultValue: '',
|
||||
desc: {
|
||||
'zh-CN': '分割线状态',
|
||||
'en-US': 'Splitting Line Status'
|
||||
},
|
||||
meta: {
|
||||
stable: '3.21.0'
|
||||
},
|
||||
mode: ['pc', 'mobile-first'],
|
||||
pcDemo: 'status',
|
||||
mfDemo: 'status'
|
||||
}
|
||||
],
|
||||
events: [],
|
||||
|
|
|
@ -219,10 +219,10 @@ export default {
|
|||
},
|
||||
{
|
||||
name: 'validate-on-rule-change',
|
||||
type: 'boolean',
|
||||
type: 'boolean | "deep"',
|
||||
defaultValue: 'true',
|
||||
desc: {
|
||||
'zh-CN': '是否在 rules 属性改变后立即触发一次验证',
|
||||
'zh-CN': '是否在 rules 属性改变后立即触发一次验证("deep"选项新增于3.21.0)',
|
||||
'en-US': 'Whether to trigger a verification immediately after the rules attribute is changed'
|
||||
},
|
||||
mode: ['pc', 'mobile', 'mobile-first'],
|
||||
|
|
|
@ -0,0 +1,128 @@
|
|||
<template>
|
||||
<div>
|
||||
<tiny-button @click="changModdeFn" type="primary">当前为 {{ flag }} 模式</tiny-button>
|
||||
<tiny-button @click="changFn">双层抽屉 </tiny-button>
|
||||
<tiny-dialog-box
|
||||
:visible="boxVisibility"
|
||||
right-slide
|
||||
@update:visible="boxVisibility = $event"
|
||||
title="父弹窗"
|
||||
width="30%"
|
||||
:custom-style="customStyle1"
|
||||
>
|
||||
<span>父弹窗内容</span>
|
||||
<tiny-dialog-box
|
||||
append-to-body
|
||||
right-slide
|
||||
:modal="false"
|
||||
:close-on-click-modal="false"
|
||||
no-animation
|
||||
:visible="boxVisibility2"
|
||||
:custom-style="customStyle2"
|
||||
@close="dialogClose"
|
||||
@update:visible="boxVisibility2 = $event"
|
||||
title="子弹窗"
|
||||
width="300px"
|
||||
>
|
||||
<span>子弹窗内容</span>
|
||||
<template #footer>
|
||||
<tiny-button type="primary" @click="boxVisibility2 = false"> 确定 </tiny-button>
|
||||
</template>
|
||||
</tiny-dialog-box>
|
||||
<template #footer>
|
||||
<tiny-button @click="boxVisibility = false">取消</tiny-button>
|
||||
<tiny-button type="primary" @click="openDialog"> 子弹窗 </tiny-button>
|
||||
</template>
|
||||
</tiny-dialog-box>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { Button, DialogBox } from '@opentiny/vue'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
TinyButton: Button,
|
||||
TinyDialogBox: DialogBox
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
flag: 'auto',
|
||||
boxVisibility: false,
|
||||
customStyle1: {},
|
||||
customStyle2: {},
|
||||
boxVisibility2: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
changFn() {
|
||||
this.boxVisibility = true
|
||||
},
|
||||
changModdeFn() {
|
||||
this.flag = this.flag === 'full' ? 'auto' : 'full'
|
||||
},
|
||||
openDialog() {
|
||||
if (this.flag === 'full') {
|
||||
this.customStyle1 = {
|
||||
right: '8px',
|
||||
bottom: '8px',
|
||||
top: '8px',
|
||||
height: 'auto',
|
||||
borderRadius: '8px',
|
||||
transition: 'right 0.2s ease-in-out'
|
||||
}
|
||||
this.customStyle2 = {
|
||||
bottom: '8px',
|
||||
top: '8px',
|
||||
height: 'auto',
|
||||
borderRadius: '8px',
|
||||
opacity: 0
|
||||
}
|
||||
const rightW = document.body.offsetWidth * 0.3
|
||||
this.customStyle1.right = -rightW + 80 + 'px'
|
||||
this.customStyle2.right = rightW + 'px'
|
||||
this.customStyle2.transition = 'right 200ms ease-in-out opacity 100ms linear'
|
||||
this.boxVisibility2 = true
|
||||
|
||||
setTimeout(() => {
|
||||
this.customStyle2.right = '85px'
|
||||
}, 10)
|
||||
|
||||
setTimeout(() => {
|
||||
this.customStyle2.opacity = 1
|
||||
}, 100)
|
||||
} else {
|
||||
this.customStyle1 = {
|
||||
right: '8px',
|
||||
bottom: '8px',
|
||||
top: '8px',
|
||||
height: 'auto',
|
||||
borderRadius: '8px',
|
||||
transition: 'right 0.2s ease-in-out'
|
||||
}
|
||||
this.customStyle2 = {
|
||||
bottom: '8px',
|
||||
top: 'unset',
|
||||
height: 'auto',
|
||||
borderRadius: '8px',
|
||||
opacity: 0
|
||||
}
|
||||
const rightW = document.body.offsetWidth * 0.3
|
||||
this.customStyle2.right = rightW + 46 + 'px'
|
||||
this.customStyle2.transition = 'opacity 100ms linear'
|
||||
this.boxVisibility2 = true
|
||||
|
||||
setTimeout(() => {
|
||||
this.customStyle2.opacity = 1
|
||||
}, 100)
|
||||
}
|
||||
},
|
||||
dialogClose() {
|
||||
setTimeout(() => {
|
||||
this.customStyle1.right = '8px'
|
||||
this.customStyle2.opacity = 0
|
||||
}, 50)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -82,6 +82,19 @@ export default {
|
|||
'en-US': '<p>code>default</code>: content default slot. <code>footer</code>: bottom slot</p>'
|
||||
},
|
||||
codeFiles: ['dialog-slot.vue']
|
||||
},
|
||||
{
|
||||
demoId: 'double-dialog-height',
|
||||
name: {
|
||||
'zh-CN': '右侧双层弹框',
|
||||
'en-US': 'Double-layer dialog box on the right'
|
||||
},
|
||||
desc: {
|
||||
'zh-CN': '右侧弹窗分两种情况,父级弹框自动缩进,子级弹框高度撑满。父级弹框不缩进,子级弹框高度自适应。',
|
||||
'en-US':
|
||||
'There are two types of pop-up windows on the right. The parent pop-up boxes are automatically indented, and the child pop-up boxes are full. The parent dialog box is not indented, and the height of the child dialog box is adaptive.'
|
||||
},
|
||||
codeFiles: ['double-dialog-height.vue']
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
<template>
|
||||
<div>
|
||||
<p>基础使用</p>
|
||||
<tiny-divider> </tiny-divider>
|
||||
<br />
|
||||
<p>带文本分割线</p>
|
||||
<tiny-divider> 分割线 </tiny-divider>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { Divider } from '@opentiny/vue'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
TinyDivider: Divider
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,17 @@
|
|||
<template>
|
||||
<div>
|
||||
<tiny-divider color="#55ccd9"></tiny-divider>
|
||||
<br />
|
||||
<tiny-divider color="#eb74df"> 分割线 </tiny-divider>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { Divider } from '@opentiny/vue'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
TinyDivider: Divider
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,17 @@
|
|||
<template>
|
||||
<div>
|
||||
<tiny-divider> 分割线 </tiny-divider>
|
||||
<tiny-divider content-position="left"> 分割线 </tiny-divider>
|
||||
<tiny-divider content-position="right"> 分割线 </tiny-divider>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { Divider } from '@opentiny/vue'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
TinyDivider: Divider
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,19 @@
|
|||
<template>
|
||||
<div>
|
||||
<p>
|
||||
豫章故郡,洪都新府。星分翼轸,地接衡庐。襟三江而带五湖,控蛮荆而引瓯越。物华天宝,龙光射牛斗之墟;人杰地灵,徐孺下陈蕃之榻;
|
||||
</p>
|
||||
<tiny-divider margin="20px 0"> 分割线 </tiny-divider>
|
||||
<p>雄州雾列,俊采星驰。台隍枕夷夏之交,宾主尽东南之美。都督阎公之雅望,棨戟遥临;宇文新州之懿范,襜帷暂驻;</p>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { Divider } from '@opentiny/vue'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
TinyDivider: Divider
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,17 @@
|
|||
<template>
|
||||
<div>
|
||||
<tiny-divider content-position="left" offset="20%"> 分割线 </tiny-divider>
|
||||
<tiny-divider content-position="left" offset="-14px"> 文本左偏移 </tiny-divider>
|
||||
<tiny-divider content-position="right" offset="-14px"> 文本右偏移 </tiny-divider>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { Divider } from '@opentiny/vue'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
TinyDivider: Divider
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,19 @@
|
|||
<template>
|
||||
<div>
|
||||
<tiny-divider> default </tiny-divider>
|
||||
<tiny-divider status="success"> success </tiny-divider>
|
||||
<tiny-divider status="error"> error </tiny-divider>
|
||||
<tiny-divider status="warning"> warning </tiny-divider>
|
||||
<tiny-divider status="info"> info </tiny-divider>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { Divider } from '@opentiny/vue'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
TinyDivider: Divider
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,17 @@
|
|||
<template>
|
||||
<div>
|
||||
<tiny-divider> 分割线 </tiny-divider>
|
||||
<tiny-divider border-style="dashed"> dash线 </tiny-divider>
|
||||
<tiny-divider border-style="dotted"> dotted线 </tiny-divider>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { Divider } from '@opentiny/vue'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
TinyDivider: Divider
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,34 @@
|
|||
<template>
|
||||
<div>
|
||||
<div>
|
||||
指南
|
||||
<tiny-divider direction="vertical" status="success"> </tiny-divider>
|
||||
组件
|
||||
<tiny-divider direction="vertical" status="success"> </tiny-divider>
|
||||
主题
|
||||
<tiny-divider direction="vertical" status="success"> </tiny-divider>
|
||||
资源
|
||||
</div>
|
||||
<br />
|
||||
<br />
|
||||
<div class="divider-wrap">
|
||||
Web 开发
|
||||
<tiny-divider direction="vertical"> </tiny-divider>
|
||||
卡片开发
|
||||
<tiny-divider direction="vertical"> </tiny-divider>
|
||||
移动开发
|
||||
<tiny-divider direction="vertical"> </tiny-divider>
|
||||
设计工具
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { Divider } from '@opentiny/vue'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
TinyDivider: Divider
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,7 @@
|
|||
---
|
||||
title: Divider 分割线
|
||||
---
|
||||
|
||||
# Divider 分割线
|
||||
|
||||
<div>Divider 分割线组件,用于对不同内容的分隔。</div>
|
|
@ -0,0 +1,7 @@
|
|||
---
|
||||
title: Divider split line
|
||||
---
|
||||
|
||||
# Divider split line
|
||||
|
||||
<div>Divider Splitting line component, which is used to separate different contents.</div>
|
|
@ -0,0 +1,111 @@
|
|||
export default {
|
||||
column: '2',
|
||||
owner: '',
|
||||
demos: [
|
||||
{
|
||||
demoId: 'basic-usage',
|
||||
name: {
|
||||
'zh-CN': '基本用法',
|
||||
'en-US': 'Basic Usage'
|
||||
},
|
||||
desc: {
|
||||
'zh-CN': '带文本的分割线',
|
||||
'en-US': 'Splitting line with text'
|
||||
},
|
||||
codeFiles: ['basic-usage.vue']
|
||||
},
|
||||
{
|
||||
demoId: 'divider-margin',
|
||||
name: {
|
||||
'zh-CN': '边距用法',
|
||||
'en-US': 'Margin Usage'
|
||||
},
|
||||
desc: {
|
||||
'zh-CN': '通过<code>margin</code>属性可以设置分割线上下左右的边距。',
|
||||
'en-US': 'You can use the <code>margin</code> attribute to set the margins of the split line.'
|
||||
},
|
||||
codeFiles: ['divider-margin.vue']
|
||||
},
|
||||
{
|
||||
demoId: 'color',
|
||||
name: {
|
||||
'zh-CN': '颜色用法',
|
||||
'en-US': 'Color Usage'
|
||||
},
|
||||
desc: {
|
||||
'zh-CN': '通过<code>color</code>属性可以自定义分割线颜色。',
|
||||
'en-US': 'You can use the <code>color</code> attribute to customize the color of the split line.'
|
||||
},
|
||||
codeFiles: ['color.vue']
|
||||
},
|
||||
{
|
||||
demoId: 'offset',
|
||||
name: {
|
||||
'zh-CN': '偏移量用法',
|
||||
'en-US': 'Offset Usage'
|
||||
},
|
||||
desc: {
|
||||
'zh-CN':
|
||||
'通过<code>offset</code>属性可以设置文本位置偏移量,需同时配合<code>content-position</code>属性使用,以确定偏移的方向。',
|
||||
'en-US':
|
||||
'<code>offset</code> can be used to set the text position offset. It must be used together with the <code>content-position</code> attribute to determine the offset direction.'
|
||||
},
|
||||
codeFiles: ['offset.vue']
|
||||
},
|
||||
{
|
||||
demoId: 'type',
|
||||
name: {
|
||||
'zh-CN': '分割线类型',
|
||||
'en-US': 'Type Usage'
|
||||
},
|
||||
desc: {
|
||||
'zh-CN':
|
||||
'通过<code>border-style</code>属性可以设置分割线类型,可选值有<code>solid</code><code>dashed</code><code>dotted</code>,默认为<code>solid</code>。',
|
||||
'en-US':
|
||||
'You can set the split line type through the <code>border-style</code> attribute. The options are <code>solid</code><code>dashed</code><code>dotted</code>. The default value is <code>solid</code>.'
|
||||
},
|
||||
codeFiles: ['type.vue']
|
||||
},
|
||||
{
|
||||
demoId: 'content-position',
|
||||
name: {
|
||||
'zh-CN': '文本位置用法',
|
||||
'en-US': 'Text Position'
|
||||
},
|
||||
desc: {
|
||||
'zh-CN':
|
||||
'通过<code>content-position</code>属性可以设置分割线文本位置,可选值有<code>center</code><code>left</code><code>right</code>三种,默认为<code>center</code>。',
|
||||
'en-US':
|
||||
'You can use the <code>content-position</code> attribute to set the text position of the split line. The options are as follows: <code>center</code><code>left</code><code>right</code>. The default value is <code>center</code>.'
|
||||
},
|
||||
codeFiles: ['content-position.vue']
|
||||
},
|
||||
{
|
||||
demoId: 'status',
|
||||
name: {
|
||||
'zh-CN': '状态',
|
||||
'en-US': 'Status'
|
||||
},
|
||||
desc: {
|
||||
'zh-CN':
|
||||
'通过<code>status</code>属性可以设置分割线状态,可选值有<code>default</code><code>success</code><code>warning</code><code>error</code><code>info</code>五种状态。',
|
||||
'en-US':
|
||||
'You can use the <code>status</code> attribute to set the split line status. The options are <code>default</code><code>success</code><code>warning</code><code>error</code><code>info</code>.'
|
||||
},
|
||||
codeFiles: ['status.vue']
|
||||
},
|
||||
{
|
||||
demoId: 'vertical',
|
||||
name: {
|
||||
'zh-CN': '垂直方向',
|
||||
'en-US': 'Vertical direction'
|
||||
},
|
||||
desc: {
|
||||
'zh-CN': '通过<code>direction</code>属性设置为<code>vertical</code>,垂直分割线,不支持默认插槽。',
|
||||
'en-US':
|
||||
'Set the <code>direction</code> attribute to <code>vertical</code>, which indicates a vertical split line. The default slot is not supported.'
|
||||
},
|
||||
codeFiles: ['vertical.vue']
|
||||
}
|
||||
]
|
||||
}
|
|
@ -125,7 +125,8 @@ export const cmpMenus = [
|
|||
{ name: 'Amount', nameCn: '金额', key: 'amount' },
|
||||
{ name: 'currency', nameCn: '币种', key: 'currency' },
|
||||
{ name: 'CalendarView', nameCn: '日历', key: 'calendar-view' },
|
||||
{ name: 'FloatingButton', nameCn: '悬浮按钮', key: 'floating-button' }
|
||||
{ name: 'FloatingButton', nameCn: '悬浮按钮', key: 'floating-button' },
|
||||
{ name: 'Divider', nameCn: '分割线', key: 'divider' }
|
||||
]
|
||||
}
|
||||
]
|
||||
|
|
|
@ -58,7 +58,7 @@ const pickerOptions = {
|
|||
}
|
||||
const yearPickerOptions = {
|
||||
disabledDate(year) {
|
||||
return year > 2025 || year < 2022
|
||||
return year.getTime() > new Date(2025, 0, 1, 0).getTime() || year.getTime() < new Date(2022, 0, 1, 0).getTime()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -62,7 +62,9 @@ export default {
|
|||
},
|
||||
yearPickerOptions: {
|
||||
disabledDate(year) {
|
||||
return year > 2025 || year < 2022
|
||||
return (
|
||||
year.getTime() > new Date(2025, 0, 1, 0).getTime() || year.getTime() < new Date(2022, 0, 1, 0).getTime()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,129 @@
|
|||
<template>
|
||||
<div>
|
||||
<tiny-button @click="changModdeFn" type="primary">当前为 {{ flag }} 模式</tiny-button>
|
||||
<tiny-button @click="changFn">双层抽屉 </tiny-button>
|
||||
<tiny-dialog-box
|
||||
:visible="boxVisibility"
|
||||
right-slide
|
||||
@update:visible="boxVisibility = $event"
|
||||
title="父弹窗"
|
||||
width="30%"
|
||||
:custom-style="customStyle1"
|
||||
>
|
||||
<span>父弹窗内容</span>
|
||||
<tiny-dialog-box
|
||||
append-to-body
|
||||
right-slide
|
||||
:modal="false"
|
||||
:close-on-click-modal="false"
|
||||
no-animation
|
||||
:visible="boxVisibility2"
|
||||
:custom-style="customStyle2"
|
||||
@close="dialogClose"
|
||||
@update:visible="boxVisibility2 = $event"
|
||||
title="子弹窗"
|
||||
width="300px"
|
||||
>
|
||||
<span>子弹窗内容</span>
|
||||
<template #footer>
|
||||
<tiny-button type="primary" @click="boxVisibility2 = false"> 确定 </tiny-button>
|
||||
</template>
|
||||
</tiny-dialog-box>
|
||||
<template #footer>
|
||||
<tiny-button @click="boxVisibility = false">取消</tiny-button>
|
||||
<tiny-button type="primary" @click="openDialog"> 子弹窗 </tiny-button>
|
||||
</template>
|
||||
</tiny-dialog-box>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="jsx">
|
||||
import { ref, nextTick } from 'vue'
|
||||
import { TinyButton, TinyDialogBox } from '@opentiny/vue'
|
||||
|
||||
const boxVisibility = ref(false)
|
||||
|
||||
const boxVisibility2 = ref(false)
|
||||
|
||||
const flag = ref('auto')
|
||||
|
||||
const customStyle1 = ref({})
|
||||
|
||||
const customStyle2 = ref({})
|
||||
|
||||
function changFn() {
|
||||
boxVisibility.value = true
|
||||
}
|
||||
|
||||
function changModdeFn() {
|
||||
flag.value = flag.value === 'full' ? 'auto' : 'full'
|
||||
}
|
||||
|
||||
function openDialog() {
|
||||
if (flag.value === 'full') {
|
||||
customStyle1.value = {
|
||||
right: '8px',
|
||||
bottom: '8px',
|
||||
top: '8px',
|
||||
height: 'auto',
|
||||
borderRadius: '8px',
|
||||
transition: 'right 0.2s ease-in-out'
|
||||
}
|
||||
customStyle2.value = {
|
||||
bottom: '8px',
|
||||
top: '8px',
|
||||
height: 'auto',
|
||||
borderRadius: '8px',
|
||||
opacity: 0
|
||||
}
|
||||
const rightW = document.body.offsetWidth * 0.3
|
||||
|
||||
customStyle1.value.right = -rightW + 80 + 'px'
|
||||
customStyle2.value.right = rightW + 'px'
|
||||
customStyle2.value.transition = 'right 200ms ease-in-out opacity 100ms linear'
|
||||
boxVisibility2.value = true
|
||||
nextTick(() => {
|
||||
customStyle2.value.right = '85px'
|
||||
}, 10)
|
||||
|
||||
nextTick(() => {
|
||||
customStyle2.value.opacity = 1
|
||||
}, 100)
|
||||
} else {
|
||||
customStyle1.value = {
|
||||
right: '8px',
|
||||
bottom: '8px',
|
||||
top: '8px',
|
||||
height: 'auto',
|
||||
borderRadius: '8px',
|
||||
transition: 'right 0.2s ease-in-out'
|
||||
}
|
||||
customStyle2.value = {
|
||||
bottom: '8px',
|
||||
top: 'unset',
|
||||
height: 'auto',
|
||||
borderRadius: '8px',
|
||||
opacity: 0
|
||||
}
|
||||
const rightW = document.body.offsetWidth * 0.3
|
||||
customStyle2.value.right = rightW + 46 + 'px'
|
||||
customStyle2.value.transition = 'opacity 100ms linear'
|
||||
boxVisibility2.value = true
|
||||
|
||||
setTimeout(() => {
|
||||
customStyle2.value.opacity = 1
|
||||
}, 100)
|
||||
}
|
||||
}
|
||||
|
||||
function dialogClose() {
|
||||
if (flag.value === 'full') {
|
||||
nextTick(() => {
|
||||
customStyle1.value.right = '8px'
|
||||
customStyle2.value.opacity = 0
|
||||
}, 50)
|
||||
} else {
|
||||
customStyle2.value.opacity = 0
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,128 @@
|
|||
<template>
|
||||
<div>
|
||||
<tiny-button @click="changModdeFn" type="primary">当前为 {{ flag }} 模式</tiny-button>
|
||||
<tiny-button @click="changFn">双层抽屉 </tiny-button>
|
||||
<tiny-dialog-box
|
||||
:visible="boxVisibility"
|
||||
right-slide
|
||||
@update:visible="boxVisibility = $event"
|
||||
title="父弹窗"
|
||||
width="30%"
|
||||
:custom-style="customStyle1"
|
||||
>
|
||||
<span>父弹窗内容</span>
|
||||
<tiny-dialog-box
|
||||
append-to-body
|
||||
right-slide
|
||||
:modal="false"
|
||||
:close-on-click-modal="false"
|
||||
no-animation
|
||||
:visible="boxVisibility2"
|
||||
:custom-style="customStyle2"
|
||||
@close="dialogClose"
|
||||
@update:visible="boxVisibility2 = $event"
|
||||
title="子弹窗"
|
||||
width="300px"
|
||||
>
|
||||
<span>子弹窗内容</span>
|
||||
<template #footer>
|
||||
<tiny-button type="primary" @click="boxVisibility2 = false"> 确定 </tiny-button>
|
||||
</template>
|
||||
</tiny-dialog-box>
|
||||
<template #footer>
|
||||
<tiny-button @click="boxVisibility = false">取消</tiny-button>
|
||||
<tiny-button type="primary" @click="openDialog"> 子弹窗 </tiny-button>
|
||||
</template>
|
||||
</tiny-dialog-box>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { Button, DialogBox } from '@opentiny/vue'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
TinyButton: Button,
|
||||
TinyDialogBox: DialogBox
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
flag: 'auto',
|
||||
boxVisibility: false,
|
||||
customStyle1: {},
|
||||
customStyle2: {},
|
||||
boxVisibility2: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
changFn() {
|
||||
this.boxVisibility = true
|
||||
},
|
||||
changModdeFn() {
|
||||
this.flag = this.flag === 'full' ? 'auto' : 'full'
|
||||
},
|
||||
openDialog() {
|
||||
if (this.flag === 'full') {
|
||||
this.customStyle1 = {
|
||||
right: '8px',
|
||||
bottom: '8px',
|
||||
top: '8px',
|
||||
height: 'auto',
|
||||
borderRadius: '8px',
|
||||
transition: 'right 0.2s ease-in-out'
|
||||
}
|
||||
this.customStyle2 = {
|
||||
bottom: '8px',
|
||||
top: '8px',
|
||||
height: 'auto',
|
||||
borderRadius: '8px',
|
||||
opacity: 0
|
||||
}
|
||||
const rightW = document.body.offsetWidth * 0.3
|
||||
this.customStyle1.right = -rightW + 80 + 'px'
|
||||
this.customStyle2.right = rightW + 'px'
|
||||
this.customStyle2.transition = 'right 200ms ease-in-out opacity 100ms linear'
|
||||
this.boxVisibility2 = true
|
||||
|
||||
setTimeout(() => {
|
||||
this.customStyle2.right = '85px'
|
||||
}, 10)
|
||||
|
||||
setTimeout(() => {
|
||||
this.customStyle2.opacity = 1
|
||||
}, 100)
|
||||
} else {
|
||||
this.customStyle1 = {
|
||||
right: '8px',
|
||||
bottom: '8px',
|
||||
top: '8px',
|
||||
height: 'auto',
|
||||
borderRadius: '8px',
|
||||
transition: 'right 0.2s ease-in-out'
|
||||
}
|
||||
this.customStyle2 = {
|
||||
bottom: '8px',
|
||||
top: 'unset',
|
||||
height: 'auto',
|
||||
borderRadius: '8px',
|
||||
opacity: 0
|
||||
}
|
||||
const rightW = document.body.offsetWidth * 0.3
|
||||
this.customStyle2.right = rightW + 46 + 'px'
|
||||
this.customStyle2.transition = 'opacity 100ms linear'
|
||||
this.boxVisibility2 = true
|
||||
|
||||
setTimeout(() => {
|
||||
this.customStyle2.opacity = 1
|
||||
}, 100)
|
||||
}
|
||||
},
|
||||
dialogClose() {
|
||||
setTimeout(() => {
|
||||
this.customStyle1.right = '8px'
|
||||
this.customStyle2.opacity = 0
|
||||
}, 50)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -164,6 +164,19 @@ export default {
|
|||
},
|
||||
codeFiles: ['right-dialog.vue']
|
||||
},
|
||||
{
|
||||
demoId: 'double-dialog-height',
|
||||
name: {
|
||||
'zh-CN': '右侧双层弹框',
|
||||
'en-US': 'Double-layer dialog box on the right'
|
||||
},
|
||||
desc: {
|
||||
'zh-CN': '右侧弹窗分两种情况,父级弹框自动缩进,子级弹框高度撑满。父级弹框不缩进,子级弹框高度自适应。',
|
||||
'en-US':
|
||||
'There are two types of pop-up windows on the right. The parent pop-up boxes are automatically indented, and the child pop-up boxes are full. The parent dialog box is not indented, and the height of the child dialog box is adaptive.'
|
||||
},
|
||||
codeFiles: ['double-dialog-height.vue']
|
||||
},
|
||||
{
|
||||
demoId: 'hidden-header',
|
||||
name: {
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
import { test, expect } from '@playwright/test'
|
||||
|
||||
test('Divider 基础用法', async ({ page }) => {
|
||||
page.on('pageerror', (exception) => expect(exception).toBeNull())
|
||||
await page.goto('divider#basic-usage')
|
||||
await page.locator('.tiny-divider').click()
|
||||
})
|
|
@ -0,0 +1,14 @@
|
|||
<template>
|
||||
<div>
|
||||
<p>文案在左侧</p>
|
||||
<tiny-divider content-position="left" offset="20%">左侧且偏移20%</tiny-divider>
|
||||
<p>文案在中间</p>
|
||||
<tiny-divider content-position="center">中间</tiny-divider>
|
||||
<p>文案在右侧</p>
|
||||
<tiny-divider content-position="right" offset="80px">右侧且偏移80px</tiny-divider>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { TinyDivider } from '@opentiny/vue'
|
||||
</script>
|
|
@ -0,0 +1,20 @@
|
|||
<template>
|
||||
<div>
|
||||
<p>文案在左侧</p>
|
||||
<tiny-divider content-position="left" offset="20%">左侧且偏移20%</tiny-divider>
|
||||
<p>文案在中间</p>
|
||||
<tiny-divider content-position="center">中间</tiny-divider>
|
||||
<p>文案在右侧</p>
|
||||
<tiny-divider content-position="right" offset="80px">右侧且偏移80px</tiny-divider>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { TinyDivider } from '@opentiny/vue'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
TinyDivider
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -1,12 +0,0 @@
|
|||
<template>
|
||||
<p>文案在左侧</p>
|
||||
<tiny-divider content-position="left">文案</tiny-divider>
|
||||
<p>文案在中间</p>
|
||||
<tiny-divider content-position="center">文案</tiny-divider>
|
||||
<p>文案在右侧</p>
|
||||
<tiny-divider content-position="right">文案</tiny-divider>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { TinyDivider } from '@opentiny/vue'
|
||||
</script>
|
|
@ -1,20 +0,0 @@
|
|||
<template>
|
||||
<div>
|
||||
<p>文案在左侧</p>
|
||||
<tiny-divider content-position="left">文案</tiny-divider>
|
||||
<p>文案在中间</p>
|
||||
<tiny-divider content-position="center">文案</tiny-divider>
|
||||
<p>文案在右侧</p>
|
||||
<tiny-divider content-position="right">文案</tiny-divider>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { TinyDivider } from '@opentiny/vue'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
TinyDivider
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,14 @@
|
|||
<template>
|
||||
<p>自定义分隔线颜色</p>
|
||||
<tiny-divider color="#1476ff"></tiny-divider>
|
||||
<p>自定义文案的颜色及字体大小</p>
|
||||
<tiny-divider content-color="#1476ff">字体颜色</tiny-divider>
|
||||
<tiny-divider content-color="#ffffff" content-background-color="#1476ff">文案背景</tiny-divider>
|
||||
<tiny-divider font-size="16px">字体大小</tiny-divider>
|
||||
<p>自定义分割线整体内容高度及边距</p>
|
||||
<tiny-divider height="40px" margin="8px 0">高度及边距</tiny-divider>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { TinyDivider } from '@opentiny/vue'
|
||||
</script>
|
|
@ -0,0 +1,22 @@
|
|||
<template>
|
||||
<div>
|
||||
<p>自定义分隔线颜色</p>
|
||||
<tiny-divider color="#1476ff"></tiny-divider>
|
||||
<p>自定义文案的颜色及字体大小</p>
|
||||
<tiny-divider content-color="#1476ff">字体颜色</tiny-divider>
|
||||
<tiny-divider content-color="#ffffff" content-background-color="#1476ff">文案背景</tiny-divider>
|
||||
<tiny-divider font-size="16px">字体大小</tiny-divider>
|
||||
<p>自定义分割线整体内容高度及边距</p>
|
||||
<tiny-divider height="40px" margin="8px 0">高度及边距</tiny-divider>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { TinyDivider } from '@opentiny/vue'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
TinyDivider
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -1,14 +0,0 @@
|
|||
<template>
|
||||
<p>自定义分隔线颜色</p>
|
||||
<tiny-divider color="#1476ff"></tiny-divider>
|
||||
<p>自定义分隔线的样式</p>
|
||||
<tiny-divider border-style="dashed"></tiny-divider>
|
||||
<p>自定义文案的颜色</p>
|
||||
<tiny-divider content-color="#1476ff">文案</tiny-divider>
|
||||
<p>文案的背景颜色</p>
|
||||
<tiny-divider content-color="#ffffff" content-background-color="#1476ff">文案</tiny-divider>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { TinyDivider } from '@opentiny/vue'
|
||||
</script>
|
|
@ -1,22 +0,0 @@
|
|||
<template>
|
||||
<div>
|
||||
<p>自定义分隔线颜色</p>
|
||||
<tiny-divider color="#1476ff"></tiny-divider>
|
||||
<p>自定义分隔线的样式</p>
|
||||
<tiny-divider border-style="dashed"></tiny-divider>
|
||||
<p>自定义文案的颜色</p>
|
||||
<tiny-divider content-color="#1476ff">文案</tiny-divider>
|
||||
<p>文案的背景颜色</p>
|
||||
<tiny-divider content-color="#ffffff" content-background-color="#1476ff">文案</tiny-divider>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { TinyDivider } from '@opentiny/vue'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
TinyDivider
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -1,9 +1,11 @@
|
|||
<template>
|
||||
<span>分隔线</span>
|
||||
<tiny-divider direction="vertical"></tiny-divider>
|
||||
<span>分隔线</span>
|
||||
<tiny-divider direction="vertical"></tiny-divider>
|
||||
<span>分隔线</span>
|
||||
<div>
|
||||
<span>分隔线</span>
|
||||
<tiny-divider direction="vertical"></tiny-divider>
|
||||
<span>分隔线</span>
|
||||
<tiny-divider direction="vertical"></tiny-divider>
|
||||
<span>分隔线</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
<template>
|
||||
<div>
|
||||
<tiny-divider>solid线</tiny-divider>
|
||||
<tiny-divider border-style="dashed">dashed线</tiny-divider>
|
||||
<tiny-divider border-style="dotted">dotted线</tiny-divider>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { TinyDivider } from '@opentiny/vue'
|
||||
</script>
|
|
@ -0,0 +1,17 @@
|
|||
<template>
|
||||
<div>
|
||||
<tiny-divider>solid线</tiny-divider>
|
||||
<tiny-divider border-style="dashed">dashed线</tiny-divider>
|
||||
<tiny-divider border-style="dotted">dotted线</tiny-divider>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { TinyDivider } from '@opentiny/vue'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
TinyDivider
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,13 @@
|
|||
<template>
|
||||
<div>
|
||||
<tiny-divider> default </tiny-divider>
|
||||
<tiny-divider status="success"> success </tiny-divider>
|
||||
<tiny-divider status="error"> error </tiny-divider>
|
||||
<tiny-divider status="warning"> warning </tiny-divider>
|
||||
<tiny-divider status="info"> info </tiny-divider>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { TinyDivider } from '@opentiny/vue'
|
||||
</script>
|
|
@ -0,0 +1,19 @@
|
|||
<template>
|
||||
<div>
|
||||
<tiny-divider> default </tiny-divider>
|
||||
<tiny-divider status="success"> success </tiny-divider>
|
||||
<tiny-divider status="error"> error </tiny-divider>
|
||||
<tiny-divider status="warning"> warning </tiny-divider>
|
||||
<tiny-divider status="info"> info </tiny-divider>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { Divider } from '@opentiny/vue'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
TinyDivider: Divider
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -12,7 +12,7 @@ export default {
|
|||
'zh-CN': '通过引用组件标签即可。',
|
||||
'en-US': 'You can refer to component label.'
|
||||
},
|
||||
codeFiles: ['base.vue']
|
||||
codeFiles: ['basic-usage.vue']
|
||||
},
|
||||
{
|
||||
demoId: 'direction',
|
||||
|
@ -21,8 +21,9 @@ export default {
|
|||
'en-US': 'Vertical divider line'
|
||||
},
|
||||
desc: {
|
||||
'zh-CN': '<p>通过 <code>direction</code> 属性可以设置分隔线的方向。</p>',
|
||||
'en-US': '<p>The direction of the separator line can be set through the<code>direction</code>attribute.</p>'
|
||||
'zh-CN': '<p>通过设置<code>vertical</code>属性为<code>true</code>可以设置分隔线的方向。</p>',
|
||||
'en-US':
|
||||
'<p>You can set the direction of the divider by setting the <code>vertical</code> property to <code>true</code>.</p>'
|
||||
},
|
||||
codeFiles: ['direction.vue']
|
||||
},
|
||||
|
@ -33,11 +34,11 @@ export default {
|
|||
'en-US': 'The position of the separator copy'
|
||||
},
|
||||
desc: {
|
||||
'zh-CN': '<p>通过 <code>content-position</code> 属性 可以设置分隔线文案的位置。</p>',
|
||||
'zh-CN': '通过<code>text-position</code> 属性设置分隔线文案的位置,<code>offset</code>属性设置左右偏移量。',
|
||||
'en-US':
|
||||
'<p>The position of the separator text can be set through the<code>content position</code>attribute.</p>'
|
||||
'The <code>text-position</code> attribute is used to set the position of the partition line copywriting, and the <code>offset</code> attribute is used to set the left and right offsets.'
|
||||
},
|
||||
codeFiles: ['contentPosition.vue']
|
||||
codeFiles: ['content-position.vue']
|
||||
},
|
||||
{
|
||||
demoId: 'custom-style',
|
||||
|
@ -47,11 +48,37 @@ export default {
|
|||
},
|
||||
desc: {
|
||||
'zh-CN':
|
||||
'<p>通过<code>color</code><code>border-style</code><code>content-color</code>属性,自定义分割线样式。</p>',
|
||||
'通过<code>line-color</code>属性设置分割线颜色,<code>content-background-color</code>属性设置文案背景颜色,<code>content-color</code>属性设置文字颜色,<code>height</code>属性设置分割线整体内容高度,<code>margin</code>属性设置外边距值。',
|
||||
'en-US':
|
||||
'<p>Customize the split line style through the<code>color</code><code>border style</code><code>content color</code>attribute.</p>'
|
||||
'The <code>line-color</code> attribute sets the color of the split line, the <code>content-background-color</code> attribute sets the background color of the copywriting, the <code>content-color</code> attribute sets the text color, and the <code>height</code> Property Sets the overall content height of the split line. The <code>margin</code> property sets the outer margin value.'
|
||||
},
|
||||
codeFiles: ['customStyle.vue']
|
||||
codeFiles: ['custom-style.vue']
|
||||
},
|
||||
{
|
||||
demoId: 'divider-type',
|
||||
name: {
|
||||
'zh-CN': '分隔线类型',
|
||||
'en-US': 'Separator Line Type'
|
||||
},
|
||||
desc: {
|
||||
'zh-CN':
|
||||
'通过<code>type</code>设置分割线显示类型,默认值为<code>solid</code>,可选值为<code>dashed</code><code>dotted</code>。',
|
||||
'en-US':
|
||||
'Set the display type of the split line through <code>type</code>. The default value is <code>solid</code>. The options are <code>dashed</code><code>dotted</code>.'
|
||||
},
|
||||
codeFiles: ['divider-type.vue']
|
||||
},
|
||||
{
|
||||
demoId: 'status',
|
||||
name: {
|
||||
'zh-CN': '分隔线状态',
|
||||
'en-US': 'Separator Status'
|
||||
},
|
||||
desc: {
|
||||
'zh-CN': '通过<code>status</code>属性设置分割线显示状态颜色。',
|
||||
'en-US': 'Use the <code>status</code> attribute to set the color of the display status of the splitter line.'
|
||||
},
|
||||
codeFiles: ['status.vue']
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ import { getAlias, pathFromWorkspaceRoot } from '../../config/vite'
|
|||
import { external } from '../../shared/config'
|
||||
import type { Module } from '../../shared/module-utils'
|
||||
import { getAllIcons, getAllModules, getByName } from '../../shared/module-utils'
|
||||
import { logGreen, kebabCase, capitalizeKebabCase, getPatchVersion, isValidVersion } from '../../shared/utils'
|
||||
import { capitalizeKebabCase, getPatchVersion, isValidVersion, kebabCase, logGreen } from '../../shared/utils'
|
||||
import generatePackageJsonPlugin from './rollup/generate-package-json'
|
||||
import inlineChunksPlugin from './rollup/inline-chunks'
|
||||
import replaceModuleNamePlugin from './rollup/replace-module-name'
|
||||
|
@ -257,11 +257,7 @@ export const getBaseConfig = ({ vueVersion, dtsInclude, dts, buildTarget, isRunt
|
|||
extensions: ['.js', '.ts', '.tsx', '.vue'],
|
||||
alias: {
|
||||
...getAlias(vueVersion, '', design),
|
||||
'@tiptap/vue': `${
|
||||
vueVersion === '2'
|
||||
? path.resolve(pathFromPackages(''), 'vue/src/rich-text-editor/node_modules/@tiptap/vue-2')
|
||||
: path.resolve(pathFromPackages(''), 'vue/src/rich-text-editor/node_modules/@tiptap/vue-3')
|
||||
}`,
|
||||
'@tiptap/vue': `${vueVersion === '2' ? '@tiptap/vue-2' : '@tiptap/vue-3'}`,
|
||||
'@vue/babel-helper-vue-jsx-merge-props': 'node_modules/@vue/babel-helper-vue-jsx-merge-props/dist/helper.js'
|
||||
}
|
||||
},
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
import rich_text_editor_pkg from '../../../../packages/vue/src/rich-text-editor/package.json'
|
||||
|
||||
const EXTENERAL = [
|
||||
'vue',
|
||||
'axios',
|
||||
|
@ -9,7 +11,8 @@ const EXTENERAL = [
|
|||
'streamsaver',
|
||||
'shepherd.js',
|
||||
'./label-wrap',
|
||||
'./tall-storage.vue'
|
||||
'./tall-storage.vue',
|
||||
...Object.keys(rich_text_editor_pkg.peerDependencies)
|
||||
]
|
||||
const external = (deps) => {
|
||||
return EXTENERAL.includes(deps) || /^@opentiny[\\/]|@originjs|echarts|cropperjs|@better-scroll/.test(deps)
|
||||
|
|
|
@ -44,4 +44,4 @@
|
|||
"vite-plugin-dts": "^4.3.0",
|
||||
"vite-svg-loader": "^5.1.0"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -11,4 +11,4 @@
|
|||
"build": "pnpm -w build:ui",
|
||||
"postversion": "pnpm build"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,496 @@
|
|||
/**
|
||||
* Copyright (c) 2022 - present TinyVue Authors.
|
||||
* Copyright (c) 2022 - present Huawei Cloud Computing Technologies Co., Ltd.
|
||||
*
|
||||
* Use of this source code is governed by an MIT-style license.
|
||||
*
|
||||
* THE OPEN SOURCE SOFTWARE IN THIS PRODUCT IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL,
|
||||
* BUT WITHOUT ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS FOR
|
||||
* A PARTICULAR PURPOSE. SEE THE APPLICABLE LICENSES FOR MORE DETAILS.
|
||||
*
|
||||
*/
|
||||
import * as hooks from 'vue'
|
||||
|
||||
import { camelize, capitalize, hyphenate } from '@opentiny/mobile-utils/string'
|
||||
import { bindFilter, emitter, getElementCssClass, getElementStatusClass } from '../utils'
|
||||
|
||||
const Teleport = hooks.Teleport
|
||||
|
||||
export { emitter, bindFilter, getElementCssClass, getElementStatusClass, Teleport }
|
||||
|
||||
export const defineAsyncComponent = hooks.defineAsyncComponent
|
||||
|
||||
export const markRaw = hooks.markRaw
|
||||
|
||||
export const renderComponent = ({
|
||||
view = undefined as any,
|
||||
component = undefined as any,
|
||||
props,
|
||||
context: { attrs, slots },
|
||||
extend = {}
|
||||
}) => {
|
||||
return () => hooks.h((view && view.value) || component, { ref: 'modeTemplate', ...props, ...attrs, ...extend }, slots)
|
||||
}
|
||||
|
||||
export const rootConfig = (context) => {
|
||||
const instance = hooks.getCurrentInstance()
|
||||
context && setInstanceEmitter(instance)
|
||||
return instance?.appContext.config.globalProperties
|
||||
}
|
||||
|
||||
export const getComponentName = () => {
|
||||
// 此处组件最多为两层组件,所以对多获取到父级组件即可
|
||||
const instance = hooks.getCurrentInstance()
|
||||
let componentName = instance?.type?.name
|
||||
if (!componentName) {
|
||||
componentName = instance?.parent?.type?.name
|
||||
}
|
||||
|
||||
return componentName || ''
|
||||
}
|
||||
|
||||
export const appContext = () =>
|
||||
hooks.getCurrentInstance()?.appContext || {
|
||||
component: () => {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
|
||||
export const appProperties = () => {
|
||||
const instance = hooks.getCurrentInstance()
|
||||
return instance?.appContext.config.globalProperties || {}
|
||||
}
|
||||
|
||||
export const useRouter = (instance = hooks.getCurrentInstance()) => {
|
||||
const router = instance?.appContext.config.globalProperties.$router
|
||||
const route = router && router.currentRoute.value
|
||||
|
||||
return { route, router }
|
||||
}
|
||||
|
||||
const setInstanceEmitter = (instance) => {
|
||||
const $emitter = emitter()
|
||||
|
||||
if (typeof instance.$emitter === 'undefined') Object.defineProperty(instance, '$emitter', { get: () => $emitter })
|
||||
}
|
||||
|
||||
const emitEvent = (vm) => {
|
||||
const broadcast = (vm, componentName, eventName, params) => {
|
||||
const children = (vm.subTree && vm.subTree.children) || vm.children
|
||||
|
||||
Array.isArray(children) &&
|
||||
children.forEach((child) => {
|
||||
const name = child.type && child.type.componentName
|
||||
const component = child.component
|
||||
|
||||
if (name === componentName) {
|
||||
component.emit(eventName, params)
|
||||
component.$emitter && component.$emitter.emit(eventName, params)
|
||||
} else {
|
||||
broadcast(child, componentName, eventName, params)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return {
|
||||
dispatch(componentName, eventName, params) {
|
||||
let parent = vm.parent || vm.root
|
||||
let name = parent.type && parent.type.componentName
|
||||
|
||||
while (parent && (!name || name !== componentName)) {
|
||||
parent = parent.parent
|
||||
|
||||
if (parent) name = parent.type && parent.type.componentName
|
||||
}
|
||||
|
||||
if (parent) {
|
||||
parent.emit(...[eventName].concat(params))
|
||||
// fix: VUE3下事件参数为数组,VUE2下事件参数不是数组,这里修改为和VUE2兼容
|
||||
parent.$emitter && parent.$emitter.emit(...[eventName].concat(params))
|
||||
}
|
||||
},
|
||||
broadcast(componentName, eventName, params) {
|
||||
broadcast(vm, componentName, eventName, params)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const getRealParent = (vm) => {
|
||||
if (vm && vm.parent)
|
||||
return vm.parent.type.name === 'AsyncComponentWrapper' && vm.parent.parent ? vm.parent.parent : vm.parent
|
||||
}
|
||||
|
||||
const parent = (vm) => (handler) => {
|
||||
let parent = getRealParent(vm)
|
||||
let level = 0
|
||||
|
||||
const parentObject = (parent) => {
|
||||
return {
|
||||
level,
|
||||
vm: createVm({}, parent),
|
||||
el: parent.vnode.el,
|
||||
options: parent.type
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof handler !== 'function') return parent ? parentObject(parent) : {}
|
||||
|
||||
level++
|
||||
|
||||
while (parent) {
|
||||
if (handler(parentObject(parent))) break
|
||||
parent = getRealParent(parent)
|
||||
level++
|
||||
}
|
||||
}
|
||||
|
||||
const children = (vm) => (handler) => {
|
||||
if (typeof handler !== 'function') return generateChildren(vm.subTree)
|
||||
|
||||
let layer = 1
|
||||
const broadcast = (subTree) => {
|
||||
if (subTree) {
|
||||
const children = subTree.children || subTree.dynamicChildren
|
||||
const level = layer++
|
||||
|
||||
if (Array.isArray(children)) {
|
||||
if (
|
||||
children.some((child) => {
|
||||
return (
|
||||
child.component &&
|
||||
handler({
|
||||
level,
|
||||
vm: createVm({}, child.component),
|
||||
el: child.el,
|
||||
options: child.type,
|
||||
isLevel1: true
|
||||
})
|
||||
)
|
||||
})
|
||||
)
|
||||
return
|
||||
|
||||
children.forEach((child) => broadcast(child))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
broadcast(vm.subTree)
|
||||
}
|
||||
|
||||
const regEventPrefix = /^on[A-Z]/
|
||||
|
||||
const generateListeners = (attrs) => {
|
||||
const $attrs = {}
|
||||
const $listeners = {}
|
||||
|
||||
for (const name in attrs) {
|
||||
const event = attrs[name]
|
||||
|
||||
if (regEventPrefix.test(name) && typeof event === 'function') {
|
||||
$listeners[hyphenate(name.substr(2))] = event
|
||||
continue
|
||||
}
|
||||
|
||||
$attrs[name] = event
|
||||
}
|
||||
|
||||
return { $attrs, $listeners }
|
||||
}
|
||||
|
||||
const generateChildren = (subTree) => {
|
||||
const children: any = []
|
||||
children.refs = {}
|
||||
|
||||
if (subTree) {
|
||||
const arr = subTree.dynamicChildren || subTree.children
|
||||
|
||||
if (Array.isArray(arr)) {
|
||||
arr.forEach((child) => {
|
||||
if (child.component) {
|
||||
const vm = createVm({}, child.component)
|
||||
|
||||
children.push(vm)
|
||||
child.props.ref && (children.refs[child.props.ref] = vm)
|
||||
}
|
||||
})
|
||||
} else if (subTree.component) {
|
||||
children.push(createVm({}, subTree.component))
|
||||
}
|
||||
}
|
||||
|
||||
return children
|
||||
}
|
||||
|
||||
const defineProperties = (vm, instance, property, filter) => {
|
||||
for (const name in instance[property]) {
|
||||
if (typeof filter === 'function' && filter(name)) continue
|
||||
|
||||
Object.defineProperty(vm, name, {
|
||||
configurable: true,
|
||||
enumerable: true,
|
||||
get: () => instance[property][name],
|
||||
set: (value) => (instance[property][name] = value)
|
||||
})
|
||||
}
|
||||
|
||||
return vm
|
||||
}
|
||||
|
||||
const filter = (name) => name.indexOf('_') === 0
|
||||
|
||||
const defineInstanceVm = (vm, instance) => {
|
||||
defineProperties(vm, instance, 'setupState', null)
|
||||
defineProperties(vm, instance, 'props', filter)
|
||||
defineProperties(vm, instance, 'ctx', filter)
|
||||
|
||||
return vm
|
||||
}
|
||||
|
||||
const createVm = (vm, instance, context = null) => {
|
||||
const { $attrs, $listeners } = generateListeners(instance.attrs)
|
||||
let $emitter = instance.$emitter
|
||||
|
||||
if (!$emitter) {
|
||||
setInstanceEmitter(instance)
|
||||
$emitter = instance.$emitter
|
||||
}
|
||||
|
||||
const emit = (...args) => {
|
||||
instance.emit(...args)
|
||||
$emitter.emit.apply(vm, args)
|
||||
}
|
||||
|
||||
const $set = (target, propertyName, value) => (target[propertyName] = value)
|
||||
|
||||
context || defineInstanceVm(vm, instance)
|
||||
|
||||
Object.defineProperties(vm, {
|
||||
$attrs: { get: () => $attrs },
|
||||
$children: { get: () => generateChildren(instance.subTree) },
|
||||
$constants: { get: () => instance.props._constants },
|
||||
$emit: { get: () => emit },
|
||||
$el: { get: () => instance.vnode.el },
|
||||
$listeners: { get: () => $listeners },
|
||||
$mode: { get: () => instance._tiny_mode },
|
||||
$nextTick: { get: () => hooks.nextTick },
|
||||
$off: { get: () => $emitter.off },
|
||||
$on: { get: () => $emitter.on },
|
||||
$once: { get: () => $emitter.once },
|
||||
$options: { get: () => ({ componentName: instance.type.componentName }) },
|
||||
$parent: {
|
||||
get: () => instance.parent && createVm({}, getRealParent(instance))
|
||||
},
|
||||
$refs: { get: () => instance.refs },
|
||||
$renderless: { get: () => instance.props.tiny_renderless },
|
||||
$scopedSlots: { get: () => instance.slots },
|
||||
$set: { get: () => $set },
|
||||
$slots: { get: () => instance.slots },
|
||||
$template: { get: () => instance.props.tiny_template }
|
||||
})
|
||||
|
||||
return vm
|
||||
}
|
||||
|
||||
const onBeforeMount = (instance, refs) => {
|
||||
for (let name in instance.refs) {
|
||||
if (Object.prototype.hasOwnProperty.call(instance.refs, name)) {
|
||||
refs[name] = instance.refs[name]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const tools = (context, mode) => {
|
||||
const instance = hooks.getCurrentInstance() as any
|
||||
const root = instance?.appContext.config.globalProperties
|
||||
const { route, router } = useRouter(instance)
|
||||
const i18n = instance?.proxy?.$root?.$i18n
|
||||
const { dispatch, broadcast } = emitEvent(instance)
|
||||
const parentHandler = parent(instance)
|
||||
const childrenHandler = children(instance)
|
||||
const vm = createVm({}, instance, context)
|
||||
const emit = context.emit
|
||||
const refs = {}
|
||||
const grandParent = typeof instance.props.tiny_template === 'undefined' && getRealParent(instance)
|
||||
const parentVm = grandParent ? createVm({}, grandParent) : instance.parent ? createVm({}, instance.parent) : null
|
||||
|
||||
const setParentAttribute = ({ name, value }) => {
|
||||
const ctx = grandParent ? grandParent.ctx : instance?.parent?.ctx
|
||||
ctx[name] = value
|
||||
|
||||
// 当前的parentVm也保存一下。
|
||||
parentVm[name] = value
|
||||
}
|
||||
|
||||
const defineInstanceProperties = (props) => {
|
||||
Object.defineProperties(vm, props)
|
||||
Object.defineProperties(instance?.ctx, props)
|
||||
}
|
||||
|
||||
const defineParentInstanceProperties = (props) => {
|
||||
parentVm && Object.defineProperties(parentVm, props)
|
||||
}
|
||||
|
||||
hooks.onBeforeMount(() => defineInstanceVm(vm, instance))
|
||||
hooks.onMounted(() => onBeforeMount(instance, refs))
|
||||
|
||||
return {
|
||||
framework: 'vue3',
|
||||
vm,
|
||||
emit,
|
||||
emitter,
|
||||
route,
|
||||
router,
|
||||
dispatch,
|
||||
broadcast,
|
||||
parentHandler,
|
||||
childrenHandler,
|
||||
i18n,
|
||||
refs,
|
||||
slots: instance?.slots,
|
||||
scopedSlots: instance?.slots,
|
||||
attrs: context.attrs,
|
||||
parent: parentVm,
|
||||
nextTick: hooks.nextTick,
|
||||
constants: instance?.props._constants,
|
||||
mode,
|
||||
isPCMode: mode === 'pc',
|
||||
isMobileMode: mode === 'mobile',
|
||||
service: root?.$service,
|
||||
getService: () => root?.$getService(vm),
|
||||
setParentAttribute,
|
||||
defineInstanceProperties,
|
||||
defineParentInstanceProperties
|
||||
}
|
||||
}
|
||||
|
||||
const mapping = (content, before, after) => {
|
||||
if (typeof content[before] !== 'undefined') {
|
||||
const fn = content[before]
|
||||
|
||||
content[after] = (el, binding, vnode) => {
|
||||
vnode.context = binding.instance
|
||||
fn(el, binding, vnode)
|
||||
}
|
||||
|
||||
delete content[before]
|
||||
}
|
||||
}
|
||||
|
||||
export const directive = (directives) => {
|
||||
for (const name in directives) {
|
||||
const content = directives[name]
|
||||
|
||||
mapping(content, 'bind', 'beforeMount')
|
||||
mapping(content, 'update', 'updated')
|
||||
mapping(content, 'unbind', 'unmounted')
|
||||
}
|
||||
|
||||
return directives
|
||||
}
|
||||
|
||||
export const parseVnode = (vnode) => vnode
|
||||
|
||||
const { Text, Comment } = hooks
|
||||
|
||||
export const isEmptyVnode = (vnode) => !vnode || !vnode.type || [Text, Comment].includes(vnode.type)
|
||||
|
||||
const parseProps = (propsData) => {
|
||||
const props = {}
|
||||
|
||||
for (const name in propsData) {
|
||||
if (name === 'class' || name === 'style') {
|
||||
props[name] = propsData[name]
|
||||
} else if (name === 'on' || name === 'nativeOn') {
|
||||
const events = propsData[name]
|
||||
|
||||
for (const eventName in events) props[`on${capitalize(camelize(eventName))}`] = events[eventName]
|
||||
} else if (name === 'attrs' || name === 'props' || name === 'domProps') {
|
||||
const attrs = propsData[name]
|
||||
|
||||
for (const key in attrs) props[key] = attrs[key]
|
||||
} else {
|
||||
props[name] = propsData[name]
|
||||
}
|
||||
}
|
||||
|
||||
return props
|
||||
}
|
||||
|
||||
const customResolveComponent = (component) => {
|
||||
let type = component
|
||||
let customElement = false
|
||||
|
||||
if (typeof component === 'string' && typeof document !== 'undefined') {
|
||||
const el = document.createElement(component)
|
||||
const svgTagNames = ['SVG', 'CIRCLE', 'PATH']
|
||||
|
||||
if ((el instanceof HTMLUnknownElement && !svgTagNames.includes(el.nodeName)) || component.includes('-')) {
|
||||
component = component.toLowerCase()
|
||||
customElement = true
|
||||
|
||||
if (component === 'transition') type = hooks.Transition
|
||||
else if (component === 'transition-group') type = hooks.TransitionGroup
|
||||
else type = hooks.resolveComponent(component)
|
||||
} else {
|
||||
type = component
|
||||
}
|
||||
}
|
||||
|
||||
return { type, component, customElement }
|
||||
}
|
||||
|
||||
type CreateElement = (component: any, propsData?: any, childData?: any) => ReturnType<typeof hooks.h>
|
||||
|
||||
export const h: CreateElement = (component, propsData, childData) => {
|
||||
let props = {}
|
||||
let children = childData
|
||||
const ret = customResolveComponent(component)
|
||||
const customElement = ret.customElement
|
||||
const type = ret.type
|
||||
|
||||
component = ret.component
|
||||
|
||||
if (propsData && typeof propsData === 'object' && !Array.isArray(propsData)) {
|
||||
props = parseProps(propsData)
|
||||
propsData.scopedSlots && (children = propsData.scopedSlots)
|
||||
} else if (typeof propsData === 'string' || Array.isArray(propsData)) {
|
||||
childData = propsData
|
||||
}
|
||||
|
||||
if (typeof childData === 'string' || Array.isArray(childData))
|
||||
children = typeof component !== 'string' || customElement ? () => childData : childData
|
||||
|
||||
return hooks.h(type, props, children)
|
||||
}
|
||||
|
||||
export const createComponentFn = (design) => {
|
||||
return ({ component, propsData, el }) => {
|
||||
const comp = Object.assign(component, { provide: { [design.configKey]: design.configInstance } })
|
||||
const vnode = hooks.createVNode(comp, propsData)
|
||||
|
||||
hooks.render(vnode, el)
|
||||
return createVm({}, vnode.component)
|
||||
}
|
||||
}
|
||||
|
||||
export const defineComponent = hooks.defineComponent
|
||||
|
||||
export default hooks
|
||||
|
||||
export const isVue2 = false
|
||||
|
||||
export const isVue3 = true
|
||||
|
||||
export const isVnode = hooks.isVNode
|
||||
|
||||
export const KeepAlive = hooks.KeepAlive
|
||||
|
||||
export type {
|
||||
PropType,
|
||||
ExtractPropTypes,
|
||||
DefineComponent,
|
||||
ComponentPublicInstance,
|
||||
SetupContext,
|
||||
ComputedRef
|
||||
} from 'vue'
|
|
@ -918,7 +918,8 @@
|
|||
"type": "component",
|
||||
"exclude": false,
|
||||
"mode": [
|
||||
"pc"
|
||||
"pc",
|
||||
"mobile-first"
|
||||
]
|
||||
},
|
||||
"DividerPc": {
|
||||
|
@ -926,6 +927,11 @@
|
|||
"type": "template",
|
||||
"exclude": false
|
||||
},
|
||||
"DividerMobileFirst": {
|
||||
"path": "vue/src/divider/src/mobile-first.vue",
|
||||
"type": "template",
|
||||
"exclude": false
|
||||
},
|
||||
"Drawer": {
|
||||
"path": "vue/src/drawer/index.ts",
|
||||
"type": "component",
|
||||
|
|
|
@ -43,4 +43,4 @@
|
|||
"esno": "^4.7.0",
|
||||
"tsup": "7.2.0"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -56,6 +56,10 @@ export const computedStyle =
|
|||
}
|
||||
}
|
||||
|
||||
if (props.customStyle) {
|
||||
style = Object.assign(style, props.customStyle)
|
||||
}
|
||||
|
||||
return style
|
||||
}
|
||||
|
||||
|
@ -111,9 +115,9 @@ export const watchVisible =
|
|||
nextTick(() => state.key++)
|
||||
}
|
||||
|
||||
if (props.rightSlide) {
|
||||
const dialogBoxDom = el.querySelector(constants.DIALOG_BOX_CLASS) || el
|
||||
dialogBoxDom.style.left = ''
|
||||
if (props.rightSlide && state.current !== 'default') {
|
||||
const selector = `[data-tag=${constants.DIALOG_BOX_DATA_TAG}]`
|
||||
props.rightSlide && (el.querySelector(selector).style.left = '')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
import type { IDividerStyle, IDividerRenderlessParams } from '@/types'
|
||||
|
||||
export const computedRootStyle =
|
||||
({ state, props }: Pick<IDividerRenderlessParams, 'state' | 'props'>) =>
|
||||
(): IDividerStyle => {
|
||||
return {
|
||||
height: props.height || state.height,
|
||||
margin: props.margin || state.margin,
|
||||
fontSize: props.fontSize
|
||||
}
|
||||
}
|
||||
export const computedLineStyle =
|
||||
({ props }: Pick<IDividerRenderlessParams, 'props'>) =>
|
||||
(): IDividerStyle => {
|
||||
const lineStyle = {
|
||||
borderTopStyle: props.borderStyle
|
||||
}
|
||||
|
||||
if (props.color) {
|
||||
Object.assign(lineStyle, { borderTopColor: props.color })
|
||||
}
|
||||
|
||||
return lineStyle
|
||||
}
|
||||
|
||||
export const computedTextStyle =
|
||||
({ props }: Pick<IDividerRenderlessParams, 'props'>) =>
|
||||
(): IDividerStyle => {
|
||||
const textStyle = {
|
||||
left: 'unset',
|
||||
right: 'unset'
|
||||
}
|
||||
const defaultOffset = '5%'
|
||||
|
||||
if (props.contentPosition === 'left') {
|
||||
textStyle.left = props.offset || defaultOffset
|
||||
} else if (props.contentPosition === 'right') {
|
||||
textStyle.right = props.offset || defaultOffset
|
||||
}
|
||||
|
||||
return textStyle
|
||||
}
|
||||
|
||||
export const setDividerHeight =
|
||||
({ state, props, vm, nextTick }: Pick<IDividerRenderlessParams, 'state' | 'props' | 'vm' | 'nextTick'>) =>
|
||||
(): void => {
|
||||
const verticalHeight = '12px'
|
||||
|
||||
if (props.direction === 'vertical') {
|
||||
state.height = props.height || verticalHeight
|
||||
} else {
|
||||
nextTick(() => {
|
||||
const offsetHeight = vm.$refs.text && vm.$refs.text.offsetHeight
|
||||
state.height = props.height || offsetHeight ? offsetHeight + 'px' : 'auto'
|
||||
})
|
||||
}
|
||||
}
|
|
@ -1,5 +1,42 @@
|
|||
export const api = []
|
||||
import type {
|
||||
IDividerApi,
|
||||
IDividerProps,
|
||||
IDividerRenderlessParamUtils,
|
||||
IDividerState,
|
||||
ISharedRenderlessParamHooks
|
||||
} from '@/types'
|
||||
import { computedLineStyle, computedTextStyle, computedRootStyle, setDividerHeight } from './index'
|
||||
|
||||
export const api = ['state']
|
||||
|
||||
export const renderless = (
|
||||
props: IDividerProps,
|
||||
{ reactive, onMounted, computed }: ISharedRenderlessParamHooks,
|
||||
{ vm, nextTick }: IDividerRenderlessParamUtils
|
||||
) => {
|
||||
const defaultMargin: string = '16px 0'
|
||||
const verticalMargin: string = '0 8px'
|
||||
|
||||
const api = {} as IDividerApi
|
||||
const state: IDividerState = reactive({
|
||||
height: 'auto',
|
||||
margin: props.direction === 'vertical' ? verticalMargin : defaultMargin,
|
||||
lineStyle: computed(() => api.computedLineStyle()),
|
||||
textStyle: computed(() => api.computedTextStyle()),
|
||||
rootStyle: computed(() => api.computedRootStyle())
|
||||
})
|
||||
|
||||
Object.assign(api, {
|
||||
state,
|
||||
computedLineStyle: computedLineStyle({ props }),
|
||||
computedTextStyle: computedTextStyle({ props }),
|
||||
computedRootStyle: computedRootStyle({ props, state }),
|
||||
setDividerHeight: setDividerHeight({ props, state, vm, nextTick })
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
api.setDividerHeight()
|
||||
})
|
||||
|
||||
export const renderless = () => {
|
||||
return api
|
||||
}
|
||||
|
|
|
@ -177,7 +177,7 @@ export const initAria =
|
|||
}
|
||||
}
|
||||
|
||||
const toggleFocus =
|
||||
export const toggleFocus =
|
||||
({ state, value }) =>
|
||||
() => {
|
||||
state.focusing = value
|
||||
|
@ -194,9 +194,9 @@ export const initEvent =
|
|||
state.dropdownElm?.addEventListener('keydown', api.handleItemKeyDown, true)
|
||||
|
||||
if (!props.splitButton || !props.singleButton) {
|
||||
on(state.triggerElm, 'focus', toggleFocus({ state, value: true }))
|
||||
on(state.triggerElm, 'blur', toggleFocus({ state, value: false }))
|
||||
on(state.triggerElm, 'click', toggleFocus({ state, value: false }))
|
||||
on(state.triggerElm, 'focus', api.toggleFocusOnTrue)
|
||||
on(state.triggerElm, 'blur', api.toggleFocusOnFalse)
|
||||
on(state.triggerElm, 'click', api.toggleFocusOnFalse)
|
||||
}
|
||||
|
||||
if (state.trigger === 'hover') {
|
||||
|
@ -270,9 +270,9 @@ export const beforeDistory =
|
|||
() => {
|
||||
if (state.triggerElm) {
|
||||
off(state.triggerElm, 'keydown', api.handleTriggerKeyDown)
|
||||
off(state.triggerElm, 'focus', toggleFocus({ state, value: true }))
|
||||
off(state.triggerElm, 'blur', toggleFocus({ state, value: false }))
|
||||
off(state.triggerElm, 'click', toggleFocus({ state, value: false }))
|
||||
off(state.triggerElm, 'focus', api.toggleFocusOnTrue)
|
||||
off(state.triggerElm, 'blur', api.toggleFocusOnFalse)
|
||||
off(state.triggerElm, 'click', api.toggleFocusOnFalse)
|
||||
off(state.triggerElm, 'mouseenter', api.show)
|
||||
off(state.triggerElm, 'mouseleave', api.hide)
|
||||
off(state.triggerElm, 'click', api.handleClick)
|
||||
|
|
|
@ -36,14 +36,15 @@ import {
|
|||
initDomOperation,
|
||||
mounted,
|
||||
beforeDistory,
|
||||
clickOutside
|
||||
clickOutside,
|
||||
toggleFocus
|
||||
} from './index'
|
||||
|
||||
export const api = ['state', 'handleMainButtonClick', 'hide', 'show', 'initDomOperation', 'handleClick', 'clickOutside']
|
||||
|
||||
export const renderless = (
|
||||
props: IDropdownProps,
|
||||
{ reactive, watch, provide, onMounted, computed }: ISharedRenderlessParamHooks,
|
||||
{ reactive, watch, provide, onMounted, computed, onBeforeUnmount }: ISharedRenderlessParamHooks,
|
||||
{ emit, parent, broadcast, vm, nextTick, mode, designConfig }: IDropdownRenderlessParamUtils
|
||||
): IDropdownApi => {
|
||||
const api = {} as IDropdownApi
|
||||
|
@ -85,13 +86,16 @@ export const renderless = (
|
|||
triggerElmFocus: triggerElmFocus(state),
|
||||
initDomOperation: initDomOperation({ api, state, vm }),
|
||||
beforeDistory: beforeDistory({ vm, api, state }),
|
||||
clickOutside: clickOutside({ props, api })
|
||||
clickOutside: clickOutside({ props, api }),
|
||||
toggleFocusOnTrue: toggleFocus({ state, value: true }),
|
||||
toggleFocusOnFalse: toggleFocus({ state, value: false })
|
||||
})
|
||||
|
||||
watch(() => state.visible, api.watchVisible)
|
||||
watch(() => state.focusing, api.watchFocusing)
|
||||
|
||||
onMounted(api.mounted)
|
||||
onBeforeUnmount(api.beforeDistory)
|
||||
|
||||
return api
|
||||
}
|
||||
|
|
|
@ -1511,7 +1511,7 @@ export const downloadFileSingleInner =
|
|||
|
||||
export const getDownloadFileInfo =
|
||||
({ api, state, props, service }: Pick<IFileUploadRenderlessParams, 'api' | 'state' | 'props' | 'service'>) =>
|
||||
({ docId }: { docId: string }) => {
|
||||
({ docId, docVersion }: { docId: string; docVersion: string }) => {
|
||||
return service.getDocumentInfoUrl().then((url) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
service
|
||||
|
|
|
@ -116,7 +116,7 @@ export const renderless = (
|
|||
|
||||
onBeforeUnmount(unbindDialogEvent)
|
||||
|
||||
watch(() => props.rules, api.watchRules)
|
||||
watch(() => props.rules, api.watchRules, { deep: props.validateOnRuleChange === 'deep' })
|
||||
|
||||
return api
|
||||
}
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
import {
|
||||
Active,
|
||||
closeTablePanel,
|
||||
eventClick,
|
||||
eventImg,
|
||||
handleChange,
|
||||
setLink,
|
||||
tableMouseMove,
|
||||
tableChoose,
|
||||
toggleTablePanel,
|
||||
closeTablePanel,
|
||||
shouldShow,
|
||||
eventImg,
|
||||
eventClick,
|
||||
Active
|
||||
tableChoose,
|
||||
tableMouseMove,
|
||||
toggleTablePanel
|
||||
} from './index'
|
||||
import type { ISharedRenderlessParamHooks } from '@/types'
|
||||
|
||||
|
@ -261,11 +261,11 @@ export const renderless = (
|
|||
onDestroy() {
|
||||
// The editor is being destroyed.
|
||||
emit('destroy')
|
||||
},
|
||||
...props.options
|
||||
}
|
||||
}
|
||||
|
||||
let options = Object.assign(defaultOptions, props.options)
|
||||
let options = { ...defaultOptions, ...props.options }
|
||||
options.extensions = [...new Set([...defaultOptions.extensions, ...(props.options.extensions || [])])]
|
||||
|
||||
const state = reactive({
|
||||
editor: new Editor(options),
|
||||
|
|
|
@ -572,6 +572,11 @@ export const handleFocus =
|
|||
if (!state.willFocusRun) return // 立即触发了blur,则不执行focus了
|
||||
|
||||
if (!state.softFocus) {
|
||||
// tiny 新增 shape条件: 防止过滤器模式,且filterable时, 面板无法关闭的bug
|
||||
if (props.shape === 'filter') {
|
||||
return
|
||||
}
|
||||
|
||||
if (props.automaticDropdown || props.filterable || props.searchable) {
|
||||
state.visible = true
|
||||
state.softFocus = true
|
||||
|
|
|
@ -27,6 +27,12 @@ export const initData =
|
|||
}
|
||||
}
|
||||
|
||||
export const getTree =
|
||||
({ vm }) =>
|
||||
() => {
|
||||
return vm.$refs.tree
|
||||
}
|
||||
|
||||
export const setMenuKey =
|
||||
(api: ITreeMenuApi) =>
|
||||
({ newData, menuData }: { newData: ITreeMenuNewData[]; menuData: ITreeMenuData[] }) => {
|
||||
|
|
|
@ -35,7 +35,8 @@ import {
|
|||
setCurrentNode,
|
||||
getCurrentNode,
|
||||
handleToggleMenu,
|
||||
computedTreeStyle
|
||||
computedTreeStyle,
|
||||
getTree
|
||||
} from './index'
|
||||
import type {
|
||||
ISharedRenderlessParamUtils,
|
||||
|
@ -70,7 +71,8 @@ export const api = [
|
|||
'getCurrentKey',
|
||||
'setCurrentNode',
|
||||
'getCurrentNode',
|
||||
'handleToggleMenu'
|
||||
'handleToggleMenu',
|
||||
'getTree'
|
||||
]
|
||||
|
||||
export const renderless = (
|
||||
|
@ -121,6 +123,7 @@ export const renderless = (
|
|||
getCurrentKey: getCurrentKey({ vm }),
|
||||
setCurrentNode: setCurrentNode({ vm }),
|
||||
getCurrentNode: getCurrentNode({ vm }),
|
||||
getTree: getTree({ vm }),
|
||||
handleToggleMenu: handleToggleMenu({ state, vm }),
|
||||
computedTreeStyle: computedTreeStyle({ props })
|
||||
})
|
||||
|
|
|
@ -28,7 +28,7 @@ export const getIsDisabled =
|
|||
({ props }) =>
|
||||
(year) => {
|
||||
return props.selectionMode.startsWith('year') && typeof props.disabledDate === 'function'
|
||||
? props.disabledDate(year)
|
||||
? props.disabledDate(new Date(year, 0, 1, 0))
|
||||
: false
|
||||
}
|
||||
|
||||
|
@ -87,7 +87,7 @@ export const getRows =
|
|||
cell.text = year
|
||||
cell.type = isToday ? DATEPICKER.Today : DATEPICKER.Normal
|
||||
if (props.selectionMode.startsWith('year')) {
|
||||
cell.disabled = typeof disabledDate === 'function' && disabledDate(year)
|
||||
cell.disabled = typeof disabledDate === 'function' && disabledDate(new Date(year, 0, 1, 0))
|
||||
}
|
||||
|
||||
if (selectionMode === DATEPICKER.YearRange) {
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
import type { ExtractPropTypes } from 'vue'
|
||||
import type { dividerProps } from '@/divider/src'
|
||||
import type { computedLineStyle, computedTextStyle, computedRootStyle, setDividerHeight } from '../src/divider'
|
||||
import type { ISharedRenderlessFunctionParams, ISharedRenderlessParamUtils } from './shared.type'
|
||||
|
||||
export interface IDividerState {
|
||||
height: string
|
||||
margin: string
|
||||
lineStyle: IDividerStyle
|
||||
textStyle: IDividerStyle
|
||||
rootStyle: IDividerStyle
|
||||
}
|
||||
|
||||
export type IDividerProps = ExtractPropTypes<typeof dividerProps>
|
||||
|
||||
export interface IDividerApi {
|
||||
state: IDividerState
|
||||
computedLineStyle: ReturnType<typeof computedLineStyle>
|
||||
computedTextStyle: ReturnType<typeof computedTextStyle>
|
||||
computedRootStyle: ReturnType<typeof computedRootStyle>
|
||||
setDividerHeight: ReturnType<typeof setDividerHeight>
|
||||
}
|
||||
|
||||
export type IDividerRenderlessParams = ISharedRenderlessFunctionParams<never> & {
|
||||
api: IDividerApi
|
||||
state: IDividerState
|
||||
props: IDividerProps
|
||||
}
|
||||
|
||||
export type IDividerRenderlessParamUtils = ISharedRenderlessParamUtils<never>
|
||||
|
||||
export interface IDividerStyle {
|
||||
margin?: string | number
|
||||
height?: string | number
|
||||
fontSize?: string | number
|
||||
right?: string | number
|
||||
left?: string | number
|
||||
borderLeftStyle?: string | number
|
||||
borderTopStyle?: string | number
|
||||
borderTopColor?: string | number
|
||||
}
|
|
@ -50,6 +50,8 @@ export interface IDropdownApi {
|
|||
initDomOperation: () => void
|
||||
beforeDistory: () => void
|
||||
clickOutside: () => void
|
||||
toggleFocusOnTrue: () => void
|
||||
toggleFocusOnFalse: () => void
|
||||
}
|
||||
|
||||
export type IDropdownRenderlessParams = ISharedRenderlessFunctionParams<null> & {
|
||||
|
|
|
@ -82,6 +82,7 @@ export * from './dropdown-item.type'
|
|||
export * from './dropdown-menu.type'
|
||||
export * from './dynamic-scroller.type'
|
||||
export * from './dynamic-scroller-item.type'
|
||||
export * from './divider.type'
|
||||
export * from './espace.type'
|
||||
export * from './exception.type'
|
||||
export * from './fall-menu.type'
|
||||
|
|
|
@ -23,7 +23,10 @@ import type {
|
|||
setCurrentKey,
|
||||
getCurrentKey,
|
||||
setCurrentNode,
|
||||
getCurrentNode
|
||||
getCurrentNode,
|
||||
handleToggleMenu,
|
||||
computedTreeStyle,
|
||||
getTree
|
||||
} from '../src/tree-menu'
|
||||
import type { ISharedRenderlessParamUtils } from './shared.type'
|
||||
|
||||
|
@ -51,6 +54,7 @@ export interface ITreeMenuApi {
|
|||
currentChange: ReturnType<typeof currentChange>
|
||||
watchFilterText: ReturnType<typeof watchFilterText>
|
||||
getTitle: ReturnType<typeof getTitle>
|
||||
getTree: ReturnType<typeof getTree>
|
||||
setMenuKey: ReturnType<typeof setMenuKey>
|
||||
initData: ReturnType<typeof initData>
|
||||
collapseChange: ReturnType<typeof collapseChange>
|
||||
|
@ -60,6 +64,8 @@ export interface ITreeMenuApi {
|
|||
getCurrentKey: ReturnType<typeof getCurrentKey>
|
||||
setCurrentNode: ReturnType<typeof setCurrentNode>
|
||||
getCurrentNode: ReturnType<typeof getCurrentNode>
|
||||
handleToggleMenu: ReturnType<typeof handleToggleMenu>
|
||||
computedTreeStyle: ReturnType<typeof computedTreeStyle>
|
||||
}
|
||||
|
||||
export interface ITreeMenuData {
|
||||
|
|
|
@ -152,6 +152,7 @@
|
|||
.@{modal-prefix-cls}__body {
|
||||
white-space: normal;
|
||||
word-break: break-word;
|
||||
overflow: auto;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,71 @@
|
|||
@import '../custom.less';
|
||||
|
||||
@divider-prefix-cls: ~'@{css-prefix}divider';
|
||||
|
||||
.@{divider-prefix-cls} {
|
||||
@apply h-auto;
|
||||
@apply flex;
|
||||
@apply items-center;
|
||||
@apply justify-center;
|
||||
@apply relative;
|
||||
@apply w-full;
|
||||
@apply overflow-hidden;
|
||||
|
||||
& &--default,
|
||||
&&--default {
|
||||
@apply border-color-border;
|
||||
}
|
||||
|
||||
& &--info,
|
||||
&&--info {
|
||||
@apply border-color-brand;
|
||||
}
|
||||
|
||||
& &--error,
|
||||
&&--error {
|
||||
@apply border-color-error;
|
||||
}
|
||||
|
||||
& &--warning,
|
||||
&&--warning {
|
||||
@apply border-color-warning;
|
||||
}
|
||||
|
||||
& &--success,
|
||||
&&--success {
|
||||
@apply border-color-success;
|
||||
}
|
||||
|
||||
&--horizontal {
|
||||
@apply mt-24 mr-0 mb-24 ml-0;
|
||||
}
|
||||
|
||||
&--vertical {
|
||||
@apply inline-block;
|
||||
@apply w-1;
|
||||
@apply align-middle;
|
||||
@apply mt-0 mr-8 mb-0 ml-8;
|
||||
height: 1em;
|
||||
@apply border-l border-l-color-border;
|
||||
}
|
||||
|
||||
&__text {
|
||||
@apply absolute;
|
||||
@apply font-medium;
|
||||
@apply pt-0 pr-14 pb-0 pl-14;
|
||||
@apply text-color-text-primary;
|
||||
@apply bg-color-bg-1;
|
||||
}
|
||||
|
||||
.@{divider-prefix-cls}-line {
|
||||
@apply h-px;
|
||||
@apply w-full;
|
||||
@apply border-t;
|
||||
}
|
||||
|
||||
.@{divider-prefix-cls}-text {
|
||||
@apply absolute;
|
||||
@apply pt-0 pr-14 pb-0 pl-14;
|
||||
@apply bg-white;
|
||||
}
|
||||
}
|
|
@ -5,6 +5,8 @@
|
|||
@custom-prefix-cls: ~'@{css-prefix}custom';
|
||||
|
||||
.@{modal-prefix-cls} {
|
||||
overflow-wrap: break-word;
|
||||
|
||||
&__wrapper {
|
||||
@apply hidden;
|
||||
@apply fixed;
|
||||
|
@ -141,8 +143,7 @@
|
|||
&.type__confirm {
|
||||
.@{modal-prefix-cls}__body {
|
||||
@apply whitespace-normal;
|
||||
word-wrap: break-word;
|
||||
@apply break-all;
|
||||
word-break: break-word;
|
||||
@apply overflow-auto;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -97,6 +97,7 @@
|
|||
@apply whitespace-pre-wrap;
|
||||
white-space-collapse: preserve-breaks;
|
||||
word-wrap: break-word;
|
||||
word-break: break-word;
|
||||
|
||||
& > * {
|
||||
@apply cursor-text;
|
||||
|
|
|
@ -91,6 +91,12 @@
|
|||
> span > .tiny-svg {
|
||||
@apply ~'-mt-0.5';
|
||||
}
|
||||
&:first-child {
|
||||
> .tiny-svg,
|
||||
> span > .tiny-svg {
|
||||
margin-top: 1px
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
& &__loading {
|
||||
|
|
|
@ -6,14 +6,43 @@
|
|||
.@{divider-prefix-cls} {
|
||||
.inject-Divider-vars();
|
||||
position: relative;
|
||||
height: auto;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
|
||||
&&--horizontal {
|
||||
display: block;
|
||||
margin: 24px 0;
|
||||
border-top: 1px solid var(--tv-Divider-dividing-line);
|
||||
& &--default,
|
||||
&&--default {
|
||||
border-color: var(--tv-Divider-default-color);
|
||||
}
|
||||
|
||||
&&--vertical {
|
||||
& &--success,
|
||||
&&--success {
|
||||
border-color: var(--tv-Divider-success-color);
|
||||
}
|
||||
|
||||
& &--warning,
|
||||
&&--warning {
|
||||
border-color: var(--tv-Divider-warning-color);
|
||||
}
|
||||
|
||||
& &--info,
|
||||
&&--info {
|
||||
border-color: var(--tv-Divider-info-color);
|
||||
}
|
||||
|
||||
& &--error,
|
||||
&&--error {
|
||||
border-color: var(--tv-Divider-error-color);
|
||||
}
|
||||
|
||||
&--horizontal {
|
||||
margin: 24px 0;
|
||||
}
|
||||
|
||||
&--vertical {
|
||||
display: inline-block;
|
||||
width: 1px;
|
||||
height: 1em;
|
||||
|
@ -24,24 +53,22 @@
|
|||
|
||||
&__text {
|
||||
position: absolute;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
padding: 0 14px;
|
||||
color: var(--tv-Divider-text-color);
|
||||
background-color: var(--tv-Divider-text-bg-color);
|
||||
line-height: normal;
|
||||
}
|
||||
|
||||
&.is-left {
|
||||
left: 20px;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
.@{divider-prefix-cls}-line {
|
||||
height: 1px;
|
||||
width: 100%;
|
||||
border-top-width: var(--tv-Divider-border-width);
|
||||
}
|
||||
|
||||
&.is-center {
|
||||
left: 50%;
|
||||
transform: translate(-50%) translateY(-50%);
|
||||
}
|
||||
|
||||
&.is-right {
|
||||
right: 20px;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
.@{divider-prefix-cls}-text {
|
||||
position: absolute;
|
||||
padding: 0 14px;
|
||||
background-color: var(--tv-Divider-text-bg-color);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,4 +5,16 @@
|
|||
--tv-Divider-text-bg-color: var(--tv-color-border-divider);
|
||||
// 文案文本色
|
||||
--tv-Divider-text-color: var(--tv-color-text);
|
||||
// 成功颜色
|
||||
--tv-Divider-success-color: var(--tv-color-success-border);
|
||||
// 默认颜色
|
||||
--tv-Divider-default-color: var(--tv-color-border-divider-short);
|
||||
// 告警颜色
|
||||
--tv-Divider-warning-color: var(--tv-color-warn-border);
|
||||
// 信息颜色
|
||||
--tv-Divider-info-color: var(--tv-color-info-border);
|
||||
// 错误颜色
|
||||
--tv-Divider-error-color: var(--tv-color-error-border);
|
||||
// 宽度
|
||||
--tv-Divider-border-width: var(--tv-border-width);
|
||||
}
|
||||
|
|
|
@ -333,7 +333,6 @@ export class Hasher extends BufferedBlockAlgorithm {
|
|||
if (messageUpdate) {
|
||||
this._append(messageUpdate)
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
const hash = this._doFinalize()
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ function editNodes(el: HTMLElement, nodes: HTMLElement[], query: string) {
|
|||
// 2、处理收集后的节点,字符串搜索性能优于正则替换
|
||||
nodes.forEach((node) => {
|
||||
const content = node.textContent as string
|
||||
const start = content.toLowerCase().indexOf(query.toLowerCase())
|
||||
const start = content.indexOf(query)
|
||||
const startText = content.substring(0, start)
|
||||
const endText = content.substring(start + query.length)
|
||||
|
||||
|
@ -58,7 +58,7 @@ function edit(el: HTMLElement, query: string) {
|
|||
}
|
||||
|
||||
const content = node.textContent || ''
|
||||
return content.toLowerCase().includes(query.toLowerCase())
|
||||
return content.includes(query)
|
||||
})
|
||||
|
||||
editNodes(el, matchNodes, query)
|
||||
|
|
|
@ -194,7 +194,7 @@ export default {
|
|||
hour: 'hour',
|
||||
minute: 'minute',
|
||||
second: 'second',
|
||||
to: '',
|
||||
to: '-',
|
||||
yearMonth: '{month} {year}',
|
||||
yearMonthDay: '{month} {day}, {year}'
|
||||
},
|
||||
|
|
|
@ -21,6 +21,7 @@ export const $constants = {
|
|||
DIALOG_BOX_CLASS: 'div.tiny-dialog-box',
|
||||
PC_SCROLL_LOCK_CLASS: 'dialog-box__scroll-lock',
|
||||
MOBILE_SCROLL_LOCK_CLASS: 'mobile-dialog-box__scroll-lock',
|
||||
DIALOG_BOX_DATA_TAG: 'tiny-dialog-box',
|
||||
Mode: 'pc',
|
||||
SCROLL_LOCK_CLASS(mode) {
|
||||
return mode === this.Mode ? this.PC_SCROLL_LOCK_CLASS : this.MOBILE_SCROLL_LOCK_CLASS
|
||||
|
@ -122,6 +123,14 @@ export const dialogBoxProps = {
|
|||
dialogTransition: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
noAnimation: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
customStyle: {
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,12 @@
|
|||
<template>
|
||||
<div>
|
||||
<div v-if="state.current !== 'default'">
|
||||
<transition :name="state.animationName" @after-enter="afterEnter" @after-leave="afterLeave">
|
||||
<transition
|
||||
:duration="noAnimation ? 0 : undefined"
|
||||
:name="state.animationName"
|
||||
@after-enter="afterEnter"
|
||||
@after-leave="afterLeave"
|
||||
>
|
||||
<div
|
||||
v-show="visible"
|
||||
:class="['fixed inset-0 m-0 flex items-center', dialogClass]"
|
||||
|
@ -26,7 +31,7 @@
|
|||
<div
|
||||
v-if="showHeader"
|
||||
data-tag="tiny-dialog-box__header"
|
||||
class="px-6 py-4 h-12 leading-4 bg-color-bg-1 flex justify-between items-center border-b border-b-color-bg-3"
|
||||
class="px-6 py-4 leading-5.5 bg-color-bg-1 flex justify-between items-center border-b border-b-color-bg-3"
|
||||
@mousedown="handleDrag"
|
||||
>
|
||||
<slot name="title">
|
||||
|
@ -171,7 +176,9 @@ export default defineComponent({
|
|||
'destroyOnClose',
|
||||
'dialogClass',
|
||||
'beforeClose',
|
||||
'maxHeight'
|
||||
'maxHeight',
|
||||
'customStyle',
|
||||
'noAnimation'
|
||||
],
|
||||
model: {
|
||||
prop: 'visible',
|
||||
|
|
|
@ -10,7 +10,12 @@
|
|||
*
|
||||
-->
|
||||
<template>
|
||||
<transition :name="state.animationName" @after-enter="afterEnter" @after-leave="afterLeave">
|
||||
<transition
|
||||
:duration="noAnimation ? 0 : undefined"
|
||||
:name="state.animationName"
|
||||
@after-enter="afterEnter"
|
||||
@after-leave="afterLeave"
|
||||
>
|
||||
<div
|
||||
v-show="visible"
|
||||
:class="['tiny-dialog-box__wrapper', dialogClass]"
|
||||
|
@ -32,6 +37,8 @@
|
|||
]"
|
||||
:style="state.style"
|
||||
class="tiny-dialog-box"
|
||||
data-tag="tiny-dialog-box"
|
||||
:data-dialog-box-draggable="draggable"
|
||||
:key="state.key"
|
||||
>
|
||||
<div v-if="showHeader" ref="header" class="tiny-dialog-box__header" @mousedown="handleDrag">
|
||||
|
@ -134,7 +141,9 @@ export default defineComponent({
|
|||
'dialogClass',
|
||||
'beforeClose',
|
||||
'maxHeight',
|
||||
'dialogTransition'
|
||||
'dialogTransition',
|
||||
'customStyle',
|
||||
'noAnimation'
|
||||
],
|
||||
model: {
|
||||
prop: 'visible',
|
||||
|
|
|
@ -3,44 +3,58 @@ import type { PropType } from '@opentiny/vue-common'
|
|||
import template from 'virtual-template?pc'
|
||||
|
||||
export type DirectionType = 'horizontal' | 'vertical'
|
||||
export type BorderStyleType = 'dashed' | 'solid'
|
||||
export type BorderStyleType = 'dashed' | 'solid' | 'dotted'
|
||||
export type ContentPositionType = 'left' | 'right' | 'center'
|
||||
|
||||
const $constants = {}
|
||||
export const $constants = {}
|
||||
|
||||
export const dividerProps = {
|
||||
...$props,
|
||||
_constants: {
|
||||
type: Object,
|
||||
default: () => $constants
|
||||
},
|
||||
direction: {
|
||||
type: String as PropType<DirectionType>,
|
||||
default: 'horizontal'
|
||||
},
|
||||
color: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
borderStyle: {
|
||||
type: String as PropType<BorderStyleType>,
|
||||
default: 'solid'
|
||||
},
|
||||
contentPosition: {
|
||||
type: String as PropType<ContentPositionType>,
|
||||
default: 'center'
|
||||
},
|
||||
contentColor: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
contentBackgroundColor: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
fontSize: {
|
||||
type: String,
|
||||
default: () => '14px'
|
||||
},
|
||||
margin: String,
|
||||
offset: String,
|
||||
height: String,
|
||||
status: {
|
||||
type: String,
|
||||
values: ['default', 'success', 'warning', 'error', 'info'],
|
||||
default: () => 'default'
|
||||
}
|
||||
}
|
||||
|
||||
export default defineComponent({
|
||||
name: $prefix + 'Divider',
|
||||
props: {
|
||||
...$props,
|
||||
_constants: {
|
||||
type: Object,
|
||||
default: () => $constants
|
||||
},
|
||||
direction: {
|
||||
type: String as PropType<DirectionType>,
|
||||
default: 'horizontal'
|
||||
},
|
||||
color: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
borderStyle: {
|
||||
type: String as PropType<BorderStyleType>,
|
||||
default: 'solid'
|
||||
},
|
||||
contentPosition: {
|
||||
type: String as PropType<ContentPositionType>,
|
||||
default: 'center'
|
||||
},
|
||||
contentColor: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
contentBackgroundColor: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
props: dividerProps,
|
||||
setup(props, context) {
|
||||
return $setup({ props, context, template })
|
||||
}
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
<template>
|
||||
<div
|
||||
data-tag="aui-divider"
|
||||
:style="state.rootStyle"
|
||||
:class="
|
||||
m(
|
||||
'overflow-hidden relative',
|
||||
vertical ? 'inline-block w-px border-l' : 'h-auto flex items-center justify-center w-full',
|
||||
gcls('status-' + status)
|
||||
)
|
||||
"
|
||||
>
|
||||
<div
|
||||
v-if="!vertical"
|
||||
class="h-px w-full border-t"
|
||||
:style="state.lineStyle"
|
||||
:class="[gcls('status-' + status)]"
|
||||
></div>
|
||||
<span v-if="!vertical" ref="text" class="absolute py-0 px-3.5 bg-white" :style="state.textStyle">
|
||||
<slot></slot>
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { renderless, api } from '@opentiny/vue-renderless/divider/vue'
|
||||
import { setup, props, defineComponent } from '@opentiny/vue-common'
|
||||
import { classes } from './token'
|
||||
|
||||
export default defineComponent({
|
||||
props: [
|
||||
...props,
|
||||
'type',
|
||||
'vertical',
|
||||
'lineColor',
|
||||
'textPosition',
|
||||
'status',
|
||||
'margin',
|
||||
'offset',
|
||||
'fontSize',
|
||||
'height'
|
||||
],
|
||||
setup(props, context): any {
|
||||
return setup({ props, context, renderless, api, classes })
|
||||
}
|
||||
})
|
||||
</script>
|
|
@ -1,18 +1,24 @@
|
|||
<template>
|
||||
<div
|
||||
:class="['tiny-divider', 'tiny-divider--' + direction]"
|
||||
:style="{
|
||||
'border-top-style': direction === 'horizontal' ? borderStyle : '',
|
||||
'border-left-style': direction === 'vertical' ? borderStyle : '',
|
||||
'border-color': color
|
||||
}"
|
||||
:class="['tiny-divider', 'tiny-divider--' + direction, direction === 'vertical' ? 'tiny-divider--' + status : '']"
|
||||
:style="state.rootStyle"
|
||||
>
|
||||
<div
|
||||
v-if="direction !== 'vertical'"
|
||||
:style="{
|
||||
'border-color': color,
|
||||
...state.lineStyle
|
||||
}"
|
||||
:class="['tiny-divider-line', 'tiny-divider--' + status]"
|
||||
></div>
|
||||
<div
|
||||
v-if="slots.default"
|
||||
:class="['tiny-divider__text', 'is-' + contentPosition]"
|
||||
ref="text"
|
||||
:class="['tiny-divider__text']"
|
||||
:style="{
|
||||
color: contentColor,
|
||||
'background-color': contentBackgroundColor
|
||||
'background-color': contentBackgroundColor,
|
||||
...state.textStyle
|
||||
}"
|
||||
>
|
||||
<slot></slot>
|
||||
|
@ -25,7 +31,20 @@ import { renderless, api } from '@opentiny/vue-renderless/divider/vue'
|
|||
import { props, setup, defineComponent } from '@opentiny/vue-common'
|
||||
|
||||
export default defineComponent({
|
||||
props: [...props, 'direction', 'color', 'borderStyle', 'contentPosition', 'contentColor', 'contentBackgroundColor'],
|
||||
props: [
|
||||
...props,
|
||||
'direction',
|
||||
'color',
|
||||
'borderStyle',
|
||||
'contentPosition',
|
||||
'contentColor',
|
||||
'contentBackgroundColor',
|
||||
'status',
|
||||
'margin',
|
||||
'offset',
|
||||
'fontSize',
|
||||
'height'
|
||||
],
|
||||
setup(props, context) {
|
||||
return setup({ props, context, renderless, api })
|
||||
}
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
export const classes = {
|
||||
'status-default': 'border-color-border',
|
||||
'status-info': 'border-color-brand',
|
||||
'status-warning': 'border-color-warning',
|
||||
'status-success': 'border-color-success',
|
||||
'status-error': 'border-color-error'
|
||||
}
|
|
@ -33,7 +33,8 @@ export const formProps = {
|
|||
size: String,
|
||||
disabled: Boolean,
|
||||
validateOnRuleChange: {
|
||||
type: Boolean,
|
||||
type: [Boolean, String],
|
||||
validator: (value: string | boolean) => typeof value === 'boolean' || ['deep'].includes(value),
|
||||
default: true
|
||||
},
|
||||
hideRequiredAsterisk: {
|
||||
|
|
|
@ -213,7 +213,9 @@ function defaultEditRender(h, renderOpts, params, context) {
|
|||
let editorModel = component.model || {}
|
||||
let modelProps = typeof component === 'string' ? 'value' : editorModel.prop || 'modelValue'
|
||||
|
||||
const key = row[$table.rowId]
|
||||
let options = {
|
||||
key,
|
||||
class: isTag ? `tiny-grid-default-${component}` : '',
|
||||
attrs: {
|
||||
formatOpt,
|
||||
|
|
|
@ -340,7 +340,7 @@ const Methods = {
|
|||
return new Promise((resolve) => {
|
||||
this.loadTableData(datas)
|
||||
resolve()
|
||||
}).then(this.recalculate)
|
||||
})
|
||||
},
|
||||
reloadRow(row, record, field) {
|
||||
let { tableData, tableSourceData } = this
|
||||
|
@ -1627,14 +1627,10 @@ const Methods = {
|
|||
},
|
||||
// 处理x轴方向虚拟滚动列数据加载
|
||||
updateScrollXData() {
|
||||
let { scrollXLoad, scrollXStore, tableColumn, treeConfig, visibleColumn, visibleColumnChanged, columnStore } = this
|
||||
let { lastStartIndex = -1, renderSize, startIndex } = scrollXStore
|
||||
let args = { lastStartIndex, renderSize, scrollXLoad, startIndex, tableColumn, columnStore }
|
||||
|
||||
Object.assign(args, { treeConfig, visibleColumn, visibleColumnChanged })
|
||||
let { scrollXStore } = this
|
||||
|
||||
// 获取需要渲染的列数和最后一次渲染列的index值
|
||||
let ret = sliceVisibleColumn(args)
|
||||
let ret = sliceVisibleColumn(this)
|
||||
|
||||
if (ret.sliced) {
|
||||
// 更新DOM样式保证表格滚动时的对齐,初始化表格时也需要计算x轴方向滚动条占位符的尺寸
|
||||
|
@ -2076,6 +2072,7 @@ const Methods = {
|
|||
lastScrollLeft = Math.min(lastScrollLeft, maxScrollLeft)
|
||||
|
||||
fastdom.mutate(() => {
|
||||
this.restoreScollFlag = true
|
||||
this.scrollTo(lastScrollLeft, lastScrollTop)
|
||||
|
||||
scrollXLoad && this.triggerScrollXEvent()
|
||||
|
|
|
@ -204,9 +204,10 @@ const getTreeShowKey = ({ scrollYLoad, treeConfig }) => {
|
|||
return treeShowKey
|
||||
}
|
||||
|
||||
const sliceVisibleColumn = (args) => {
|
||||
const { lastStartIndex, renderSize, scrollXLoad, startIndex, tableColumn, columnStore } = args
|
||||
const { treeConfig, visibleColumn, visibleColumnChanged } = args
|
||||
const sliceVisibleColumn = (tableVm) => {
|
||||
const { treeConfig, visibleColumn, tableColumn, columnStore, visibleColumnChanged, scrollXLoad, scrollXStore } =
|
||||
tableVm
|
||||
const { lastStartIndex = -1, renderSize, startIndex } = scrollXStore
|
||||
const { leftList, rightList } = columnStore
|
||||
|
||||
let tableColumn2 = tableColumn
|
||||
|
@ -215,7 +216,8 @@ const sliceVisibleColumn = (args) => {
|
|||
let sliced = false
|
||||
|
||||
if (scrollXLoad && treeConfig) {
|
||||
if (visibleColumnChanged || !~lastStartIndex || lastStartIndex !== startIndex) {
|
||||
if (visibleColumnChanged || !~lastStartIndex || lastStartIndex !== startIndex || tableVm.restoreScollFlag) {
|
||||
tableVm.restoreScollFlag = false
|
||||
tableColumn2 = visibleColumn.slice(startIndex, startIndex + renderSize)
|
||||
lastStartIndex2 = startIndex
|
||||
visibleColumnChanged2 = false
|
||||
|
|
|
@ -85,7 +85,7 @@
|
|||
'w-full border-0 sm:border px-0 sm:px-3 sm:border-solid sm:border-color-border sm:hover:border-color-border-hover ' +
|
||||
'sm:focus:border-color-brand-focus sm:disabled:border-color-border-separator ' +
|
||||
'placeholder:text-color-text-placeholder placeholder:text-sm sm:disabled:placeholder:text-color-text-disabled text-sm text-color-text-primary ' +
|
||||
'bg-color-bg-1 disabled:cursor-not-allowed disabled:text-color-text-disabled sm:disabled:text-color-text-secondary ' +
|
||||
'bg-color-bg-1 disabled:cursor-not-allowed disabled:text-color-text-disabled sm:disabled:text-color-text-disabled ' +
|
||||
'sm:disabled:bg-color-bg-6 py-0 outline-0 transition-colors duration-200 ease-in-out ',
|
||||
state.inputSizeMf === 'medium'
|
||||
? `h-8 leading-8 ${m('sm:text-sm')} placeholder:text-sm`
|
||||
|
@ -323,7 +323,7 @@
|
|||
ref="textarea"
|
||||
v-bind="a($attrs, ['type', 'class', 'style', '^on[A-Z]'])"
|
||||
:tabindex="tabindex"
|
||||
class="block w-full border-0 sm:border-solid sm:border-color-border sm:hover:border-color-border-hover sm:focus:border-color-brand-focus sm:disabled:border-color-border-separator outline-0 rounded placeholder:text-color-text-placeholder placeholder:text-sm sm:disabled:placeholder:text-color-text-disabled text-sm text-color-text-primary bg-color-bg-1 disabled:cursor-not-allowed disabled:text-color-text-disabled sm:disabled:text-color-text-secondary sm:disabled:bg-color-bg-6"
|
||||
class="block w-full border-0 sm:border-solid sm:border-color-border sm:hover:border-color-border-hover sm:focus:border-color-brand-focus sm:disabled:border-color-border-separator outline-0 rounded placeholder:text-color-text-placeholder placeholder:text-sm sm:disabled:placeholder:text-color-text-disabled text-sm text-color-text-primary bg-color-bg-1 disabled:cursor-not-allowed disabled:text-color-text-disabled sm:disabled:text-color-text-disabled sm:disabled:bg-color-bg-6"
|
||||
:class="[
|
||||
readonly ? 'sm:border-0 px-0 py-0' : 'sm:border px-3 ',
|
||||
state.isDisplayOnly ? 'hidden' : '',
|
||||
|
|
|
@ -412,7 +412,7 @@ export default defineComponent({
|
|||
? h(
|
||||
'div',
|
||||
{
|
||||
class: 'flex-auto flex mx-6 mt-4 mb-5 sm:my-6 leading-5 overflow-auto'
|
||||
class: 'flex-auto flex mx-6 mt-4 mb-5 sm:my-6 leading-5 overflow-auto break-normal'
|
||||
},
|
||||
[
|
||||
status ? h('div', { class: 'hidden sm:block mr-8' }) : null,
|
||||
|
|
|
@ -134,8 +134,9 @@ export const useRule = (props: RuleProps) => {
|
|||
}
|
||||
}
|
||||
}
|
||||
return { name: field, label: field }
|
||||
}
|
||||
let fieldData = fieldMap?.[field] ?? findFieldData(field, fields)
|
||||
let fieldData = fieldMap?.[field] ? fieldMap[field] : findFieldData(field, fields)
|
||||
const inputType = fieldData.inputType ?? getInputType(field, operator)
|
||||
const operators = getOperators(field)
|
||||
const operatorObject = getOption(operators, operator)
|
||||
|
|
|
@ -18,6 +18,10 @@
|
|||
"@opentiny/vue-icon": "workspace:~"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@opentiny-internal/vue-test-utils": "workspace:*",
|
||||
"vitest": "catalog:"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@tiptap/core": "~2.1.16",
|
||||
"@tiptap/extension-code-block-lowlight": "~2.1.16",
|
||||
"@tiptap/extension-collaboration": "~2.1.16",
|
||||
|
@ -43,8 +47,6 @@
|
|||
"@tiptap/vue-2": "~2.1.16",
|
||||
"@tiptap/vue-3": "~2.1.16",
|
||||
"highlight.js": "^11.8.0",
|
||||
"lowlight": "^2.9.0",
|
||||
"@opentiny-internal/vue-test-utils": "workspace:*",
|
||||
"vitest": "catalog:"
|
||||
"lowlight": "^2.9.0"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -57,7 +57,7 @@
|
|||
v-if="~['fail'].indexOf(file.status)"
|
||||
class="relative w-full h-full bg-black/50 rounded"
|
||||
>
|
||||
<icon-cue-l-o class="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 fill-color-error" />
|
||||
<icon-cue-l class="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 fill-color-error" />
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
|
|
|
@ -123,18 +123,18 @@ export default defineComponent({
|
|||
{state.currentBreakpoint !== 'default' &&
|
||||
!displayOnly &&
|
||||
(promptTip && tipMessage ? (
|
||||
<div class="hidden sm:inline-flex sm:items-center">
|
||||
<div class="hidden sm:inline-flex sm:items-center w-full">
|
||||
{uploadTrigger()}
|
||||
<tiny-tooltip effect="light" content={tipMessage} placement="right" popper-options={popperConfig}>
|
||||
<tiny-icon-help-circle custom-class="ml-2 cursor-pointer fill-color-icon-tertiary"></tiny-icon-help-circle>
|
||||
</tiny-tooltip>
|
||||
</div>
|
||||
) : listType === 'text' ? (
|
||||
<div class="hidden sm:inline-flex sm:items-center">
|
||||
<div class="hidden sm:inline-flex sm:items-center w-full">
|
||||
{uploadTrigger()}
|
||||
<div
|
||||
title={tipMessage}
|
||||
class="hidden sm:block text-xs leading-4 overflow-hidden text-ellipsis whitespace-nowrap text-color-text-placeholder ml-2 cursor-pointer">
|
||||
title={typeof tipMessage === 'string' ? tipMessage : ''}
|
||||
class="hidden sm:block text-xs leading-4 overflow-hidden whitespace-nowrap text-ellipsis text-color-text-placeholder ml-2 cursor-pointer">
|
||||
{tipMessage}
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -51,4 +51,4 @@
|
|||
"**/dist*",
|
||||
"**/*.md"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue