feat: adpting to OpenTinyDesign Themes (#2422)

This commit is contained in:
ajaxzheng 2024-10-28 11:09:09 +08:00 committed by GitHub
parent e7aa4a7561
commit 6496e5dcab
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
295 changed files with 4365 additions and 1069 deletions

View File

@ -377,6 +377,21 @@ export default {
}
],
methods: [
{
name: 'getSelection',
type: '() => IData[]',
typeAnchorName: 'IData',
meta: {
stable: '3.19.0'
},
defaultValue: '',
desc: {
'zh-CN': '获取多选选中数据',
'en-US': 'Get multi-select selected data'
},
mode: ['pc'],
pcDemo: 'set-selection'
},
{
name: 'queryGridData',
type: '() => void',
@ -387,6 +402,21 @@ export default {
},
mode: ['pc'],
pcDemo: 'nest-grid-multi'
},
{
name: 'setSelection',
type: '(data: IData | IData[], checked: boolean) => void',
typeAnchorName: 'IData',
meta: {
stable: '3.19.0'
},
defaultValue: '',
desc: {
'zh-CN': '设置数据的多选选中状态,需要在弹窗初始化后调用,否则调用无效',
'en-US': 'Set the multi-select selected state of data'
},
mode: ['pc'],
pcDemo: 'set-selection'
}
],
slots: [
@ -674,6 +704,16 @@ interface IResizeEvent {
fullscreen: boolean
// 弹窗的元素
dialog: HTMLElement
}
`
},
{
name: 'IData',
type: 'interface',
code: `
interface IData {
// 表格或者tree行数据
[prop: string]: any
}
`
}

View File

@ -631,7 +631,7 @@ type IFormTrigger = 'change' | 'blur'
interface IFormRules {
required?: boolean // 是否必填
message?: number // 校验错误的提示
message?: string // 校验错误的提示
// 内置的类型校验
type?: 'date' | 'dateTime' | 'float' | 'array' | 'string' | 'number' | 'url' | 'time' | 'email' | 'object' | 'boolean' | 'enum'
// 校验触发时机, 默认为 ['change', 'blur'] 两种场景都触发,如果仅在主动调用校验方式时触发,可设置为空数组 []。

View File

@ -4415,6 +4415,8 @@ interface IEditConfig {
showStatus?: boolean
// 自定义编辑规则返回true可以编辑返回false则禁止编辑
activeMethod?: ({row: IRow, column: IColumnConfig})=> boolean
// 3.19新增当mode为'row'时行编辑激活状态下默认会忽略activeMethod配置为true使其生效
activeStrictly?: boolean
}
`
},

View File

@ -0,0 +1,4 @@
export default {
mode: ['pc'],
apis: []
}

View File

@ -222,6 +222,21 @@ export default {
mode: ['pc', 'mobile-first'],
pcDemo: 'count-slot',
mfDemo: ''
},
{
name: 'appendToBody',
type: 'boolean',
defaultValue: 'true',
meta: {
stable: '3.19.0'
},
desc: {
'zh-CN': '预览弹框是否显示在当前节点下面',
'en-US': 'Indicates whether the preview dialog box is displayed under the current node.'
},
mode: ['pc', 'mobile-first'],
pcDemo: 'preview',
mfDemo: ''
}
]
}

View File

@ -422,6 +422,21 @@ export default {
},
mode: ['pc'],
pcDemo: 'show-filter'
},
{
name: 'width-adapt',
type: 'boolean',
defaultValue: 'false',
desc: {
'zh-CN': '通过 <code> widthAdapt </code> 属性,是否让组件宽度自适应父容器。',
'en-US':
'The <code>widthAdapt </code> attribute specifies whether to enable the component width to adapt to the parent container.'
},
meta: {
stable: '3.19.0'
},
mode: ['pc'],
pcDemo: 'show-filter'
}
],
events: [

View File

@ -11,9 +11,6 @@
>
</tiny-action-menu>
<br />
<tiny-action-menu :options="options" :suffix-icon="tinyIconEllipsis" more-text="" spacing="8px" :max-show-num="3">
</tiny-action-menu>
<br />
<p>场景2只显示文本</p>
<tiny-action-menu :options="options1" :show-icon="false" :max-show-num="3"> </tiny-action-menu>
</div>
@ -22,12 +19,12 @@
<script setup>
import { ref } from 'vue'
import { ActionMenu as TinyActionMenu } from '@opentiny/vue'
import { IconPreChecked, iconSuccessful, iconCloseSquare, iconEllipsis } from '@opentiny/vue-icon'
import { iconWebPlus, iconSuccessful, iconShutdown, iconEllipsis } from '@opentiny/vue-icon'
const options = ref([
{
label: '远程登陆',
icon: IconPreChecked()
icon: iconWebPlus()
},
{
label: '开机',
@ -35,7 +32,7 @@ const options = ref([
},
{
label: '关机',
icon: iconCloseSquare()
icon: iconShutdown()
},
{
label: '重启'

View File

@ -17,7 +17,7 @@
<script>
import { ActionMenu } from '@opentiny/vue'
import { IconPreChecked, iconSuccessful, iconCloseSquare, iconEllipsis } from '@opentiny/vue-icon'
import { iconWebPlus, iconSuccessful, iconShutdown, iconEllipsis } from '@opentiny/vue-icon'
export default {
components: {
@ -28,7 +28,7 @@ export default {
options: [
{
label: '远程登陆',
icon: IconPreChecked()
icon: iconWebPlus()
},
{
label: '开机',
@ -36,7 +36,7 @@ export default {
},
{
label: '关机',
icon: iconCloseSquare()
icon: iconShutdown()
},
{
label: '重启'

View File

@ -3,7 +3,7 @@
<tiny-autocomplete
v-model="value"
:prefix-icon="IconEdit"
:suffix-icon="IconAssociation"
:suffix-icon="IconApp"
placeholder="请输入内容"
:fetch-suggestions="querySearch"
></tiny-autocomplete>
@ -13,12 +13,12 @@
<script setup>
import { ref, onMounted } from 'vue'
import { Autocomplete as TinyAutocomplete } from '@opentiny/vue'
import { iconEdit, iconAssociation } from '@opentiny/vue-icon'
import { iconEdit, iconApp } from '@opentiny/vue-icon'
const restaurants = ref([])
const value = ref('')
const IconEdit = iconEdit()
const IconAssociation = iconAssociation()
const IconApp = iconApp()
onMounted(() => {
restaurants.value = loadAll()

View File

@ -3,7 +3,7 @@
<tiny-autocomplete
v-model="value"
:prefix-icon="IconEdit"
:suffix-icon="IconAssociation"
:suffix-icon="IconApp"
placeholder="请输入内容"
:fetch-suggestions="querySearch"
></tiny-autocomplete>
@ -12,7 +12,7 @@
<script>
import { Autocomplete } from '@opentiny/vue'
import { IconEdit, IconAssociation } from '@opentiny/vue-icon'
import { iconEdit, iconApp } from '@opentiny/vue-icon'
export default {
components: {
@ -22,8 +22,8 @@ export default {
return {
restaurants: [],
value: '',
IconEdit: IconEdit(),
IconAssociation: IconAssociation()
IconEdit: iconEdit(),
IconApp: iconApp()
}
},
methods: {

View File

@ -20,22 +20,22 @@
</tiny-row>
<tiny-row>
<tiny-button :icon="IconSearch" circle></tiny-button>
<tiny-button type="primary" :icon="IconEdit" circle></tiny-button>
<tiny-button type="primary" :icon="IconEditor" circle></tiny-button>
<tiny-button type="success" :icon="IconYes" circle></tiny-button>
<tiny-button type="info" :icon="IconMail" circle></tiny-button>
<tiny-button type="warning" :icon="IconStarO" circle></tiny-button>
<tiny-button type="danger" :icon="IconDel" circle></tiny-button>
<tiny-button type="danger" :icon="IconDeleteL" circle></tiny-button>
</tiny-row>
</tiny-layout>
</template>
<script setup>
import { TinyButton, TinyLayout, TinyRow } from '@opentiny/vue'
import { iconDel, iconYes, iconEdit, iconMail, iconStarO, iconSearch } from '@opentiny/vue-icon'
import { iconDeleteL, iconYes, iconEditor, iconMail, iconStarO, iconSearch } from '@opentiny/vue-icon'
const IconDel = iconDel()
const IconDeleteL = iconDeleteL()
const IconYes = iconYes()
const IconEdit = iconEdit()
const IconEditor = iconEditor()
const IconMail = iconMail()
const IconStarO = iconStarO()
const IconSearch = iconSearch()

View File

@ -20,18 +20,18 @@
</tiny-row>
<tiny-row>
<tiny-button :icon="IconSearch" circle></tiny-button>
<tiny-button type="primary" :icon="IconEdit" circle></tiny-button>
<tiny-button type="primary" :icon="IconEditor" circle></tiny-button>
<tiny-button type="success" :icon="IconYes" circle></tiny-button>
<tiny-button type="info" :icon="IconMail" circle></tiny-button>
<tiny-button type="warning" :icon="IconStarO" circle></tiny-button>
<tiny-button type="danger" :icon="IconDel" circle></tiny-button>
<tiny-button type="danger" :icon="IconDeleteL" circle></tiny-button>
</tiny-row>
</tiny-layout>
</template>
<script>
import { Button, Layout, Row } from '@opentiny/vue'
import { IconDel, IconYes, IconEdit, IconMail, IconStarO, IconSearch } from '@opentiny/vue-icon'
import { IconDeleteL, IconYes, IconEditor, IconMail, IconStarO, IconSearch } from '@opentiny/vue-icon'
export default {
components: {
@ -41,9 +41,9 @@ export default {
},
data() {
return {
IconDel: IconDel(),
IconDeleteL: IconDeleteL(),
IconYes: IconYes(),
IconEdit: IconEdit(),
IconEditor: IconEditor(),
IconMail: IconMail(),
IconStarO: IconStarO(),
IconSearch: IconSearch()

View File

@ -1,5 +1,5 @@
<template>
<tiny-button>
<tiny-button class="demo-button">
<img :src="image" width="26" />
<span>图片按钮</span>
</tiny-button>
@ -8,5 +8,18 @@
<script setup>
import { TinyButton } from '@opentiny/vue'
const image = `${import.meta.env.VITE_APP_BUILD_BASE_URL}static/images/button-image.png`
const image = `${import.meta.env.VITE_APP_BUILD_BASE_URL}static/images/email.png`
</script>
<style>
.demo-button img {
width: 16px;
height: 16px;
margin-right: 8px;
border-radius: 2px;
}
.demo-button span {
height: 16px;
line-height: 16px;
}
</style>

View File

@ -1,5 +1,5 @@
<template>
<tiny-button>
<tiny-button class="demo-button">
<img :src="image" width="26" />
<span>图片按钮</span>
</tiny-button>
@ -14,8 +14,21 @@ export default {
},
data() {
return {
image: `${import.meta.env.VITE_APP_BUILD_BASE_URL}static/images/button-image.png`
image: `${import.meta.env.VITE_APP_BUILD_BASE_URL}static/images/email.png`
}
}
}
</script>
<style>
.demo-button img {
width: 16px;
height: 16px;
margin-right: 8px;
border-radius: 2px;
}
.demo-button span {
height: 16px;
line-height: 16px;
}
</style>

View File

@ -26,26 +26,26 @@
<script setup>
import { Card as TinyCard } from '@opentiny/vue'
import { IconDel, IconWriting, IconAscending, IconShare } from '@opentiny/vue-icon'
import { IconDeleteL, IconEditor, IconSortTriangle, IconFilletExternalLink } from '@opentiny/vue-icon'
import { ref } from 'vue'
const options = ref([
{
text: '删除列表',
icon: IconDel()
icon: IconDeleteL()
},
{
text: '编辑',
icon: IconWriting(),
icon: IconEditor(),
disabled: true
},
{
text: '排序',
icon: IconAscending()
icon: IconSortTriangle()
},
{
text: '分享',
icon: IconShare(),
icon: IconFilletExternalLink(),
disabled: true
}
])

View File

@ -26,7 +26,7 @@
<script>
import { Card } from '@opentiny/vue'
import { IconDel, IconWriting, IconAscending, IconShare } from '@opentiny/vue-icon'
import { IconDeleteL, IconEditor, IconSortTriangle, IconFilletExternalLink } from '@opentiny/vue-icon'
export default {
components: {
@ -37,20 +37,20 @@ export default {
options: [
{
text: '删除列表',
icon: IconDel()
icon: IconDeleteL()
},
{
text: '编辑',
icon: IconWriting(),
icon: IconEditor(),
disabled: true
},
{
text: '排序',
icon: IconAscending()
icon: IconSortTriangle()
},
{
text: '分享',
icon: IconShare(),
icon: IconFilletExternalLink(),
disabled: true
}
]

View File

@ -3,7 +3,7 @@
<div class="my20">自定义节点,为节点添加提示</div>
<tiny-cascader v-model="value1" :options="options">
<template #default="{ node }">
<span :title="node.label"> {{ node.label }} <tiny-icon-share /></span>
<span :title="node.label"> {{ node.label }} <tiny-icon-fillet-external-link /></span>
</template>
</tiny-cascader>
<div class="my20">自定义空数据插槽</div>
@ -18,9 +18,9 @@
<script setup>
import { ref } from 'vue'
import { Cascader as TinyCascader } from '@opentiny/vue'
import { iconShare } from '@opentiny/vue-icon'
import { iconFilletExternalLink } from '@opentiny/vue-icon'
const tinyIconShare = iconShare()
const TinyIconFilletExternalLink = iconFilletExternalLink()
const value1 = ref('')
const value2 = ref('')
const options = ref([

View File

@ -3,7 +3,7 @@
<div class="my20">自定义节点,为节点添加提示</div>
<tiny-cascader v-model="value1" :options="options">
<template #default="{ node }">
<span :title="node.label"> {{ node.label }} <tiny-icon-share /></span>
<span :title="node.label"> {{ node.label }} <tiny-icon-fillet-external-link /></span>
</template>
</tiny-cascader>
<div class="my20">自定义空数据插槽</div>
@ -17,12 +17,12 @@
<script>
import { Cascader } from '@opentiny/vue'
import { iconShare } from '@opentiny/vue-icon'
import { iconFilletExternalLink } from '@opentiny/vue-icon'
export default {
components: {
TinyCascader: Cascader,
TinyIconShare: iconShare()
TinyIconFilletExternalLink: iconFilletExternalLink()
},
data() {
return {

View File

@ -21,7 +21,7 @@
@change="onDialogSelectChange"
value-field="id"
text-field="name"
:main-height="290"
:main-height="240"
>
<template #search>
<div class="tiny-demo-search">
@ -34,6 +34,7 @@
placeholder="选择城市"
:options="state.options"
clearable
@change="onCitySearch"
></tiny-select>
</div>
</div>
@ -48,8 +49,7 @@ import {
DialogSelect as TinyDialogSelect,
Button as TinyButton,
Search as TinySearch,
Select as TinySelect,
Modal
Select as TinySelect
} from '@opentiny/vue'
import Sortable from 'sortablejs'
@ -106,7 +106,7 @@ const state = reactive({
},
gridOp: {
columns: [
{ field: 'id', title: 'ID', width: 40 },
{ field: 'id', title: 'ID', width: 50 },
{ field: 'name', title: '名称', showOverflow: 'tooltip' },
{ field: 'province', title: '省份', width: 80 },
{ field: 'city', title: '城市', width: 80 }
@ -117,6 +117,8 @@ const state = reactive({
reserve: true,
checkRowKeys: ['1', '6']
},
border: false, //
size: 'small', //
//
radioConfig: { checkRowKey: '3' }
},
@ -157,6 +159,12 @@ const onSearch = (key, value) => {
dialogSelect.value.queryGridData()
}
const onCitySearch = (value) => {
state.searchData.city = value
state.pagerOp.currentPage = 1
dialogSelect.value.queryGridData()
}
const remoteSearch = () => {
return new Promise((resolve) => {
setTimeout(() => {
@ -184,22 +192,22 @@ const lookupMethod = (values) => {
}
const onDialogSelectChange = (values, texts, selectedDatas) => {
Modal.message({
message: `values:${values},texts:${texts},selectedDatas:${JSON.stringify(selectedDatas)}`,
status: 'info'
})
// change
console.log({ values, texts, selectedDatas })
}
</script>
<style scoped>
.tiny-demo-dialog-select .tiny-demo-search {
display: flow-root;
}
<style scoped lang="less">
.tiny-demo-search {
display: flex;
.tiny-demo-dialog-select .tiny-demo-search-left,
.tiny-demo-dialog-select .tiny-demo-search-right {
float: left;
width: 200px;
margin-right: 16px;
.tiny-demo-search-left {
flex: 1;
}
.tiny-demo-search-right {
width: 216px;
margin-left: 8px;
}
}
</style>

View File

@ -21,7 +21,7 @@
@change="onDialogSelectChange"
value-field="id"
text-field="name"
:main-height="290"
:main-height="240"
>
<template #search>
<div class="tiny-demo-search">
@ -29,7 +29,13 @@
<tiny-search placeholder="公司名称" is-enter-search @search="onSearch"></tiny-search>
</div>
<div class="tiny-demo-search-right">
<tiny-select v-model="searchData.city" placeholder="选择城市" :options="options" clearable></tiny-select>
<tiny-select
v-model="searchData.city"
placeholder="选择城市"
:options="options"
clearable
@change="onCitySearch"
></tiny-select>
</div>
</div>
</template>
@ -38,7 +44,7 @@
</template>
<script>
import { DialogSelect, Button, Search, Select, Modal } from '@opentiny/vue'
import { DialogSelect, Button, Search, Select } from '@opentiny/vue'
import Sortable from 'sortablejs'
//
@ -91,14 +97,14 @@ export default {
visible: false,
dialogOp: {
top: '20vh',
width: '800px',
width: '700px',
title: '选择公司',
beforeClose: this.beforeClose,
dialogClass: 'custom-dialog-class'
},
gridOp: {
columns: [
{ field: 'id', title: 'ID', width: 40 },
{ field: 'id', title: 'ID', width: 50 },
{ field: 'name', title: '名称', showOverflow: 'tooltip' },
{ field: 'province', title: '省份', width: 80 },
{ field: 'city', title: '城市', width: 80 }
@ -108,15 +114,19 @@ export default {
reserve: true,
checkRowKeys: ['1', '6']
},
border: false,
size: 'small',
//
radioConfig: { checkRowKey: '3' }
},
// Pager
pagerOp: {
currentPage: 1,
pageSize: 5,
pageSizes: [5, 10],
total: 0,
layout: 'prev, pager, next'
layout: 'total, sizes, prev, pager, next',
size: 'mini'
},
selectedBoxOp: {
config: {
@ -145,6 +155,11 @@ export default {
this.pagerOp.currentPage = 1
this.$refs.dialogSelect.queryGridData()
},
onCitySearch(value) {
this.searchData.city = value
this.pagerOp.currentPage = 1
this.$refs.dialogSelect.queryGridData()
},
remoteSearch() {
return new Promise((resolve) => {
setTimeout(() => {
@ -170,24 +185,24 @@ export default {
})
},
onDialogSelectChange(values, texts, selectedDatas) {
Modal.message({
message: `values:${values},texts:${texts},selectedDatas:${JSON.stringify(selectedDatas)}`,
status: 'info'
})
// change
console.log({ values, texts, selectedDatas })
}
}
}
</script>
<style scoped>
.tiny-demo-dialog-select .tiny-demo-search {
display: flow-root;
}
<style scoped lang="less">
.tiny-demo-search {
display: flex;
.tiny-demo-dialog-select .tiny-demo-search-left,
.tiny-demo-dialog-select .tiny-demo-search-right {
float: left;
width: 200px;
margin-right: 16px;
.tiny-demo-search-left {
flex: 1;
}
.tiny-demo-search-right {
width: 186px;
margin-left: 8px;
}
}
</style>

View File

@ -18,7 +18,7 @@
@change="onDialogSelectChange"
value-field="id"
text-field="name"
:main-height="290"
:main-height="240"
>
<template #search>
<div class="tiny-demo-search">
@ -31,6 +31,7 @@
placeholder="选择城市"
:options="state.options"
clearable
@change="onCitySearch"
></tiny-select>
</div>
</div>
@ -45,8 +46,7 @@ import {
DialogSelect as TinyDialogSelect,
Button as TinyButton,
Search as TinySearch,
Select as TinySelect,
Modal
Select as TinySelect
} from '@opentiny/vue'
//
@ -103,20 +103,23 @@ const state = reactive({
},
gridOp: {
columns: [
{ field: 'id', title: 'ID', width: 40 },
{ field: 'id', title: 'ID', width: 50 },
{ field: 'name', title: '名称', showOverflow: 'tooltip' },
{ field: 'province', title: '省份', width: 80 },
{ field: 'city', title: '城市', width: 80 }
],
data: [],
radioConfig: { checkRowKey: '1' }
radioConfig: { checkRowKey: '1' },
border: false, //
size: 'small' //
},
pagerOp: {
currentPage: 1,
pageSize: 5,
pageSizes: [5, 10],
total: 0,
layout: 'prev, pager, next'
layout: 'prev, pager, next',
size: 'mini'
}
})
@ -136,6 +139,12 @@ const onSearch = (key, value) => {
dialogSelect.value.queryGridData()
}
const onCitySearch = (value) => {
state.searchData.city = value
state.pagerOp.currentPage = 1
dialogSelect.value.queryGridData()
}
const remoteSearch = () => {
return new Promise((resolve) => {
setTimeout(() => {
@ -163,22 +172,21 @@ const lookupMethod = (values) => {
}
const onDialogSelectChange = (values, texts, selectedDatas) => {
Modal.message({
message: `values:${values},texts:${texts},selectedDatas:${JSON.stringify(selectedDatas)}`,
status: 'info'
})
// change
console.log({ values, texts, selectedDatas })
}
</script>
<style scoped>
.tiny-demo-dialog-select .tiny-demo-search {
display: flow-root;
}
<style scoped lang="less">
.tiny-demo-search {
display: flex;
.tiny-demo-dialog-select .tiny-demo-search-left,
.tiny-demo-dialog-select .tiny-demo-search-right {
float: left;
width: 200px;
margin-right: 16px;
.tiny-demo-search-left {
flex: 1;
}
.tiny-demo-search-right {
width: 200px;
margin-left: 8px;
}
}
</style>

View File

@ -18,7 +18,7 @@
@change="onDialogSelectChange"
value-field="id"
text-field="name"
:main-height="290"
:main-height="240"
>
<template #search>
<div class="tiny-demo-search">
@ -26,7 +26,13 @@
<tiny-search placeholder="公司名称" is-enter-search @search="onSearch"></tiny-search>
</div>
<div class="tiny-demo-search-right">
<tiny-select v-model="searchData.city" placeholder="选择城市" :options="options" clearable></tiny-select>
<tiny-select
v-model="searchData.city"
placeholder="选择城市"
:options="options"
clearable
@change="onCitySearch"
></tiny-select>
</div>
</div>
</template>
@ -35,7 +41,7 @@
</template>
<script>
import { DialogSelect, Button, Search, Select, Modal } from '@opentiny/vue'
import { DialogSelect, Button, Search, Select } from '@opentiny/vue'
//
const datas = [
@ -86,27 +92,30 @@ export default {
visible: false,
dialogOp: {
top: '20vh',
width: '800px',
width: '700px',
title: '选择公司',
beforeClose: this.beforeClose,
dialogClass: 'custom-dialog-class'
},
gridOp: {
columns: [
{ field: 'id', title: 'ID', width: 40 },
{ field: 'id', title: 'ID', width: 50 },
{ field: 'name', title: '名称', showOverflow: 'tooltip' },
{ field: 'province', title: '省份', width: 80 },
{ field: 'city', title: '城市', width: 80 }
],
data: [],
radioConfig: { checkRowKey: '1' }
radioConfig: { checkRowKey: '1' },
border: false, //
size: 'small' //
},
pagerOp: {
currentPage: 1,
pageSize: 5,
pageSizes: [5, 10],
total: 0,
layout: 'prev, pager, next'
layout: 'prev, pager, next',
size: 'mini'
}
}
},
@ -127,6 +136,11 @@ export default {
this.pagerOp.currentPage = 1
this.$refs.dialogSelect.queryGridData()
},
onCitySearch(value) {
this.searchData.city = value
this.pagerOp.currentPage = 1
this.$refs.dialogSelect.queryGridData()
},
remoteSearch() {
return new Promise((resolve) => {
setTimeout(() => {
@ -152,24 +166,23 @@ export default {
})
},
onDialogSelectChange(values, texts, selectedDatas) {
Modal.message({
message: `values:${values},texts:${texts},selectedDatas:${JSON.stringify(selectedDatas)}`,
status: 'info'
})
// change
console.log({ values, texts, selectedDatas })
}
}
}
</script>
<style scoped>
.tiny-demo-dialog-select .tiny-demo-search {
display: flow-root;
}
<style scoped lang="less">
.tiny-demo-search {
display: flex;
.tiny-demo-dialog-select .tiny-demo-search-left,
.tiny-demo-dialog-select .tiny-demo-search-right {
float: left;
width: 200px;
margin-right: 16px;
.tiny-demo-search-left {
flex: 1;
}
.tiny-demo-search-right {
width: 200px;
margin-left: 8px;
}
}
</style>

View File

@ -1,6 +1,10 @@
<template>
<div class="tiny-demo">
<tiny-button @click="state.visible = !state.visible">{{ `${state.visible ? '关闭' : '打开'}窗口` }}</tiny-button>
<tiny-button @click="state.visible1 = !state.visible1">
{{ `${state.visible1 ? '关闭' : '打开'}窗口(插槽自定义场景)` }}
</tiny-button>
<tiny-dialog-select
ref="dialogSelect"
class="tiny-demo-tree-multi"
@ -17,6 +21,24 @@
value-field="id"
text-field="label"
:main-height="290"
>
</tiny-dialog-select>
<tiny-dialog-select
ref="dialogSelect1"
class="tiny-demo-tree-multi"
:visible="state.visible1"
@update:visible="state.visible1 = $event"
popseletor="tree"
multi
:dialog-op="state.dialogOp"
:tree-op="state.treeOp"
:selected-box-op="state.selectedBoxOp"
:lookup-method="lookupMethod"
:before-close="beforeClose"
@change="onDialogSelectChange"
value-field="id"
text-field="label"
:main-height="290"
>
<template #option="{ option, mouseenter, mouseleave }">
<div class="tiny-demo-tree-multi-option" @mouseenter="mouseenter" @mouseleave="mouseleave">
@ -37,7 +59,7 @@
<script setup lang="ts">
import { reactive } from 'vue'
import { DialogSelect as TinyDialogSelect, Button as TinyButton, Modal } from '@opentiny/vue'
import { DialogSelect as TinyDialogSelect, Button as TinyButton } from '@opentiny/vue'
import { iconClose } from '@opentiny/vue-icon'
import Sortable from 'sortablejs'
@ -143,6 +165,7 @@ const beforeClose = () => {
const state = reactive({
visible: false,
visible1: false,
dialogOp: {
top: '20vh',
width: '800px',
@ -167,7 +190,8 @@ const state = reactive({
load: remoteSearch,
queryPidsBySearch,
queryPidsByIds,
defaultCheckedKeys: [1, 4, 8]
defaultCheckedKeys: [1, 4, 8],
showLine: true
}
})
@ -188,10 +212,8 @@ const lookupMethod = (values) => {
}
const onDialogSelectChange = (values, texts, selectedDatas) => {
Modal.message({
message: `values:${values},texts:${texts},selectedDatas:${JSON.stringify(selectedDatas)}`,
status: 'info'
})
// change
console.log({ values, texts, selectedDatas })
}
</script>
@ -201,28 +223,32 @@ const onDialogSelectChange = (values, texts, selectedDatas) => {
text-overflow: ellipsis;
white-space: nowrap;
height: 28px;
line-height: 28px;
}
.tiny-demo-tree-multi .tiny-demo-tree-multi-option .title {
color: #161e26;
position: relative;
top: 4px;
color: #191919;
font-size: 14px;
}
.tiny-demo-tree-multi .tiny-demo-tree-multi-option .sub-text {
color: #8d959e;
position: relative;
top: 4px;
color: #808080;
margin-left: 8px;
}
.tiny-demo-tree-multi-close {
height: 28px;
line-height: 28px;
font-size: 0;
.tiny-svg {
fill: #808080;
font-size: 16px;
}
}
.tiny-demo-tree-multi-close > span {
position: relative;
top: 2px;
left: 12px;
}
</style>

View File

@ -1,6 +1,9 @@
<template>
<div class="tiny-demo">
<tiny-button @click="visible = !visible">{{ `${visible ? '关闭' : '打开'}窗口` }}</tiny-button>
<tiny-button @click="visible1 = !visible1">
{{ `${visible1 ? '关闭' : '打开'}窗口(插槽自定义场景)` }}
</tiny-button>
<tiny-dialog-select
ref="dialogSelect"
class="tiny-demo-tree-multi"
@ -17,6 +20,24 @@
value-field="id"
text-field="label"
:main-height="290"
>
</tiny-dialog-select>
<tiny-dialog-select
ref="dialogSelect"
class="tiny-demo-tree-multi"
:visible="visible1"
@update:visible="visible1 = $event"
popseletor="tree"
multi
:dialog-op="dialogOp"
:tree-op="treeOp"
:selected-box-op="selectedBoxOp"
:lookup-method="lookupMethod"
:before-close="beforeClose"
@change="onDialogSelectChange"
value-field="id"
text-field="label"
:main-height="290"
>
<template #option="{ option, mouseenter, mouseleave }">
<div class="tiny-demo-tree-multi-option" @mouseenter="mouseenter" @mouseleave="mouseleave">
@ -36,7 +57,7 @@
</template>
<script>
import { DialogSelect, Button, Modal } from '@opentiny/vue'
import { DialogSelect, Button } from '@opentiny/vue'
import { iconClose } from '@opentiny/vue-icon'
import Sortable from 'sortablejs'
@ -122,6 +143,7 @@ export default {
data() {
return {
visible: false,
visible1: false,
dialogOp: {
top: '20vh',
width: '800px',
@ -146,7 +168,8 @@ export default {
load: this.remoteSearch,
queryPidsBySearch: this.queryPidsBySearch,
queryPidsByIds: this.queryPidsByIds,
defaultCheckedKeys: [1, 4, 8]
defaultCheckedKeys: [1, 4, 8],
showLine: true
}
}
},
@ -189,10 +212,8 @@ export default {
})
},
onDialogSelectChange(values, texts, selectedDatas) {
Modal.message({
message: `values:${values},texts:${texts},selectedDatas:${JSON.stringify(selectedDatas)}`,
status: 'info'
})
// change
console.log({ values, texts, selectedDatas })
}
}
}
@ -204,28 +225,29 @@ export default {
text-overflow: ellipsis;
white-space: nowrap;
height: 28px;
line-height: 28px;
}
.tiny-demo-tree-multi .tiny-demo-tree-multi-option .title {
color: #161e26;
position: relative;
top: 4px;
font-size: 14px;
}
.tiny-demo-tree-multi .tiny-demo-tree-multi-option .sub-text {
color: #8d959e;
position: relative;
top: 4px;
margin-left: 8px;
}
.tiny-demo-tree-multi-close {
height: 28px;
line-height: 28px;
svg {
fill: #808080;
}
}
.tiny-demo-tree-multi-close > span {
position: relative;
top: 2px;
left: 12px;
}
</style>

View File

@ -21,7 +21,7 @@
<script setup lang="ts">
import { reactive } from 'vue'
import { DialogSelect as TinyDialogSelect, Button as TinyButton, Modal } from '@opentiny/vue'
import { DialogSelect as TinyDialogSelect, Button as TinyButton } from '@opentiny/vue'
//
const datas = [
@ -139,7 +139,8 @@ const state = reactive({
load: remoteSearch,
queryPidsBySearch,
queryPidsByIds,
defaultCheckedKeys: [4]
defaultCheckedKeys: [4],
showLine: true
}
})
@ -159,9 +160,7 @@ const lookupMethod = (values) => {
})
}
const onDialogSelectChange = (values, texts, selectedDatas) => {
Modal.message({
message: `values:${values},texts:${texts},selectedDatas:${JSON.stringify(selectedDatas)}`,
status: 'info'
})
// change
console.log({ values, texts, selectedDatas })
}
</script>

View File

@ -20,7 +20,7 @@
</template>
<script>
import { DialogSelect, Button, Modal } from '@opentiny/vue'
import { DialogSelect, Button } from '@opentiny/vue'
//
const datas = [
@ -119,7 +119,8 @@ export default {
load: this.remoteSearch,
queryPidsBySearch: this.queryPidsBySearch,
queryPidsByIds: this.queryPidsByIds,
defaultCheckedKeys: [4]
defaultCheckedKeys: [4],
showLine: true
}
}
},
@ -161,10 +162,8 @@ export default {
})
},
onDialogSelectChange(values, texts, selectedDatas) {
Modal.message({
message: `values:${values},texts:${texts},selectedDatas:${JSON.stringify(selectedDatas)}`,
status: 'info'
})
// change
console.log({ values, texts, selectedDatas })
}
}
}

View File

@ -0,0 +1,218 @@
<template>
<div class="tiny-demo">
<tiny-button @click="changeVisible">{{ `${state.visible ? '关闭' : '打开'}窗口` }}</tiny-button>
<tiny-button @click="setSelection" :disabled="!state.init">切换第二行选中状态</tiny-button>
<tiny-dialog-select
ref="dialogSelect"
class="tiny-demo-dialog-select"
:visible="state.visible"
@update:visible="state.visible = $event"
popseletor="grid"
multi
:dialog-op="state.dialogOp"
:grid-op="state.gridOp"
:pager-op="state.pagerOp"
:selected-box-op="state.selectedBoxOp"
:remote-search="remoteSearch"
:lookup-method="lookupMethod"
:before-close="beforeClose"
@size-change="onSizeChange"
@current-change="onCurrentChange"
@close="saveSelection"
value-field="id"
text-field="name"
:main-height="290"
>
<template #search>
<div class="tiny-demo-search">
<div class="tiny-demo-search-left">
<tiny-search placeholder="公司名称" is-enter-search @search="onSearch"></tiny-search>
</div>
<div class="tiny-demo-search-right">
<tiny-select
v-model="state.searchData.city"
placeholder="选择城市"
:options="state.options"
clearable
></tiny-select>
</div>
</div>
</template>
</tiny-dialog-select>
</div>
</template>
<script setup lang="ts">
import { reactive, ref } from 'vue'
import {
DialogSelect as TinyDialogSelect,
Button as TinyButton,
Search as TinySearch,
Select as TinySelect
} from '@opentiny/vue'
import Sortable from 'sortablejs'
//
const datas = [
{ id: '1', name: 'GFD科技有限公司', city: '福州', province: '福建' },
{ id: '2', name: 'WWW科技有限公司', city: '深圳', province: '广东' },
{ id: '3', name: 'RFV有限责任公司', city: '中山', province: '广东' },
{ id: '4', name: 'TGB科技有限公司', city: '龙岩', province: '福建' },
{ id: '5', name: 'YHN科技有限公司', city: '韶关', province: '广东' },
{ id: '6', name: 'WSX科技有限公司', city: '黄冈', province: '湖北' },
{ id: '7', name: 'KBG物业有限公司', city: '赤壁', province: '湖北' },
{ id: '8', name: '深圳市福德宝网络技术有限公司', city: '深圳', province: '广东' },
{ id: '9', name: 'KBG物业有限公司', city: '赤壁', province: '湖北' },
{ id: '10', name: '深圳市福德宝网络技术有限公司', city: '深圳', province: '广东' }
]
// 1id
const queryRowsByIds = (ids) => datas.filter((row) => ~ids.indexOf(row.id))
// 2
const queryFilter = (pager, search) => {
const { currentPage, pageSize } = pager
const { name, city } = search
const start = (currentPage - 1) * pageSize
const end = currentPage * pageSize
//
const filtered = datas.filter((row) => (!name || ~row.name.indexOf(name)) && (!city || row.city === city))
//
const data = filtered.slice(start, end)
return { data, total: datas.length }
}
const beforeClose = () => {
return true
}
const state = reactive({
init: false,
selectedDatas: [],
multi: true,
searchData: { name: '', city: '' },
options: [
{ value: '福州', label: '福州' },
{ value: '深圳', label: '深圳' },
{ value: '赤壁', label: '赤壁' }
],
visible: false,
dialogOp: {
top: '20vh',
width: '800px',
title: '选择公司',
beforeClose,
dialogClass: 'custom-dialog-class'
},
gridOp: {
columns: [
{ field: 'id', title: 'ID', width: 50 },
{ field: 'name', title: '名称', showOverflow: 'tooltip' },
{ field: 'province', title: '省份', width: 80 },
{ field: 'city', title: '城市', width: 80 }
],
data: [],
//
selectConfig: {
reserve: true,
checkRowKeys: ['1', '6']
},
//
radioConfig: { checkRowKey: '3' }
},
pagerOp: {
currentPage: 1,
pageSize: 5,
pageSizes: [5, 10],
total: 0,
layout: 'prev, pager, next'
},
selectedBoxOp: {
config: {
pkField: 'id',
pkFieldType: 'string',
showField: ['name', 'city'],
plugin: Sortable
}
}
})
const dialogSelect = ref('')
const onSizeChange = (pageSize) => {
state.pagerOp.pageSize = pageSize
dialogSelect.value.valuequeryGridData()
}
const onCurrentChange = (currentPage) => {
state.pagerOp.currentPage = currentPage
dialogSelect.value.queryGridData()
}
const onSearch = (key, value) => {
state.searchData.name = value
state.pagerOp.currentPage = 1
dialogSelect.value.queryGridData()
}
const remoteSearch = () => {
return new Promise((resolve) => {
setTimeout(() => {
const res = queryFilter(state.pagerOp, state.searchData)
//
const copy = JSON.parse(JSON.stringify(res.data))
state.gridOp.data = copy
state.pagerOp.total = res.total
// promise
resolve()
}, 300)
})
}
const lookupMethod = (values) => {
return new Promise((resolve) => {
setTimeout(() => {
const res = queryRowsByIds(values)
//
const copy = JSON.parse(JSON.stringify(res))
resolve(copy)
}, 300)
})
}
function changeVisible() {
state.visible = !state.visible
state.init = true
}
function saveSelection() {
state.selectedDatas = dialogSelect.value.getSelection()
}
function setSelection() {
let value = true
// id
if (state.selectedDatas.map((i) => i.id).includes(datas[1].id)) {
value = false
}
dialogSelect.value.setSelection([datas[1]], value)
saveSelection()
}
</script>
<style scoped lang="less">
.tiny-demo-search {
display: flex;
.tiny-demo-search-left {
flex: 1;
}
.tiny-demo-search-right {
width: 216px;
margin-left: 8px;
}
}
</style>

View File

@ -0,0 +1,204 @@
<template>
<div class="tiny-demo">
<tiny-button @click="changeVisible">{{ `${visible ? '关闭' : '打开'}窗口` }}</tiny-button>
<tiny-button @click="setSelection" :disabled="!init">切换第二行选中状态</tiny-button>
<tiny-dialog-select
ref="dialogSelect"
class="tiny-demo-dialog-select"
:visible="visible"
@update:visible="visible = $event"
popseletor="grid"
multi
:dialog-op="dialogOp"
:grid-op="gridOp"
:pager-op="pagerOp"
:selected-box-op="selectedBoxOp"
:remote-search="remoteSearch"
:lookup-method="lookupMethod"
:before-close="beforeClose"
@size-change="onSizeChange"
@current-change="onCurrentChange"
@close="saveSelection"
value-field="id"
text-field="name"
:main-height="290"
>
<template #search>
<div class="tiny-demo-search">
<div class="tiny-demo-search-left">
<tiny-search placeholder="公司名称" is-enter-search @search="onSearch"></tiny-search>
</div>
<div class="tiny-demo-search-right">
<tiny-select v-model="searchData.city" placeholder="选择城市" :options="options" clearable></tiny-select>
</div>
</div>
</template>
</tiny-dialog-select>
</div>
</template>
<script>
import { DialogSelect, Button, Search, Select } from '@opentiny/vue'
import Sortable from 'sortablejs'
//
const datas = [
{ id: '1', name: 'GFD科技有限公司', city: '福州', province: '福建' },
{ id: '2', name: 'WWW科技有限公司', city: '深圳', province: '广东' },
{ id: '3', name: 'RFV有限责任公司', city: '中山', province: '广东' },
{ id: '4', name: 'TGB科技有限公司', city: '龙岩', province: '福建' },
{ id: '5', name: 'YHN科技有限公司', city: '韶关', province: '广东' },
{ id: '6', name: 'WSX科技有限公司', city: '黄冈', province: '湖北' },
{ id: '7', name: 'KBG物业有限公司', city: '赤壁', province: '湖北' },
{ id: '8', name: '深圳市福德宝网络技术有限公司', city: '深圳', province: '广东' },
{ id: '9', name: 'KBG物业有限公司', city: '赤壁', province: '湖北' },
{ id: '10', name: '深圳市福德宝网络技术有限公司', city: '深圳', province: '广东' }
]
// 1id
const queryRowsByIds = (ids) => datas.filter((row) => ~ids.indexOf(row.id))
// 2
const queryFilter = (pager, search) => {
const { currentPage, pageSize } = pager
const { name, city } = search
const start = (currentPage - 1) * pageSize
const end = currentPage * pageSize
//
const filtered = datas.filter((row) => (!name || ~row.name.indexOf(name)) && (!city || row.city === city))
//
const data = filtered.slice(start, end)
return { data, total: datas.length }
}
export default {
components: {
TinyDialogSelect: DialogSelect,
TinyButton: Button,
TinySearch: Search,
TinySelect: Select
},
data() {
return {
init: false,
searchData: { name: '', city: '' },
selectedDatas: [],
options: [
{ value: '福州', label: '福州' },
{ value: '深圳', label: '深圳' },
{ value: '赤壁', label: '赤壁' }
],
visible: false,
dialogOp: {
top: '20vh',
width: '800px',
title: '选择公司',
beforeClose: this.beforeClose,
dialogClass: 'custom-dialog-class'
},
gridOp: {
columns: [
{ field: 'id', title: 'ID', width: 50 },
{ field: 'name', title: '名称', showOverflow: 'tooltip' },
{ field: 'province', title: '省份', width: 80 },
{ field: 'city', title: '城市', width: 80 }
],
data: [],
selectConfig: {
reserve: true,
checkRowKeys: ['1', '6']
}
},
pagerOp: {
currentPage: 1,
pageSize: 5,
pageSizes: [5, 10],
total: 0,
layout: 'prev, pager, next'
},
selectedBoxOp: {
config: {
pkField: 'id',
pkFieldType: 'string',
showField: ['name', 'city'],
plugin: Sortable
}
}
}
},
methods: {
beforeClose() {
return true
},
onSizeChange(pageSize) {
this.pagerOp.pageSize = pageSize
this.$refs.dialogSelect.queryGridData()
},
onCurrentChange(currentPage) {
this.pagerOp.currentPage = currentPage
this.$refs.dialogSelect.queryGridData()
},
onSearch(key, value) {
this.searchData.name = value
this.pagerOp.currentPage = 1
this.$refs.dialogSelect.queryGridData()
},
remoteSearch() {
return new Promise((resolve) => {
setTimeout(() => {
const res = queryFilter(this.pagerOp, this.searchData)
//
const copy = JSON.parse(JSON.stringify(res.data))
this.gridOp.data = copy
this.pagerOp.total = res.total
// promise
resolve()
}, 300)
})
},
lookupMethod(values) {
return new Promise((resolve) => {
setTimeout(() => {
const res = queryRowsByIds(values)
//
const copy = JSON.parse(JSON.stringify(res))
resolve(copy)
}, 300)
})
},
changeVisible() {
this.visible = !this.visible
this.init = true
},
saveSelection() {
this.selectedDatas = this.$refs.dialogSelect.getSelection()
},
setSelection() {
let value = true
// id
if (this.selectedDatas.map((i) => i.id).includes(datas[1].id)) {
value = false
}
this.$refs.dialogSelect.setSelection([datas[1]], value)
this.saveSelection()
}
}
}
</script>
<style scoped lang="less">
.tiny-demo-search {
display: flex;
.tiny-demo-search-left {
flex: 1;
}
.tiny-demo-search-right {
width: 216px;
margin-left: 8px;
}
}
</style>

View File

@ -1,6 +1,6 @@
export default {
column: '2',
owner: '詹旖旎 30021340',
owner: '',
demos: [
{
demoId: 'nest-grid-multi',
@ -57,6 +57,20 @@ export default {
'<p>Use the <code>auto-lookup</code>,<code>lookup-method</code> attributes, and <code>change</code> events to set the anti lookup echo function for data initialization.</p>\n<p>Tree selection scenarios require setting <code>popcollector</code> to <code>tree</code>,<code>multi</code> to <code>false</code>, and<code>defaultCheckedKeys</code>to set default selected data.</p>\n'
},
codeFiles: ['nest-tree-single.vue']
},
{
demoId: 'set-selection',
name: {
'zh-CN': '设置多选状态',
'en-US': 'Tree radio selection'
},
desc: {
'zh-CN':
'<p>通过 <code>auto-lookup</code>、<code>lookup-method</code> 属性和 <code>change</code> 事件设置初始化时数据的反查回显功能。</p>\n<p>树单选场景需要设置 <code>popselector</code> 为 <code>tree</code><code>multi</code> 为 <code>false</code ><code>defaultCheckedKeys</code> 设置默认选中数据。</p>\n',
'en-US':
'<p>Use the <code>auto-lookup</code>,<code>lookup-method</code> attributes, and <code>change</code> events to set the anti lookup echo function for data initialization.</p>\n<p>Tree selection scenarios require setting <code>popcollector</code> to <code>tree</code>,<code>multi</code> to <code>false</code>, and<code>defaultCheckedKeys</code>to set default selected data.</p>\n'
},
codeFiles: ['set-selection.vue']
}
]
}

View File

@ -26,6 +26,20 @@
</tiny-dropdown-menu>
</template>
</tiny-dropdown>
<p>场景3前置图标</p>
<tiny-dropdown :prefix-icon="tinyIconLanguage" :show-icon="false">
<template #dropdown>
<tiny-dropdown-menu>
<tiny-dropdown-item label="老友粉"></tiny-dropdown-item>
<tiny-dropdown-item>黄金糕</tiny-dropdown-item>
<tiny-dropdown-item>狮子头</tiny-dropdown-item>
<tiny-dropdown-item>螺蛳粉</tiny-dropdown-item>
<tiny-dropdown-item>双皮奶</tiny-dropdown-item>
<tiny-dropdown-item>蚵仔煎</tiny-dropdown-item>
</tiny-dropdown-menu>
</template>
</tiny-dropdown>
</div>
</template>
@ -35,9 +49,10 @@ import {
DropdownMenu as TinyDropdownMenu,
DropdownItem as TinyDropdownItem
} from '@opentiny/vue'
import { iconEllipsis } from '@opentiny/vue-icon'
import { iconEllipsis, iconLanguage } from '@opentiny/vue-icon'
const tinyIconEllipsis = iconEllipsis()
const tinyIconLanguage = iconLanguage()
</script>
<style lang="less" scoped>

View File

@ -26,12 +26,25 @@
</tiny-dropdown-menu>
</template>
</tiny-dropdown>
<p>场景3前置图标</p>
<tiny-dropdown :prefix-icon="tinyIconLanguage" :show-icon="false">
<template #dropdown>
<tiny-dropdown-menu>
<tiny-dropdown-item label="老友粉"></tiny-dropdown-item>
<tiny-dropdown-item>黄金糕</tiny-dropdown-item>
<tiny-dropdown-item>狮子头</tiny-dropdown-item>
<tiny-dropdown-item>螺蛳粉</tiny-dropdown-item>
<tiny-dropdown-item>双皮奶</tiny-dropdown-item>
<tiny-dropdown-item>蚵仔煎</tiny-dropdown-item>
</tiny-dropdown-menu>
</template>
</tiny-dropdown>
</div>
</template>
<script>
import { Dropdown, DropdownMenu, DropdownItem } from '@opentiny/vue'
import { iconEllipsis } from '@opentiny/vue-icon'
import { iconEllipsis, iconLanguage } from '@opentiny/vue-icon'
export default {
components: {
@ -41,7 +54,8 @@ export default {
},
data() {
return {
tinyIconEllipsis: iconEllipsis()
tinyIconEllipsis: iconEllipsis(),
tinyIconLanguage: iconLanguage()
}
}
}

View File

@ -1,18 +1,18 @@
<template>
<div class="tiny-upload__text">将文件拖到此处<em>点击上传</em></div>
<tiny-file-upload drag :action="action" multiple accept=".png,.jpeg,.jpg" @drop-error="dropErrorHandler">
<tiny-icon-fileupload class="tiny-svg-size icon-fileupload"></tiny-icon-fileupload>
<tiny-icon-picture class="tiny-svg-size icon-fileupload"></tiny-icon-picture>
</tiny-file-upload>
</template>
<script setup>
import { ref } from 'vue'
import { FileUpload as TinyFileUpload, Modal } from '@opentiny/vue'
import { iconFileupload } from '@opentiny/vue-icon'
import { iconPicture } from '@opentiny/vue-icon'
const action = ref('http://localhost:3000/api/upload')
const TinyIconFileupload = iconFileupload()
const TinyIconPicture = iconPicture()
function dropErrorHandler(files) {
Modal.message(`${files.length}个文件拖拽失败`)

View File

@ -1,18 +1,18 @@
<template>
<div class="tiny-upload__text">将文件拖到此处<em>点击上传</em></div>
<tiny-file-upload drag :action="action" multiple accept=".png,.jpeg,.jpg" @drop-error="dropErrorHandler">
<tiny-icon-fileupload-pro class="tiny-svg-size icon-fileupload"></tiny-icon-fileupload-pro>
<tiny-icon-picture class="tiny-svg-size icon-fileupload"></tiny-icon-picture>
</tiny-file-upload>
</template>
<script>
import { FileUpload, Modal } from '@opentiny/vue'
import { IconFileuploadPro } from '@opentiny/vue-icon'
import { iconPicture } from '@opentiny/vue-icon'
export default {
components: {
TinyFileUpload: FileUpload,
TinyIconFileuploadPro: IconFileuploadPro()
TinyIconPicture: iconPicture()
},
data() {
return {

View File

@ -15,7 +15,7 @@
<script setup>
import { ref } from 'vue'
import { FileUpload as TinyFileUpload, Button as TinyButton } from '@opentiny/vue'
import { iconEditorListNum } from '@opentiny/vue-icon'
import { IconEditorList } from '@opentiny/vue-icon'
const options = ref({
width: 300,
@ -27,7 +27,7 @@ const options = ref({
// downloadFile: (file) => {
// console.log('file', file)
// },
icon: iconEditorListNum()
icon: IconEditorList()
})
const fileList = ref([
{

View File

@ -14,7 +14,7 @@
<script>
import { FileUpload, Button } from '@opentiny/vue'
import { iconEditorListNum } from '@opentiny/vue-icon'
import { IconEditorList } from '@opentiny/vue-icon'
export default {
components: {
@ -33,7 +33,7 @@ export default {
// downloadFile: (file) => {
// console.log('file', file)
// },
icon: iconEditorListNum()
icon: IconEditorList()
},
fileList: [
{

View File

@ -0,0 +1,83 @@
<template>
<tiny-grid
:data="tableData"
show-overflow="ellipsis"
:edit-config="{ activeMethod, mode: 'row', activeStrictly: true }"
:cell-class-name="cellClassName"
>
<tiny-grid-column type="index" width="60"></tiny-grid-column>
<tiny-grid-column field="name" title="名称" :editor="{ component: 'input' }"></tiny-grid-column>
<tiny-grid-column field="area" title="区域" :editor="{ component: 'select', options }"></tiny-grid-column>
<tiny-grid-column field="address" title="地址" :editor="{ component: 'input' }"></tiny-grid-column>
<tiny-grid-column field="introduction" title="公司简介" :editor="{ component: 'input' }"></tiny-grid-column>
</tiny-grid>
</template>
<script setup>
import { ref } from 'vue'
import { Grid as TinyGrid, GridColumn as TinyGridColumn } from '@opentiny/vue'
const options = ref([
{ label: '华北区', value: '华北区' },
{ label: '华东区', value: '华东区' },
{ label: '华南区', value: '华南区' }
])
const tableData = ref([
{
id: '1',
name: 'GFD科技有限公司',
area: '华东区',
address: '福州',
introduction: '公司技术和研发实力雄厚是国家863项目的参与者并被政府认定为“高新技术企业”。'
},
{
id: '2',
name: 'WWWW科技有限公司',
area: '华南区',
address: '深圳福田区',
introduction: '公司技术和研发实力雄厚是国家863项目的参与者并被政府认定为“高新技术企业”。'
},
{
id: '3',
name: 'RFV有限责任公司',
area: '华南区',
address: '中山市',
introduction: '公司技术和研发实力雄厚是国家863项目的参与者并被政府认定为“高新技术企业”。'
},
{
id: '4',
name: 'TGB有限公司',
area: '华北区',
address: '梅州',
introduction: '公司技术和研发实力雄厚是国家863项目的参与者并被政府认定为“高新技术企业”。'
},
{
id: '5',
name: 'YHN科技有限公司',
area: '华南区',
address: '韶关',
introduction: '公司技术和研发实力雄厚是国家863项目的参与者并被政府认定为“高新技术企业”。'
},
{
id: '6',
name: '康康物业有限公司',
area: '华北区',
address: '广州天河区',
introduction: '公司技术和研发实力雄厚是国家863项目的参与者并被政府认定为“高新技术企业”。'
}
])
function activeMethod({ row, column }) {
return column.property !== 'name' && row.id !== '3'
}
function cellClassName({ row, column }) {
return activeMethod({ row, column }) ? '' : 'disable-cell-edit'
}
</script>
<style>
.disable-cell-edit {
background-color: #e8ebef;
}
</style>

View File

@ -0,0 +1,11 @@
import { test, expect } from '@playwright/test'
test('维护编辑状态', async ({ page }) => {
page.on('pageerror', (exception) => expect(exception).toBeNull())
await page.goto('grid-editor#active-strictly')
await page.getByRole('cell', { name: '福州' }).click()
const demo = page.locator('#active-strictly')
await expect(
demo.locator('.tiny-grid-body__row').first().locator('.tiny-grid-body__column').nth(1).locator('input')
).toHaveCount(0)
})

View File

@ -0,0 +1,92 @@
<template>
<tiny-grid
:data="tableData"
show-overflow="ellipsis"
:edit-config="{ activeMethod, mode: 'row', activeStrictly: true }"
:cell-class-name="cellClassName"
>
<tiny-grid-column type="index" width="60"></tiny-grid-column>
<tiny-grid-column field="name" title="名称" :editor="{ component: 'input' }"></tiny-grid-column>
<tiny-grid-column field="area" title="区域" :editor="{ component: 'select', options }"></tiny-grid-column>
<tiny-grid-column field="address" title="地址" :editor="{ component: 'input' }"></tiny-grid-column>
<tiny-grid-column field="introduction" title="公司简介" :editor="{ component: 'input' }"></tiny-grid-column>
</tiny-grid>
</template>
<script>
import { Grid, GridColumn } from '@opentiny/vue'
export default {
components: {
TinyGrid: Grid,
TinyGridColumn: GridColumn
},
data() {
return {
options: [
{ label: '华北区', value: '华北区' },
{ label: '华东区', value: '华东区' },
{ label: '华南区', value: '华南区' }
],
tableData: [
{
id: '1',
name: 'GFD科技有限公司',
area: '华东区',
address: '福州',
introduction: '公司技术和研发实力雄厚是国家863项目的参与者并被政府认定为“高新技术企业”。'
},
{
id: '2',
name: 'WWWW科技有限公司',
area: '华南区',
address: '深圳福田区',
introduction: '公司技术和研发实力雄厚是国家863项目的参与者并被政府认定为“高新技术企业”。'
},
{
id: '3',
name: 'RFV有限责任公司',
area: '华南区',
address: '中山市',
introduction: '公司技术和研发实力雄厚是国家863项目的参与者并被政府认定为“高新技术企业”。'
},
{
id: '4',
name: 'TGB有限公司',
area: '华北区',
address: '梅州',
introduction: '公司技术和研发实力雄厚是国家863项目的参与者并被政府认定为“高新技术企业”。'
},
{
id: '5',
name: 'YHN科技有限公司',
area: '华南区',
address: '韶关',
introduction: '公司技术和研发实力雄厚是国家863项目的参与者并被政府认定为“高新技术企业”。'
},
{
id: '6',
name: '康康物业有限公司',
area: '华北区',
address: '广州天河区',
introduction: '公司技术和研发实力雄厚是国家863项目的参与者并被政府认定为“高新技术企业”。'
}
]
}
},
methods: {
activeMethod({ row, column }) {
return column.property !== 'name' && row.id !== '3'
},
cellClassName({ row, column }) {
return this.activeMethod({ row, column }) ? '' : 'disable-cell-edit'
}
}
}
</script>
<style>
.disable-cell-edit {
background-color: #e8ebef;
}
</style>

View File

@ -4,7 +4,9 @@ test('键盘导航测试', async ({ page }) => {
page.on('pageerror', (exception) => expect(exception).toBeNull())
const demo = page.locator('#mouse-keyboard-keyboard-navigation')
await page.goto('grid-mouse-keyboard#mouse-keyboard-keyboard-navigation')
await page.getByText('GFD科技YX公司').click()
await page.waitForTimeout(300)
await page.locator('body').press('ArrowDown')
await page.waitForTimeout(300)
await page.locator('body').press('F2')

View File

@ -64,6 +64,16 @@ export default {
},
'codeFiles': ['editor/editor-bg.vue']
},
{
'demoId': 'active-strictly',
'name': { 'zh-CN': '行编辑禁用特定列', 'en-US': '' },
'desc': {
'zh-CN':
"<p>当 <code>editConfig.mode</code> 为'row'时,行编辑激活状态下默认会忽略 <code>editConfig.activeMethod</code> ,配置 <code>editConfig.activeStrictly</code> 为true使其生效",
'en-US': ''
},
'codeFiles': ['editor/active-strictly.vue']
},
{
'demoId': 'editor-custom-edit',
'name': { 'zh-CN': '多行编辑', 'en-US': '' },

View File

@ -0,0 +1,38 @@
<template>
<div class="icon-demo">
<color-administrative-fees
first-color="#2070F3"
second-color="#715AFB"
class="tiny-svg-size"
></color-administrative-fees>
<color-express-delivery first-color="#2070F3" second-color="#715AFB" class="tiny-svg-size"></color-express-delivery>
<color-meal-allowance first-color="#2070F3" second-color="#715AFB" class="tiny-svg-size"></color-meal-allowance>
<color-lodging-fees first-color="#2070F3" second-color="#715AFB" class="tiny-svg-size"></color-lodging-fees>
</div>
</template>
<script setup>
import {
ColorIconAdministrativeFees,
ColorIconExpressDelivery,
ColorIconMealAllowance,
ColorIconLodgingFees
} from '@opentiny/vue-icon-multicolor'
const ColorAdministrativeFees = ColorIconAdministrativeFees()
const ColorExpressDelivery = ColorIconExpressDelivery()
const ColorMealAllowance = ColorIconMealAllowance()
const ColorLodgingFees = ColorIconLodgingFees()
</script>
<style scoped>
.icon-demo .tiny-svg-size {
fill: #8994aa;
margin: 20px 50px;
vertical-align: middle;
}
.icon-demo {
font-size: 2em;
}
</style>

View File

@ -0,0 +1,54 @@
<template>
<div class="icon-demo">
<color-icon-administrative-fees
first-color="#2070F3"
second-color="#715AFB"
class="tiny-svg-size"
></color-icon-administrative-fees>
<color-icon-express-delivery
first-color="#2070F3"
second-color="#715AFB"
class="tiny-svg-size"
></color-icon-express-delivery>
<color-icon-meal-allowance
first-color="#2070F3"
second-color="#715AFB"
class="tiny-svg-size"
></color-icon-meal-allowance>
<color-icon-lodging-fees
first-color="#2070F3"
second-color="#715AFB"
class="tiny-svg-size"
></color-icon-lodging-fees>
</div>
</template>
<script>
import {
ColorIconAdministrativeFees,
ColorIconExpressDelivery,
ColorIconMealAllowance,
ColorIconLodgingFees
} from '@opentiny/vue-icon-multicolor'
export default {
components: {
ColorIconAdministrativeFees: ColorIconAdministrativeFees(),
ColorIconExpressDelivery: ColorIconExpressDelivery(),
ColorIconMealAllowance: ColorIconMealAllowance(),
ColorIconLodgingFees: ColorIconLodgingFees()
}
}
</script>
<style scoped>
.icon-demo .tiny-svg-size {
fill: #8994aa;
margin: 20px 50px;
vertical-align: middle;
}
.icon-demo {
font-size: 2em;
}
</style>

View File

@ -0,0 +1,120 @@
<template>
<div>
<div class="svgs-wrapper">
<div v-for="(icon, index) in MultiColorSvgs" :key="index">
<div class="svgs-item">
<component
:is="icon.component"
class="svgs-icon"
style="width: 2em; fill: #000; height: 2em"
@click="click(icon.name)"
></component>
<span class="svgs-text">{{ icon.name }}</span>
</div>
</div>
</div>
</div>
</template>
<script setup>
import MultiColorSvgsList from '@opentiny/vue-icon-multicolor'
import { Modal } from '@opentiny/vue'
const tinyIconMulticolor = [
'ColorIconActivitys',
'ColorIconAdministrativeFees',
'ColorIconAirFares',
'ColorIconApply',
'ColorIconArchives',
'ColorIconBaggageFees',
'ColorIconCarInsurance',
'ColorIconCarRental',
'ColorIconCeremonyFees',
'ColorIconConolences',
'ColorIconEntertainmentExpense',
'ColorIconExpertConsultationFees',
'ColorIconExpertTeachingFees',
'ColorIconExpressDelivery',
'ColorIconFerryFares',
'ColorIconFuelCost',
'ColorIconGiftCost',
'ColorIconHousingSubsidy',
'ColorIconIncidentalExpenses',
'ColorIconLandlinePhone',
'ColorIconLineRental',
'ColorIconLivingSubsidy',
'ColorIconLodgingFees',
'ColorIconMaintenanceService',
'ColorIconMealAllowance',
'ColorIconMealSubsidy',
'ColorIconMeetingExpenses',
'ColorIconNewspaperSubscription',
'ColorIconOfficeEquipments',
'ColorIconOfficeSupplies',
'ColorIconOthers',
'ColorIconPhoneBills',
'ColorIconPhysicalExamination',
'ColorIconPrivateVehicleAllowance',
'ColorIconServiceCharges',
'ColorIconTaxiFares',
'ColorIconTrainFares',
'ColorIconTrainingFees',
'ColorIconTravelExpenses',
'ColorIconVenueHospitalityFees',
'ColorIconVenueRentalFees',
'ColorIconVisaFees'
]
const MultiColorSvgs = Object.keys(MultiColorSvgsList).map((name) => {
return {
name,
component: MultiColorSvgsList[name](),
// 3.19.0
tinyFlag3_19: tinyIconMulticolor.includes(name)
}
})
function click(name) {
const input = document.createElement('input')
input.value = name
document.body.appendChild(input)
input.select()
document.execCommand('Copy')
document.body.removeChild(input)
Modal.message({
message: `成功复制图标名称 ${name} `,
status: 'info'
})
}
</script>
<style scoped>
.svgs-wrapper {
display: flex;
flex-wrap: wrap;
padding-top: 20px;
}
.svgs-icon {
cursor: pointer;
transition: all 0.4s;
}
.svgs-icon:hover {
transform: scale(1.5, 1.5);
}
.svgs-item {
width: 260px;
text-align: center;
display: inline-block;
margin-bottom: 28px;
}
.svgs-text {
padding-top: 8px;
display: block;
font-size: 14px;
font-weight: 600;
}
</style>

View File

@ -0,0 +1,131 @@
<template>
<div>
<div class="svgs-wrapper">
<div v-for="(icon, index) in MultiColorSvgs" :key="index">
<div class="svgs-item">
<component
:is="icon.component"
class="svgs-icon"
style="width: 2em; fill: #000; height: 2em"
@click="click(icon.name)"
></component>
<span class="svgs-text">{{ icon.name }}</span>
</div>
</div>
</div>
</div>
</template>
<script>
import MultiColorSvgs from '@opentiny/vue-icon-multicolor'
import { Modal, Tabs, TabItem } from '@opentiny/vue'
const tinyIconMulticolor = [
'ColorIconActivitys',
'ColorIconAdministrativeFees',
'ColorIconAirFares',
'ColorIconApply',
'ColorIconArchives',
'ColorIconBaggageFees',
'ColorIconCarInsurance',
'ColorIconCarRental',
'ColorIconCeremonyFees',
'ColorIconConolences',
'ColorIconEntertainmentExpense',
'ColorIconExpertConsultationFees',
'ColorIconExpertTeachingFees',
'ColorIconExpressDelivery',
'ColorIconFerryFares',
'ColorIconFuelCost',
'ColorIconGiftCost',
'ColorIconHousingSubsidy',
'ColorIconIncidentalExpenses',
'ColorIconLandlinePhone',
'ColorIconLineRental',
'ColorIconLivingSubsidy',
'ColorIconLodgingFees',
'ColorIconMaintenanceService',
'ColorIconMealAllowance',
'ColorIconMealSubsidy',
'ColorIconMeetingExpenses',
'ColorIconNewspaperSubscription',
'ColorIconOfficeEquipments',
'ColorIconOfficeSupplies',
'ColorIconOthers',
'ColorIconPhoneBills',
'ColorIconPhysicalExamination',
'ColorIconPrivateVehicleAllowance',
'ColorIconServiceCharges',
'ColorIconTaxiFares',
'ColorIconTrainFares',
'ColorIconTrainingFees',
'ColorIconTravelExpenses',
'ColorIconVenueHospitalityFees',
'ColorIconVenueRentalFees',
'ColorIconVisaFees'
]
export default {
components: {
TinyTabs: Tabs,
TinyTabItem: TabItem
},
data() {
return {
MultiColorSvgs: Object.keys(MultiColorSvgs).map((name) => {
return {
name,
component: MultiColorSvgs[name](),
// 3.19.0
tinyFlag3_19: tinyIconMulticolor.includes(name)
}
})
}
},
methods: {
click(name) {
const input = document.createElement('input')
input.value = name
document.body.appendChild(input)
input.select()
document.execCommand('Copy')
document.body.removeChild(input)
Modal.message({
message: `成功复制图标名称 ${name} `,
status: 'info'
})
}
}
}
</script>
<style scoped>
.svgs-wrapper {
display: flex;
flex-wrap: wrap;
padding-top: 20px;
}
.svgs-icon {
cursor: pointer;
transition: all 0.4s;
}
.svgs-icon:hover {
transform: scale(1.5, 1.5);
}
.svgs-item {
width: 260px;
text-align: center;
display: inline-block;
margin-bottom: 28px;
}
.svgs-text {
padding-top: 8px;
display: block;
font-size: 14px;
font-weight: 600;
}
</style>

View File

@ -0,0 +1,7 @@
---
title: IconMulticolor 多色图标
---
# IconMulticolor 多色图标
<div>多色图标集合</div>

View File

@ -0,0 +1,7 @@
---
title: IconMulticolor
---
# IconMulticolor
<div>MultiColor icon collection</div>

View File

@ -0,0 +1,38 @@
export default {
column: '1',
owner: '',
demos: [
{
demoId: 'basic-usage',
name: {
'zh-CN': '基本用法',
'en-US': 'Basic Usage'
},
desc: {
'zh-CN': `通过 <code>first-color</code> 自定义图标第一层颜色,通过 <code>second-color</code> 自定义图标第二层颜色。
<div class="tip custom-block">
<p>图标颜色规则 共三层颜色其中一二层颜色可独立配置第三层颜色为第二层颜色透明度的50%</p>
<p>第一层默认颜色 rgba(0,103,209,1)</p>
<p>第二层默认颜色 rgba(0,103,209,0.7) 默认为第一层的70%</p>
<p>第三层默认颜色 rgba(0,103,209,0.35)第二层的50%</p>
</div>
`,
'en-US':
'Introduce icon functions from the <code>@opentiny/vue-icon</code> icon library, execute them, and generate corresponding icons.'
},
codeFiles: ['basic-usage.vue']
},
{
demoId: 'list',
name: {
'zh-CN': '图标集合',
'en-US': 'Icon Set'
},
desc: {
'zh-CN': '输入图标名称进行搜索,点击图标即可快速复制名称。',
'en-US': 'Enter the icon name for search, Click on the icon to quickly copy the name.'
},
codeFiles: ['list.vue']
}
]
}

View File

@ -69,6 +69,7 @@ export const iconGroups = {
'IconDeltaUpO',
'IconFreeze',
'IconUp',
'IconUpdate',
'IconUpO',
'IconUpWard'
],
@ -179,6 +180,7 @@ export const iconGroups = {
],
Stretchable: [
'IconFullscreenLeft',
'IconFullscreenRight',
'IconMinscreenLeft',
'IconMinscreenRight',
'IconStretch',
@ -247,12 +249,15 @@ export const iconGroups = {
Brands: ['IconAngularjs', 'IconEspaceAuto', 'IconEspace', 'IconNodejs', 'IconReactjs', 'IconVuejs'],
Charts: ['IconAreaChart', 'IconDotChart', 'IconLineChart', 'IconPieChart', 'IconStatistics'],
Editor: [
'IconEdit',
'IconEditor',
'IconEditorAlignCenter',
'IconEditorAlignLeft',
'IconEditorAlignRight',
'IconEditorBackground',
'IconEditorCode',
'IconEditorEraser',
'IconEditorEraserFilled',
'IconEditorLeftBorder',
'IconEditorList',
'IconEditorListDot',
@ -262,6 +267,7 @@ export const iconGroups = {
'IconEditorQuote',
'IconEditorRedo',
'IconEditorRightBorder',
'IconEditorTab',
'IconEditorTable',
'IconEditorTextcolor',
'IconExport',
@ -276,6 +282,7 @@ export const iconGroups = {
'IconDesktopView',
'IconException',
'IconLanguage',
'IconLock',
'IconMobileView',
'IconMobile',
'IconPrintPreview',
@ -294,10 +301,16 @@ export const iconGroups = {
Email: ['IconEmailAdd', 'IconEmailCircle', 'IconMailContent', 'IconMail', 'IconReplies', 'IconSent', 'IconUnsent'],
Folder: ['IconFileCloudupload', 'IconFolder', 'IconFolderClosed', 'IconFolderOpened'],
File: [
'IconAgency',
'IconCloudUpload',
'iconCheckOut',
'IconCheckedTrue',
'IconDeletePage',
'IconDocument',
'IconExcel',
'IconExcelType',
'IconExpressSearch',
'IconFeedback',
'IconFileExcel',
'IconFile',
'IconFilesCircle',
@ -307,9 +320,14 @@ export const iconGroups = {
'IconFileupload',
'IconFinishO',
'IconHistoryRecord',
'IconLocalePanel',
'IconNoPremission',
'IconOtherType',
'IconPagelink',
'IconPdfType',
'IconPptType',
'IconRenew',
'IconSynchronize',
'IconTextType',
'IconText',
'IconTextAlign',

View File

@ -3,7 +3,7 @@
<div>点击图片预览大图</div>
<br />
<div class="demo-image__preview">
<tiny-image :src="url" :preview-src-list="srcList" :z-index="3000" show-index></tiny-image>
<tiny-image :src="url" :preview-src-list="srcList" :z-index="3000" show-index :appendToBody="false"></tiny-image>
</div>
</div>
</template>

View File

@ -3,7 +3,7 @@
<div>点击图片预览大图</div>
<br />
<div class="demo-image__preview">
<tiny-image :src="url" :preview-src-list="srcList" :z-index="3000" show-index></tiny-image>
<tiny-image :src="url" :preview-src-list="srcList" :z-index="3000" show-index :appendToBody="false"></tiny-image>
</div>
</div>
</template>

View File

@ -1,12 +1,16 @@
<template>
<div>
<tiny-link>默认链接</tiny-link>
<tiny-link @click="handleClick">默认链接</tiny-link>
<tiny-link value="默认链接2"></tiny-link>
</div>
</template>
<script setup>
import { Link as TinyLink } from '@opentiny/vue'
function handleClick() {
console.log('clicked')
}
</script>
<style scoped>

View File

@ -10,4 +10,15 @@ test('基础用法', async ({ page }) => {
await expect(link.nth(1)).toHaveText('默认链接2')
await link.first().hover()
await expect(link.first()).toHaveCSS('color', 'rgb(20, 118, 255)')
// 测试点击
const values = [] as string[]
page.on('console', async (msg) => {
for (const arg of msg.args()) {
values.push(await arg.jsonValue())
}
})
await link.first().click()
expect(values[0]).toBe('clicked')
})

View File

@ -1,6 +1,6 @@
<template>
<div>
<tiny-link>默认链接</tiny-link>
<tiny-link @click="handleClick">默认链接</tiny-link>
<tiny-link value="默认链接2"></tiny-link>
</div>
</template>
@ -11,6 +11,11 @@ import { Link } from '@opentiny/vue'
export default {
components: {
TinyLink: Link
},
methods: {
handleClick() {
console.log('clicked')
}
}
}
</script>

View File

@ -12,7 +12,7 @@
>
<tiny-link :icon="IconEdit">编辑</tiny-link>
<tiny-link :icon="IconEdit">禁用</tiny-link>
<tiny-link>查看<tiny-icon-view class="tiny-svg-size"></tiny-icon-view> </tiny-link>
<tiny-link>查看<tiny-icon-search class="tiny-svg-size"></tiny-icon-search> </tiny-link>
<tiny-link>
<template #icon> <tiny-icon-del class="tiny-svg-size"></tiny-icon-del> </template></tiny-link
>
@ -21,10 +21,10 @@
<script setup>
import { TinyLink } from '@opentiny/vue'
import { IconEditor, iconView, IconDeleteL, iconFilletExternalLink } from '@opentiny/vue-icon'
import { IconEditor, iconSearch, IconDeleteL, iconFilletExternalLink } from '@opentiny/vue-icon'
const IconEdit = IconEditor()
const TinyIconView = iconView()
const TinyIconSearch = iconSearch()
const TinyIconDel = IconDeleteL()
const TinyIconFilletExternalLink = iconFilletExternalLink()
</script>

View File

@ -10,7 +10,7 @@
>
<tiny-link :icon="IconEdit">编辑</tiny-link>
<tiny-link :icon="IconEdit">禁用</tiny-link>
<tiny-link>查看<icon-view class="tiny-svg-size"></icon-view> </tiny-link>
<tiny-link>查看<icon-search class="tiny-svg-size"></icon-search> </tiny-link>
<tiny-link>
<template #icon> <icon-del class="tiny-svg-size"></icon-del> </template></tiny-link
>
@ -19,12 +19,12 @@
<script>
import { Link } from '@opentiny/vue'
import { IconEditor, IconView, IconDeleteL, IconFilletExternalLink } from '@opentiny/vue-icon'
import { IconEditor, IconSearch, IconDeleteL, IconFilletExternalLink } from '@opentiny/vue-icon'
export default {
components: {
TinyLink: Link,
IconView: IconView(),
IconSearch: IconSearch(),
IconDel: IconDeleteL(),
IconFilletExternalLink: IconFilletExternalLink()
},

View File

@ -9,8 +9,14 @@ export default {
'en-US': 'Basic Usage'
},
desc: {
'zh-CN': '<p>通过 <code>value</code> 或者默认插槽设置链接显示内容。</p>',
'en-US': '<p>Set the link to display content via <code>value</code> or the default slot. </p></p>'
'zh-CN': `
通过 <code>value</code> <br>
绑定 <code>click</code> <code>href</code> <code>click</code>
`,
'en-US': `
Set the link to display content via <code>value</code> or the default slot.
Bind the click event to listen for clicks.The click event is not triggered when the href attribute is disabled or configured!
`
},
codeFiles: ['basic-usage.vue']
},

View File

@ -0,0 +1,17 @@
<template>
<div class="content">
<tiny-button @click="visible = !visible" :reset-time="0">自定义底部</tiny-button>
<tiny-modal v-model="visible" footer-dragable show-footer>
<template #footer>
<tiny-button>自定义底部信息</tiny-button>
</template>
</tiny-modal>
</div>
</template>
<script setup>
import { ref } from 'vue'
import { Button as TinyButton, Modal as TinyModal } from '@opentiny/vue'
const visible = ref(false)
</script>

View File

@ -0,0 +1,26 @@
<template>
<div class="content">
<tiny-button @click="visible = !visible" :reset-time="0">自定义底部</tiny-button>
<tiny-modal v-model="visible" footer-dragable show-footer>
<template #footer>
<tiny-button>自定义底部信息</tiny-button>
</template>
</tiny-modal>
</div>
</template>
<script>
import { Button, Modal } from '@opentiny/vue'
export default {
components: {
TinyButton: Button,
TinyModal: Modal
},
data() {
return {
visible: false
}
}
}
</script>

View File

@ -5,14 +5,14 @@
<script setup>
import { ref, reactive } from 'vue'
import { TimeLine as TinyTimeLine } from '@opentiny/vue'
import { iconCheckOut, iconCalendar, iconLoading, iconEnd } from '@opentiny/vue-icon'
import { iconLocalePanel, iconFeedback, iconSynchronize, iconAgency } from '@opentiny/vue-icon'
const active = ref(1)
const data = reactive([
{ name: '立项', time: '2022-11-12 10:00', autoColor: iconCheckOut() },
{ name: '开发', time: '2022-11-15 20:00', autoColor: iconCalendar() },
{ name: '交付', time: '2022-12-10 20:00', autoColor: iconLoading() },
{ name: '结项', time: '2022-12-15 00:00', autoColor: iconEnd() }
{ name: '立项', time: '2022-11-12 10:00', autoColor: iconLocalePanel() },
{ name: '开发', time: '2022-11-15 20:00', autoColor: iconFeedback() },
{ name: '交付', time: '2022-12-10 20:00', autoColor: iconSynchronize() },
{ name: '结项', time: '2022-12-15 00:00', autoColor: iconAgency() }
])
const onClick = (index) => {

View File

@ -4,7 +4,7 @@
<script>
import { TimeLine, Modal } from '@opentiny/vue'
import { iconCheckOut, iconCalendar, iconLoading, iconEnd } from '@opentiny/vue-icon'
import { iconLocalePanel, iconFeedback, iconSynchronize, iconAgency } from '@opentiny/vue-icon'
export default {
components: {
@ -14,10 +14,10 @@ export default {
return {
active: 2,
data: [
{ name: '立项', time: '2022-11-12 10:00', autoColor: iconCheckOut() },
{ name: '开发', time: '2022-11-15 20:00', autoColor: iconCalendar() },
{ name: '交付', time: '2022-12-10 20:00', autoColor: iconLoading() },
{ name: '结项', time: '2022-12-15 00:00', autoColor: iconEnd() }
{ name: '立项', time: '2022-11-12 10:00', autoColor: iconLocalePanel() },
{ name: '开发', time: '2022-11-15 20:00', autoColor: iconFeedback() },
{ name: '交付', time: '2022-12-10 20:00', autoColor: iconSynchronize() },
{ name: '结项', time: '2022-12-15 00:00', autoColor: iconAgency() }
]
}
},

View File

@ -21,14 +21,14 @@
<script setup lang="ts">
import { reactive } from 'vue'
import { TimeLine as TinyTimeLine } from '@opentiny/vue'
import { IconTime } from '@opentiny/vue-icon'
import { iconUpdate } from '@opentiny/vue-icon'
const data1 = reactive([
{ name: '默认状态' },
{ name: '成功状态', autoColor: 'success' },
{ name: '警告状态', autoColor: 'warning' },
{ name: '异常状态', error: true }, // 使 autoColor: 'error'
{ name: '定义图标', autoColor: IconTime() }, //
{ name: '定义图标', autoColor: iconUpdate() }, //
{ name: '禁用状态', disabled: true }
])
const data2 = reactive([

View File

@ -20,7 +20,7 @@
<script lang="ts">
import { TimeLine } from '@opentiny/vue'
import { IconTime } from '@opentiny/vue-icon'
import { iconUpdate } from '@opentiny/vue-icon'
export default {
components: {
@ -33,7 +33,7 @@ export default {
{ name: '成功状态', autoColor: 'success' },
{ name: '警告状态', autoColor: 'warning' },
{ name: '异常状态', error: true }, // 使 autoColor: 'error'
{ name: '定义图标', autoColor: IconTime() }, //
{ name: '定义图标', autoColor: iconUpdate() }, //
{ name: '禁用状态', disabled: true }
],
data2: [

View File

@ -359,6 +359,19 @@ export default {
'Indicate whether to allow the search box clear button to be displayed by setting the<code>clearable</code>property'
},
codeFiles: ['clearable.vue']
},
{
demoId: 'width-adapt',
name: {
'zh-CN': '宽度自适应',
'en-US': 'Can the search box be cleared'
},
desc: {
'zh-CN': '通过 <code> widthAdapt </code> 属性,是否让组件宽度自适应父容器。默认为 <code> false </code>',
'en-US':
'The <code>widthAdapt </code> attribute specifies whether to enable the component width to adapt to the parent container.'
},
codeFiles: ['width-adapt.vue']
}
]
}

View File

@ -0,0 +1,192 @@
<template>
<tiny-tree-menu :data="data" widthAdapt />
</template>
<script setup>
import { TinyTreeMenu } from '@opentiny/vue'
const data = [
{
id: 100,
label: '组件总览'
},
{
id: 200,
label: '使用指南',
children: [
{
id: 201,
label: '更新日志'
},
{ id: 202, label: '环境准备' },
{ id: 203, label: '安装' },
{
id: 204,
label: '引入组件',
children: [
{ id: 20401, label: '按需引入' },
{ id: 20402, label: '完整引入' }
]
},
{ id: 205, label: '开发示例' },
{ id: 206, label: '国际化' },
{ id: 207, label: '主题配置' },
{ id: 208, label: '表单校验配置' },
{ id: 209, label: '常见问题' }
]
},
{
id: 300,
label: '框架风格',
children: [
{
id: 301,
label: 'Color 色彩'
},
{ id: 302, label: 'Container 版型' },
{ id: 303, label: 'Font 字体' },
{ id: 304, label: 'Icon 图标' },
{ id: 305, label: 'Layout 布局' }
]
},
{
id: 400,
label: '导航组件',
children: [
{
id: 401,
label: 'Anchor 锚点'
},
{ id: 402, label: 'Guide 引导' },
{ id: 403, label: 'Breadcrumb 面包屑' }
]
},
{
id: 500,
label: '容器组件',
children: [
{
id: 501,
label: 'Carousel 走马灯'
},
{ id: 502, label: 'Collapse 折叠面板' },
{ id: 503, label: 'DialogBox 对话框' }
]
},
{
id: 600,
label: '表单组件',
children: [
{
id: 60101,
label: 'Button 按钮',
url: 'button'
},
{
id: 60102,
label: 'DatePicker 日期选择器',
url: 'date-picker'
},
{
id: 60103,
label: 'Select 选择器',
url: 'select'
},
{
id: 60104,
label: 'DropTimes 下拉时间',
url: 'drop-times'
},
{
id: 60105,
label: 'Input 输入框',
url: 'input'
}
]
},
{
id: 700,
label: '业务组件',
children: [
{
id: 701,
label: 'Amount 金额'
},
{ id: 702, label: 'Area 片区' },
{ id: 703, label: 'Company 公司' }
]
},
{
id: 800,
label: '其他组件',
children: [
{
id: 801,
label: '废弃组件',
children: [
{
id: 80101,
label: 'CreditCardForm 信用卡表单',
url: 'credit-card-form'
},
{
id: 80102,
label: 'DetailPage 表头详情栏',
url: 'detail-page'
}
]
},
{
id: 802,
label: '新增组件',
children: [
{
id: 80201,
label: 'QrCode 二维码',
url: 'qr-code'
},
{
id: 80202,
label: 'Watermark 水印',
url: 'watermark'
},
{
id: 80203,
label: 'MindMap 脑图',
url: 'mind-map'
},
{
id: 80204,
label: 'Skeleton 骨架屏',
url: 'skeleton'
}
]
},
{
id: 803,
label: 'BulletinBoard 公告牌'
},
{ id: 804, label: 'Calendar 日历' }
]
}
]
</script>
<!-- <template>
<tiny-tree-menu ></tiny-tree-menu>
</template>
<script>
export default {
components: {
TinyTreeMenu: TreeMenu
},
data() {
return {
treeData:
}
}
}
</script> -->

View File

@ -0,0 +1,13 @@
import type { Page } from '@playwright/test'
import { test, expect } from '@playwright/test'
const getIcon = (page: Page) => page.locator('#clearable').getByRole('img').nth(1)
test('宽度自适应', async ({ page }) => {
page.on('pageerror', (exception) => expect(exception).toBeNull())
await page.goto('tree-menu#width-adapt')
const wrap = page.locator('#width-adapt')
const treeMenu = wrap.locator('.tiny-tree-menu')
await expect(treeMenu).toHaveAttribute('style', 'width: 100%;')
})

View File

@ -0,0 +1,182 @@
<template>
<tiny-tree-menu :data="treeData" widthAdapt></tiny-tree-menu>
</template>
<script>
import { TinyTreeMenu } from '@opentiny/vue'
export default {
components: {
TinyTreeMenu
},
data() {
return {
treeData: [
{
id: 100,
label: '组件总览'
},
{
id: 200,
label: '使用指南',
children: [
{
id: 201,
label: '更新日志'
},
{ id: 202, label: '环境准备' },
{ id: 203, label: '安装' },
{
id: 204,
label: '引入组件',
children: [
{ id: 20401, label: '按需引入' },
{ id: 20402, label: '完整引入' }
]
},
{ id: 205, label: '开发示例' },
{ id: 206, label: '国际化' },
{ id: 207, label: '主题配置' },
{ id: 208, label: '表单校验配置' },
{ id: 209, label: '常见问题' }
]
},
{
id: 300,
label: '框架风格',
children: [
{
id: 301,
label: 'Color 色彩'
},
{ id: 302, label: 'Container 版型' },
{ id: 303, label: 'Font 字体' },
{ id: 304, label: 'Icon 图标' },
{ id: 305, label: 'Layout 布局' }
]
},
{
id: 400,
label: '导航组件',
children: [
{
id: 401,
label: 'Anchor 锚点'
},
{ id: 402, label: 'Guide 引导' },
{ id: 403, label: 'Breadcrumb 面包屑' }
]
},
{
id: 500,
label: '容器组件',
children: [
{
id: 501,
label: 'Carousel 走马灯'
},
{ id: 502, label: 'Collapse 折叠面板' },
{ id: 503, label: 'DialogBox 对话框' }
]
},
{
id: 600,
label: '表单组件',
children: [
{
id: 60101,
label: 'Button 按钮',
url: 'button'
},
{
id: 60102,
label: 'DatePicker 日期选择器',
url: 'date-picker'
},
{
id: 60103,
label: 'Select 选择器',
url: 'select'
},
{
id: 60104,
label: 'DropTimes 下拉时间',
url: 'drop-times'
},
{
id: 60105,
label: 'Input 输入框',
url: 'input'
}
]
},
{
id: 700,
label: '业务组件',
children: [
{
id: 701,
label: 'Amount 金额'
},
{ id: 702, label: 'Area 片区' },
{ id: 703, label: 'Company 公司' }
]
},
{
id: 800,
label: '其他组件',
children: [
{
id: 801,
label: '废弃组件',
children: [
{
id: 80101,
label: 'CreditCardForm 信用卡表单',
url: 'credit-card-form'
},
{
id: 80102,
label: 'DetailPage 表头详情栏',
url: 'detail-page'
}
]
},
{
id: 802,
label: '新增组件',
children: [
{
id: 80201,
label: 'QrCode 二维码',
url: 'qr-code'
},
{
id: 80202,
label: 'Watermark 水印',
url: 'watermark'
},
{
id: 80203,
label: 'MindMap 脑图',
url: 'mind-map'
},
{
id: 80204,
label: 'Skeleton 骨架屏',
url: 'skeleton'
}
]
},
{
id: 803,
label: 'BulletinBoard 公告牌'
},
{ id: 804, label: 'Calendar 日历' }
]
}
]
}
}
}
</script>

View File

@ -82,6 +82,7 @@ export const cmpMenus = [
{ 'nameCn': '按钮组', 'name': 'ButtonGroup', 'key': 'button-group' },
{ 'nameCn': '容器布局', 'name': 'Container', 'key': 'container' },
{ 'nameCn': '图标', 'name': 'Icon', 'key': 'icon' },
// { 'nameCn': '多色图标', 'name': 'IconMulticolor', 'key': 'icon-multicolor' }, // 隐藏路由目前只有saas使用
{ 'nameCn': '栅格布局', 'name': 'Layout', 'key': 'layout' },
{ 'nameCn': '链接', 'name': 'Link', 'key': 'link' },
{ 'nameCn': '分割线', 'name': 'Divider', 'key': 'divider' },

View File

@ -1,5 +1,104 @@
# 更新日志
## v2.18.0/v3.18.0
`2024/08/20`
## What's Changed
### Exciting New Features 🎉
- feat(tree-select): [tree-select] add tree-select component by @kagol in https://github.com/opentiny/tiny-vue/pull/1683
- feat: support solidjs (#1566) by @zzcr in https://github.com/opentiny/tiny-vue/pull/1682
- feat(tree-menu)[tree-menu]: clearable by @GaoNeng-wWw in https://github.com/opentiny/tiny-vue/pull/1672
- feat(tabs): [tabs] Add new specification function by @chenxi-20 in https://github.com/opentiny/tiny-vue/pull/1762
- feat(search): [search] add disabled functionality to the search component and adapt to new specifications by @chenxi-20 in https://github.com/opentiny/tiny-vue/pull/1756
- feat(fluent-editor): add mobile-first template by @kagol in https://github.com/opentiny/tiny-vue/pull/1763
- feat(Switch): [switch] suppor custom open and close icon. by @AcWrong02 in https://github.com/opentiny/tiny-vue/pull/1551
- feat(runtime): add directive runtime by @zzcr in https://github.com/opentiny/tiny-vue/pull/1784
- fix(warning): fix all warning , fix dialog-box's visible ,default false by @shenjunjian in https://github.com/opentiny/tiny-vue/pull/1792
- feat(fluent-editor): optimize fluent-editor mobile-first by @kagol in https://github.com/opentiny/tiny-vue/pull/1794
- feat(file-upload): [file-upload]刷新上传组件新规范 by @chenxi-20 in https://github.com/opentiny/tiny-vue/pull/1811
- feat(pager): [pager] add new props total-fixed-left by @gimmyhehe in https://github.com/opentiny/tiny-vue/pull/1819
- develop split for smb-design theme by @shenjunjian in https://github.com/opentiny/tiny-vue/pull/1830
- feat(fall-menu): [fall-menu]modify smb-theme by @James-9696 in https://github.com/opentiny/tiny-vue/pull/1842
- feat(bulletin-board): [bulletin-board] updata bulletin-board xdesign by @wuyiping0628 in https://github.com/opentiny/tiny-vue/pull/1844
- feat(link-menu): [link-menu]modify smb-theme by @James-9696 in https://github.com/opentiny/tiny-vue/pull/1846
- feat(nav-menu): [nav-menu] updata nav-menu xdesign by @wuyiping0628 in https://github.com/opentiny/tiny-vue/pull/1849
- feat(pop-upload): [pop-upload] 刷新popupload规范增加uploadTip插槽 by @chenxi-20 in https://github.com/opentiny/tiny-vue/pull/1850
- feat(pop-upload): [pop-upload] 刷新popupload规范表格头部优化增加上传数据统计能力,修复长度限制bug by @chenxi-20 in https://github.com/opentiny/tiny-vue/pull/1852
- feat(toggle-menu): [toggle-menu] add smb theme by @James-9696 in https://github.com/opentiny/tiny-vue/pull/1861
- feat(color-select-panel): [color-select-panel]modify smb-theme by @James-9696 in https://github.com/opentiny/tiny-vue/pull/1837
- fix(button): [button] add ts declaration for button , and remove hook-updated … by @shenjunjian in https://github.com/opentiny/tiny-vue/pull/1853
- fix (anchor): [anchor] Fix the issue that the scrolling response lags after the anchor is clicked. Add a tooltip to adapt to the SaaS theme. by @chenxi-20 in https://github.com/opentiny/tiny-vue/pull/1892
### Bug Fixes 🐛
- fix(unplugin-virtual-template): fix build internals error in node v18.19.1 by @gweesin in https://github.com/opentiny/tiny-vue/pull/1676
- fix(vue-renderless): [radio] fix handleKeydown blocking default events and bubble logic by @Nowitzki41 in https://github.com/opentiny/tiny-vue/pull/1650
- fix: fix pnpm site error by @kagol in https://github.com/opentiny/tiny-vue/pull/1702
- chore(fluent-editor): update package.json by @kagol in https://github.com/opentiny/tiny-vue/pull/1721
- fix(docs): fix components number by @zzcr in https://github.com/opentiny/tiny-vue/pull/1754
- fix(tree-menu): [tree-menu] resolve the issue of disabled treemenu components not taking effect by @wuyiping0628 in https://github.com/opentiny/tiny-vue/pull/1736
- fix(auto-tip): [auto-tip] Fix the issue where the placement configuration always has old values by @MomoPoppy in https://github.com/opentiny/tiny-vue/pull/1774
- fix(rich-text-editor): [rich-text-editor] fix data binding doen't work by @gweesin in https://github.com/opentiny/tiny-vue/pull/1779
- fix(playground): could not open playground as Composition mode by @gweesin in https://github.com/opentiny/tiny-vue/pull/1787
- fix(picker): fix mobile breakpoint cannot use pc datepicker and timep… by @gweesin in https://github.com/opentiny/tiny-vue/pull/1678
- fix(fluent-editor): fix toolbar icon and undo/redo by @kagol in https://github.com/opentiny/tiny-vue/pull/1786
- fix: fix layout asider layer error on mobile mode by @gweesin in https://github.com/opentiny/tiny-vue/pull/1778
- fix(color-picker): [color-picker,color-select-panel] fix issue 1684 by @GaoNeng-wWw in https://github.com/opentiny/tiny-vue/pull/1686
- fix: fix Vue packages version mismatch by @kagol in https://github.com/opentiny/tiny-vue/pull/1791
- fix(fluent-editor): fix better-table module by @kagol in https://github.com/opentiny/tiny-vue/pull/1788
- fix(fluent-editor): fix image module and optimize toolbar style by @kagol in https://github.com/opentiny/tiny-vue/pull/1799
- fix(form): [form] fix text validation style error in other size form … by @gimmyhehe in https://github.com/opentiny/tiny-vue/pull/1798
- fix(tree-menu): [tree-menu] Delete the prefix-icon attribute of the tree-menu component by @wuyiping0628 in https://github.com/opentiny/tiny-vue/pull/1789
- fix(grid): fix grid click menu item jump to blank tab in playground c… by @gimmyhehe in https://github.com/opentiny/tiny-vue/pull/1802
- fix(fluent-editor): fix error when execute pnpm site by @kagol in https://github.com/opentiny/tiny-vue/pull/1815
- fix(fluent-editor): fix fluent-editor saas theme by @kagol in https://github.com/opentiny/tiny-vue/pull/1814
- fix(form): [form] fix content not aligned when display only close #1698 by @gimmyhehe in https://github.com/opentiny/tiny-vue/pull/1805
- fix(warning): fix unocss version conflicts by @gweesin in https://github.com/opentiny/tiny-vue/pull/1825
- fix(playground): fix old version runtime not found close #1817 by @gimmyhehe in https://github.com/opentiny/tiny-vue/pull/1818
- fix(fluent-editor): fix style error by @kagol in https://github.com/opentiny/tiny-vue/pull/1829
- fix(fluent-editor): fix style missing by @kagol in https://github.com/opentiny/tiny-vue/pull/1831
- fix(fluent-editor): fix console warn by @kagol in https://github.com/opentiny/tiny-vue/pull/1833
- fix(select): [select] Adapt to multiple+disabled+displayOnly scenarios with different themes by @MomoPoppy in https://github.com/opentiny/tiny-vue/pull/1835
- fix(fluent-editor): fix tasklist format by @kagol in https://github.com/opentiny/tiny-vue/pull/1845
- fix(base-select): [base-select] fix check all style by @kagol in https://github.com/opentiny/tiny-vue/pull/1848
- fix(form): [form] fix dynamic change size fail in prod mode by @gimmyhehe in https://github.com/opentiny/tiny-vue/pull/1857
- fix(theme): [anchor] Fixed the theme switch bug and the anchor line color under the default theme. by @chenxi-20 in https://github.com/opentiny/tiny-vue/pull/1854
- fix(pop-confirm): [pop-confirm] remove m funtion from pc template by @shenjunjian in https://github.com/opentiny/tiny-vue/pull/1863
- fix(build): fix some bugs when build components by @zzcr in https://github.com/opentiny/tiny-vue/pull/1873
- fix(theme): Fixed the issue that multiple root files are generated when the theme is packaged. by @chenxi-20 in https://github.com/opentiny/tiny-vue/pull/1893
### Other Changes
- chore(base-select): [base-select] add mark and metaData by @kagol in https://github.com/opentiny/tiny-vue/pull/1681
- chore: update workflow node-version to 20 by @kagol in https://github.com/opentiny/tiny-vue/pull/1742
- docs(changelog): update changelog and runtime doc by @zzcr in https://github.com/opentiny/tiny-vue/pull/1749
- feat: update site design style by @zzcr in https://github.com/opentiny/tiny-vue/pull/1752
- docs(sites): fix docs typo by @gimmyhehe in https://github.com/opentiny/tiny-vue/pull/1758
- docs(tree-select): [tree-select] optimize demo/api docs by @kagol in https://github.com/opentiny/tiny-vue/pull/1743
- docs(fluent-editor): optimize demo/api docs by @kagol in https://github.com/opentiny/tiny-vue/pull/1757
- docs(grid): add grid-column props docs by @gimmyhehe in https://github.com/opentiny/tiny-vue/pull/1782
- docs(dialog-box): [dialog-box] update document by @James-9696 in https://github.com/opentiny/tiny-vue/pull/1732
- docs(numeric): [numeric]optimized docs of numeric component by @James-9696 in https://github.com/opentiny/tiny-vue/pull/1753
- docs(button-group): add new slot api version by @gimmyhehe in https://github.com/opentiny/tiny-vue/pull/1797
- docs(fluent-editor): optimize fluent-editor mobile-first docs by @kagol in https://github.com/opentiny/tiny-vue/pull/1804
- fix(numeric): modify docs by @James-9696 in https://github.com/opentiny/tiny-vue/pull/1803
- feat: update vue-docs by @zzcr in https://github.com/opentiny/tiny-vue/pull/1810
- docs(fluent-editor): optimize fluent-editor pc docs by @kagol in https://github.com/opentiny/tiny-vue/pull/1807
- docs(theme): add custom cssvar variable prefix documentation by @zzcr in https://github.com/opentiny/tiny-vue/pull/1806
- feat(link): add links typescript and docs by @shenjunjian in https://github.com/opentiny/tiny-vue/pull/1816
- feat(readme): add readme files to main packages by @zzcr in https://github.com/opentiny/tiny-vue/pull/1826
- docs(fluent-editor): add fluent-editor docs by @kagol in https://github.com/opentiny/tiny-vue/pull/1834
- docs(fluent-editor): optimize mobile-first demo by @kagol in https://github.com/opentiny/tiny-vue/pull/1836
- ci: add automate script to transform demos to add "Tiny" prefix by @gimmyhehe in https://github.com/opentiny/tiny-vue/pull/1832
## New Contributors
- @Nowitzki41 made their first contribution in https://github.com/opentiny/tiny-vue/pull/1650
- @Simon-He95 made their first contribution in https://github.com/opentiny/tiny-vue/pull/1839
## v2.17.0/v3.17.0
`2024/07/17`

View File

@ -1,6 +1,6 @@
{
"name": "@opentiny/vue-docs",
"version": "3.18.4",
"version": "3.18.5",
"license": "MIT",
"scripts": {
"start": "vite",
@ -29,6 +29,7 @@
"@opentiny/vue-hooks": "workspace:~",
"@opentiny/vue-icon": "workspace:~",
"@opentiny/vue-icon-saas": "workspace:~",
"@opentiny/vue-icon-multicolor": "workspace:~",
"@opentiny/vue-repl": "^1.1.2",
"@opentiny/vue-theme": "workspace:~",
"@opentiny/vue-theme-mobile": "workspace:~",

View File

@ -72,9 +72,8 @@ const createImportMap = (version) => {
'sortablejs': `${cdnHost}/sortablejs${versionDelimiter}1.15.0/${fileDelimiter}modular/sortable.esm.js`
}
if (['aurora', 'saas'].includes(tinyTheme)) {
imports[
`@opentiny/vue-design-${tinyTheme}`
] = `${cdnHost}/@opentiny/vue-design-${tinyTheme}${versionDelimiter}${version}/${fileDelimiter}index.js`
imports[`@opentiny/vue-design-${tinyTheme}`] =
`${cdnHost}/@opentiny/vue-design-${tinyTheme}${versionDelimiter}${version}/${fileDelimiter}index.js`
}
if (isSaas) {
imports['@opentiny/vue-icon'] = `${getRuntime(version)}tiny-vue-icon-saas.mjs`

Binary file not shown.

After

Width:  |  Height:  |  Size: 75 KiB

View File

@ -694,12 +694,11 @@ export default defineComponent({
router.push(data.link)
} else if (apiModeState.demoMode === 'default' && data.link.startsWith('#')) {
e.preventDefault()
// singleDemo
e.preventDefault()
const hash = data.link.slice(1)
state.currDemoId = hash
state.singleDemo = state.currJson.demos.find((d) => d.demoId === hash)
router.push(data.link)
scrollByHash(hash)
}

View File

@ -20,6 +20,7 @@
"@opentiny/vue": "workspace:~",
"@opentiny/vue-common": "workspace:~",
"@opentiny/vue-icon": "workspace:~",
"@opentiny/vue-icon-multicolor": "workspace:~",
"@opentiny/vue-locale": "workspace:~",
"@opentiny/vue-renderless": "workspace:~",
"@opentiny/vue-theme": "workspace:~",
@ -56,4 +57,4 @@
"@unocss/preset-icons": "^0.61.9",
"@unocss/transformer-directives": "^0.48.0"
}
}
}

View File

@ -20,6 +20,7 @@
"@opentiny/vue": "workspace:~",
"@opentiny/vue-common": "workspace:~",
"@opentiny/vue-icon": "workspace:~",
"@opentiny/vue-icon-multicolor": "workspace:~",
"@opentiny/vue-locale": "workspace:~",
"@opentiny/vue-renderless": "workspace:~",
"@opentiny/vue-theme": "workspace:~",

View File

@ -23,6 +23,7 @@
"@opentiny/vue-common": "workspace:~",
"@opentiny/vue-design-aurora": "workspace:~",
"@opentiny/vue-icon": "workspace:~",
"@opentiny/vue-icon-multicolor": "workspace:~",
"@opentiny/vue-locale": "workspace:~",
"@opentiny/vue-renderless": "workspace:~",
"@opentiny/vue-theme": "workspace:~",

View File

@ -38,6 +38,7 @@ async function batchBuildAll({ vueVersion, tasks, message, emptyOutDir, npmScope
'@opentiny/vue-locale': 'TinyVueLocale',
'@opentiny/vue-common': 'TinyVueCommon',
'@opentiny/vue-icon': 'TinyVueIcon',
'@opentiny/vue-icon-multicolor': 'TinyVueIconMulticolor',
'echarts': 'Echarts'
}
}
@ -192,6 +193,10 @@ function getEntryTasks() {
path: 'vue-icon/index.ts',
libPath: 'tiny-vue-icon'
},
{
path: 'vue-icon-multicolor/index.ts',
libPath: 'tiny-vue-icon-multicolor'
},
{
path: 'vue-directive/index.ts',
libPath: 'tiny-vue-directive'

View File

@ -200,7 +200,15 @@ export const getBaseConfig = ({ vueVersion, dtsInclude, dts, buildTarget, isRunt
dependencies['@vue/composition-api'] = '1.7.2'
}
const matchList = ['vue-icon', 'vue-icon-saas', 'vue', 'design/aurora', 'design/saas', 'vue-directive']
const matchList = [
'vue-icon',
'vue-icon-saas',
'vue-icon-multicolor',
'vue',
'design/aurora',
'design/saas',
'vue-directive'
]
// 如果是主入口、svg图标或者主题规范包则直接指向相同路径
if (matchList.includes(filePath)) {
@ -320,7 +328,7 @@ async function batchBuildAll({ vueVersion, tasks, formats, message, emptyOutDir,
if (source.includes('vue-design-') || source.includes('vue-icon') || source.includes('vue-common')) {
return false
}
} else if (/vue-icon(-saas)?\/index/.test(importer)) {
} else if (/vue-icon(-saas|-multicolor)?\/index/.test(importer)) {
// 图标入口排除子图标
return /^\.\//.test(source)
}
@ -331,7 +339,7 @@ async function batchBuildAll({ vueVersion, tasks, formats, message, emptyOutDir,
}
// 子图标排除周边引用, 这里注意不要排除svg图标
if (/vue-icon(-saas)?\/.+\/index/.test(importer)) {
if (/vue-icon(-saas|-multicolor)?\/.+\/index/.test(importer)) {
return !/\.svg/.test(source)
}
@ -432,6 +440,7 @@ export async function buildUi(
// 如果指定了打包icon或者没有传入任何组件
if (names.some((name) => name.includes('icon')) || !names.length) {
tasks.push(...getByName({ name: kebabCase({ str: 'icon-saas' }), isSort: false }))
tasks.push(...getByName({ name: kebabCase({ str: 'icon-multicolor' }), isSort: false }))
tasks.push(...getAllIcons())
}

View File

@ -14,6 +14,11 @@
"type": "module",
"exclude": false
},
"IconMulticolor": {
"path": "vue-icon-multicolor/index.ts",
"type": "module",
"exclude": false
},
"Common": {
"path": "vue-common/src/index.ts",
"type": "module",

View File

@ -38,6 +38,8 @@ const findAllpage = (packagesPath) => {
.replace(/-openaui/g, '-opentiny')
// 解决在linkjs环境z-index无法统一导致下拉框被遮挡问题
.replace(/"(.*?\/popup-manager)"/g, '"@aurora/renderless/common/deps/popup-manager"')
// 修复使用@aurora/utils配置xss白名单失效问题
.replace(/"(.*?\/xss)"/g, '"@aurora/utils"')
// @opentiny/fluent-editor 包是与框架无关的包
.replace(/@aurora\/fluent-editor/g, '@opentiny/fluent-editor')

View File

@ -21,6 +21,7 @@ const getAlias = (vueVersion: string | number, theme = '', design) => {
'@opentiny/vue-icon-saas$': pathFromWorkspaceRoot('packages/vue-icon-saas/index.ts'),
'@opentiny/vue-icon-saas': pathFromWorkspaceRoot('packages/vue-icon-saas/src'),
'@opentiny/vue-icon$': pathFromWorkspaceRoot(`packages/vue-icon${ns(design || theme)}/index.ts`),
'@opentiny/vue-icon-multicolor$': pathFromWorkspaceRoot(`packages/vue-icon-multicolor${ns(theme)}/index.ts`),
'@opentiny/vue-renderless': pathFromWorkspaceRoot('packages/renderless/src'),
'@opentiny/vue-theme-mobile': pathFromWorkspaceRoot('packages/theme-mobile/src'),
'@opentiny/vue-theme': pathFromWorkspaceRoot(`packages/theme${ns(design || theme)}/src`),

View File

@ -147,6 +147,7 @@ const getSortModules = ({ filterIntercept, isSort = true }: { filterIntercept: F
.replace('vue-common/src/', 'packages/common/')
.replace('vue-locale/src/', 'packages/locale/')
.replace('vue-icon/src/', 'packages/icon/')
.replace('vue-icon-multicolor/src/', 'packages/icon-multicolor/')
.replace('/index.ts', '/src/index.js')
.replace('/src/', '/dist/lib/')
.replace('.vue', '.js')

View File

@ -27,6 +27,7 @@ import Pager from './src/pager'
import Wizard from './src/wizard'
import DialogBox from './src/dialog-box'
import Popeditor from './src/popeditor'
import DialogSelect from './src/dialog-select'
import { version } from './package.json'
export default {
@ -61,6 +62,7 @@ export default {
Pager,
Wizard,
DialogBox,
Popeditor
Popeditor,
DialogSelect
}
}

View File

@ -27,9 +27,10 @@ import DateRange from './src/date-range'
import Pager from './src/pager'
import DialogBox from './src/dialog-box'
import Popeditor from './src/popeditor'
import { version } from './package.json'
import DialogSelect from './src/dialog-select'
import DatePanel from './src/date-panel'
import Cascader from './src/cascader'
import { version } from './package.json'
export default {
name: 'saas',
@ -65,6 +66,7 @@ export default {
DateRange,
DialogBox,
DatePanel,
DialogSelect,
Cascader
}
}

View File

@ -0,0 +1,6 @@
export default {
constants: {
INPUT_HEIGHT: '28px',
INPUT_MARGIN_BOTTOM: '0px'
}
}

View File

@ -1286,6 +1286,11 @@
"type": "module",
"exclude": false
},
"IconMulticolor": {
"path": "vue-icon-multicolor/index.ts",
"type": "module",
"exclude": false
},
"Image": {
"path": "vue/src/image/index.ts",
"type": "component",

View File

@ -10,7 +10,7 @@
*
*/
import { xss } from '../common/xss.js'
import { xss } from '../common/xss'
export const getRoute = (route) => `/${route || ''}`.replace(/^\/+/, '/')

View File

@ -10,7 +10,7 @@
*
*/
import type { IButtonRenderlessParams, IButtonState } from '@/types'
import { xss } from '../common'
import { xss } from '../common/xss'
export const handleClick =
({ emit, props, state }: Pick<IButtonRenderlessParams, 'emit' | 'props' | 'state'>) =>

View File

@ -15,7 +15,7 @@ import { isObject, typeOf as getType, isNull } from '../../common/type'
import _debounce from '../../common/deps/debounce'
import _numerify from './numerify'
import { escapeHtml } from '../../common/string'
import { xss } from '../../common'
import { xss } from '../../common/xss'
export { setObj as set, getObj as get, isEqual } from '../../common/object'

View File

@ -215,7 +215,8 @@ export default (options: IPopperInputParams) => {
/** remove时执行真的移除popper dom操作。 */
const destroyPopper = (remove: 'remove' | boolean) => {
if (remove) {
if (state.popperElm) {
// 当popper中嵌套popper时内层popper被移除后不会重新创建因此onDeactivated不将内层popper移除
if (state.popperElm && state.popperElm.parentNode === document.body) {
off(state.popperElm, 'click', stop)
state.popperElm.remove()
}

View File

@ -10,7 +10,7 @@
*
*/
import { log as uLog, xss } from './xss.js'
import { log as uLog, xss } from './xss'
export const KEY_CODE = {
Backspace: 8,

View File

@ -162,6 +162,93 @@ export const selectedBoxClear =
state.selectedChanged = true
}
export const setTreeSelection =
({ api, state, vm, props }) =>
(keys, value) => {
const tree = vm.$refs.multiTree
if (!tree) {
return
}
if (value) {
keys.forEach((key) => {
if (!state.selectedValues.includes(key)) {
tree.setCheckedByNodeKey(key, true)
const datas = getTreeSelect({ vm, props })
const values = datas.map((item) => item[props.valueField])
state.selectedDatas = datas
state.selectedValues = values
}
})
} else {
keys.forEach((key) => {
if (state.selectedValues.includes(key)) {
tree.setCheckedByNodeKey(key, false)
const datas = getTreeSelect({ vm, props })
const values = datas.map((item) => item[props.valueField])
state.selectedDatas = datas
state.selectedValues = values
}
})
}
api.selectedBoxInit()
}
export const setGridSelection =
({ api, state, vm }) =>
(keys, value) => {
const grid = vm.$refs.multiGrid
if (!grid) {
return
}
const gridRows = []
if (value) {
keys.forEach((key) => {
if (!state.selectedValues.includes(key)) {
const row = grid.getRowById(key)
state.selectedValues = [...state.selectedValues, key]
state.selectedDatas = [...state.selectedDatas, row]
gridRows.push(row)
}
})
} else {
keys.forEach((key) => {
if (state.selectedValues.includes(key)) {
const index = state.selectedValues.indexOf(key)
state.selectedValues.splice(index, 1)
state.selectedDatas.splice(index, 1)
gridRows.push(grid.getRowById(key))
}
})
}
grid.setSelection(gridRows, Boolean(value))
api.selectedBoxInit()
}
export const setSelection =
({ props, api }) =>
(data, value) => {
const { multi, popseletor, valueField } = props
if (!multi) {
return
}
const dataArr = Array.isArray(data) ? data : [data]
const keys = dataArr.map((i) => i[valueField]).filter((i) => i)
if (keys.length === 0) {
return
}
if (popseletor === 'grid') {
return api.setGridSelection(keys, value)
}
if (popseletor === 'tree') {
return api.setTreeSelection(keys, value)
}
}
export const getSelection =
({ state }) =>
() =>
state.selectedDatas
export const selectedBoxDelete =
({ props, state, vm }) =>
({ option: row }) => {

View File

@ -23,7 +23,11 @@ import {
multiTreeRadio,
multiGridRadioChange,
watchMulti,
clearStatus
clearStatus,
setGridSelection,
setTreeSelection,
setSelection,
getSelection
} from './index'
export const api = [
@ -45,10 +49,12 @@ export const api = [
'onFooterConfirm',
'multiTreeRadio',
'multiGridRadioChange',
'clearStatus'
'clearStatus',
'setSelection',
'getSelection'
]
export const renderless = (props, { reactive, computed, watch }, { vm, nextTick, emit }) => {
export const renderless = (props, { reactive, computed, watch }, { vm, nextTick, emit, constants, designConfig }) => {
const state = reactive({
splitValue: 0,
gridColumns: computed(() => api.computedGridColumns()),
@ -72,7 +78,15 @@ export const renderless = (props, { reactive, computed, watch }, { vm, nextTick,
lookupStore: {
datas: []
},
theme: vm.theme
theme: vm.theme,
isBorder: computed(() => {
if (typeof props.gridOp.border === 'boolean') {
return props.gridOp.border
} else {
return vm.theme !== 'saas'
}
}),
constants: designConfig?.constants || constants
})
state.temporary = {}
@ -106,12 +120,20 @@ export const renderless = (props, { reactive, computed, watch }, { vm, nextTick,
setChecked: setChecked({ api, props, state }),
multiTreeRadio: multiTreeRadio({ api, props }),
watchMulti: watchMulti({ api, state, props }),
clearStatus: clearStatus(api)
clearStatus: clearStatus(api),
setSelection: setSelection({ api, props }),
getSelection: getSelection({ state }),
setTreeSelection: setTreeSelection({ api, state, vm, props }),
setGridSelection: setGridSelection({ api, state, vm })
})
watch(
() => props.visible,
(value) => value && !state.multiGridStore.inited && api.queryGridData()
(value) => {
if (value && !state.multiGridStore.inited) {
api.queryGridData()
}
}
)
watch(

View File

@ -10,7 +10,7 @@
*
*/
import { xss } from '../common'
import { xss } from '../common/xss'
export const getUserHref =
({ api, props }) =>

View File

@ -13,7 +13,7 @@
import { REFRESH_INTERVAL } from '../common'
import { on, off } from '../common/deps/dom'
import PopupManager from '../common/deps/popup-manager'
import { xss } from '../common/xss.js'
import { xss } from '../common/xss'
import type { IFallMenuApi, IFallMenuState, IFallMenuProps, IPagerData } from '@/types'
export const arrowClick = (state: IFallMenuState) => (opt) => {

View File

@ -11,7 +11,7 @@
*/
import type { IFloatbarRenderlessParams, IFloatbarItem } from '@/types'
import { xss } from '../common/xss.js'
import { xss } from '../common/xss'
export const computeData = ({ props }: Pick<IFloatbarRenderlessParams, 'props'>): IFloatbarItem[] => {
if (Array.isArray(props.data) && props.data.length) {

View File

@ -23,7 +23,7 @@
*
*/
import { xss } from '../../common/xss.js'
import { xss } from '../../common/xss'
import browser from '../../common/browser'
import { toTreeArray } from '../static'
import { getCellValue, getFuncText } from '../utils'
@ -71,7 +71,7 @@ const getCsvContent = ($table, opts, oColumns, oData) => {
const tableEl = $table.$el
const tab = opts.useTabs === false ? '' : '\t'
const { columns, datas } = getCsvData(opts, oData, oColumns, tableEl)
let content = '\ufeff' // BOM字节序标记
let content = '\uFEFF' // BOM字节序标记
const transfrom = (str) => {
if (typeof str === 'string' && str.replace(/ /g, '').match(/[\s,"]/)) {
str = '"' + str.replace(/"/g, '""') + '"'

View File

@ -134,19 +134,15 @@ const itemStep = (item, state, deepCopy, index, Shepherd) => {
const footer = currentStepElement && currentStepElement.querySelector('.shepherd-footer')
const cancelIcon =
currentStepElement && currentStepElement.querySelector('.shepherd-header .shepherd-cancel-icon span')
const cloesIcon = `<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 26.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 16 16" style="enable-background:new 0 0 16 16;" xml:space="preserve">
<style type="text/css">
.st0{fill:none;}
.st1{fill-rule:evenodd;clip-rule:evenodd;}
</style>
<polygon id="Fill-1" class="st0" points="0,16 16,16 16,0 0,0 "/>
<path id="形状结合" class="st1" d="M4.25,3.4L8,7.15l3.75-3.75c0.23-0.23,0.61-0.23,0.85,0c0.23,0.23,0.23,0.62,0,0.85L8.85,8
l3.75,3.75c0.23,0.24,0.23,0.62,0,0.85c-0.23,0.23-0.61,0.23-0.85,0L8,8.85L4.25,12.6c-0.23,0.23-0.61,0.23-0.85,0
c-0.24-0.23-0.24-0.61,0-0.85L7.15,8L3.4,4.25c-0.23-0.23-0.23-0.61,0-0.85C3.64,3.17,4.02,3.17,4.25,3.4z"/>
</svg>`
const cloesIcon = `<svg viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<desc fill="none">
Created with Pixso.
</desc>
<defs fill="none" />
<g>
<path id="path" d="M12.49 3.3C12.66 3.47 12.66 3.74 12.54 3.92L8.58 7.89L12.49 11.77C12.7 11.96 12.72 12.25 12.54 12.48C12.37 12.67 12.05 12.72 11.83 12.54L7.88 8.58L4 12.49C3.82 12.66 3.5 12.67 3.32 12.5C3.13 12.33 3.08 12.05 3.24 11.83L7.17 7.89L3.29 4C3.12 3.79 3.13 3.48 3.33 3.29C3.5 3.15 3.75 3.13 3.91 3.24L7.88 7.17L11.78 3.3C11.96 3.08 12.29 3.08 12.49 3.3Z" fill-opacity="1.000000" fill-rule="evenodd"/>
</g>
</svg>`
cancelIcon.innerHTML = cloesIcon
const progress = document.createElement('span')

View File

@ -93,7 +93,8 @@ const initState = ({ reactive, computed, api, mode, props, constants, inject })
infinite: true,
loading: false,
transform: { scale: 1, deg: 0, offsetX: 0, offsetY: 0, objfit: 'contain', enableTransition: false },
urlList: props.urlList || inject('urlList', null),
urlList:
props.urlList || (Array.isArray(inject('urlList')) && inject('urlList').length !== 0) ? inject('urlList') : null,
mode: constants.MODE.CONTAIN,
previewVisible: props.previewVisible,
fullScreen: props.imageFullCurrent,

View File

@ -11,13 +11,7 @@
*/
import { omitText } from '../common/string'
import type {
IInputApi,
IInputClassPrefixConstants,
IInputRenderlessParamUtils,
IInputRenderlessParams,
IInputState
} from 'types/input.type'
import type { IInputApi, IInputRenderlessParamUtils, IInputRenderlessParams, IInputState } from 'types/input.type'
const HIDDEN_STYLE = `
height:0 !important;visibility:hidden !important;overflow:hidden !important;
@ -340,11 +334,9 @@ export const handleCompositionEnd =
}
export const calcIconOffset =
({ CLASS_PREFIX, parent }: Pick<IInputRenderlessParams, 'parent'> & { CLASS_PREFIX: IInputClassPrefixConstants }) =>
({ vm, parent }: Pick<IInputRenderlessParams, 'parent' | 'vm'>) =>
(place: 'prefix' | 'suffix'): void => {
const elList = [].slice.call(
parent.$el.querySelectorAll(`.${CLASS_PREFIX.Input}${place}`) || []
) as unknown as HTMLElement[]
const elList = vm.$refs[place] ? [vm.$refs[place]] : []
if (!elList.length) {
return
@ -367,11 +359,11 @@ export const calcIconOffset =
const pendant = pendantMap[place]
if (parent.$slots[pendant]) {
const dom = parent.$el.querySelector(`.${CLASS_PREFIX.InputGroup}${pendant}`)
const dom = vm.$refs[pendant]
let transform
if (place === 'suffix') {
transform = `translateX(-${dom.offsetWidth}px)`
transform = `translateX(-${dom.offsetWidth}px) translateY(-50%)`
} else if (place === 'prefix') {
transform = `translate(${dom.offsetWidth}px, -50%)`
}

View File

@ -15,7 +15,6 @@ import type {
IInputState,
ISharedRenderlessParamHooks,
IInputRenderlessParamUtils,
IInputClassPrefixConstants,
IInputEventNameConstants,
IInputRenderlessParams
} from '@/types'
@ -195,15 +194,12 @@ const initApi = ({
emit,
vm,
props,
CLASS_PREFIX,
parent,
nextTick
}: Pick<
IInputRenderlessParams,
'api' | 'state' | 'dispatch' | 'broadcast' | 'emit' | 'refs' | 'props' | 'parent' | 'vm' | 'nextTick'
> & {
CLASS_PREFIX: IInputClassPrefixConstants
}) => {
>) => {
Object.assign(api, {
state,
dispatch,
@ -214,7 +210,7 @@ const initApi = ({
setShowMoreBtn: setShowMoreBtn({ state, vm }),
handleChange: handleChange(emit),
watchFormSelect: watchFormSelect({ emit, props, state }),
calcIconOffset: calcIconOffset({ CLASS_PREFIX, parent }),
calcIconOffset: calcIconOffset({ vm, parent }),
getSuffixVisible: getSuffixVisible({ parent, props, state }),
calculateNodeStyling: calculateNodeStyling(),
handleCompositionStart: handleCompositionStart(state),
@ -388,13 +384,9 @@ export const renderless = (
const api = {} as IInputApi
const componentName = constants.COMPONENT_NAME.FormItem
const eventName: IInputEventNameConstants = { change: 'form.change', blur: 'form.blur' }
const CLASS_PREFIX: IInputClassPrefixConstants = {
Input: constants.inputMode(mode),
InputGroup: constants.inputGroupMode(mode)
}
const state = initState({ reactive, computed, mode, props, parent, constants, api, vm, designConfig })
initApi({ api, state, dispatch, broadcast, emit, refs, props, CLASS_PREFIX, parent, vm, nextTick })
initApi({ api, state, dispatch, broadcast, emit, refs, props, parent, vm, nextTick })
const storages = useStorageBox({ api, props, reactive, toRefs })

Some files were not shown because too many files have changed in this diff Show More