Demo:新增外框设置功能
This commit is contained in:
parent
53eb608007
commit
1fc5b951a0
@ -1,8 +1,8 @@
|
|||||||
@font-face {
|
@font-face {
|
||||||
font-family: "iconfont"; /* Project id 2479351 */
|
font-family: "iconfont"; /* Project id 2479351 */
|
||||||
src: url('iconfont.woff2?t=1718261316837') format('woff2'),
|
src: url('iconfont.woff2?t=1719815803051') format('woff2'),
|
||||||
url('iconfont.woff?t=1718261316837') format('woff'),
|
url('iconfont.woff?t=1719815803051') format('woff'),
|
||||||
url('iconfont.ttf?t=1718261316837') format('truetype');
|
url('iconfont.ttf?t=1719815803051') format('truetype');
|
||||||
}
|
}
|
||||||
|
|
||||||
.iconfont {
|
.iconfont {
|
||||||
@ -13,6 +13,10 @@
|
|||||||
-moz-osx-font-smoothing: grayscale;
|
-moz-osx-font-smoothing: grayscale;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.iconwaikuang:before {
|
||||||
|
content: "\e640";
|
||||||
|
}
|
||||||
|
|
||||||
.iconhighlight:before {
|
.iconhighlight:before {
|
||||||
content: "\e6b8";
|
content: "\e6b8";
|
||||||
}
|
}
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -266,6 +266,7 @@ export default {
|
|||||||
painter: 'Painter',
|
painter: 'Painter',
|
||||||
formula: 'Formula',
|
formula: 'Formula',
|
||||||
attachment: 'Attachment',
|
attachment: 'Attachment',
|
||||||
|
outerFrame: 'Outer frame',
|
||||||
more: 'More',
|
more: 'More',
|
||||||
selectFileTip: 'Please select a file',
|
selectFileTip: 'Please select a file',
|
||||||
notSupportTip:
|
notSupportTip:
|
||||||
@ -357,5 +358,12 @@ export default {
|
|||||||
lineWidth: 'Line width',
|
lineWidth: 'Line width',
|
||||||
padding: 'Padding',
|
padding: 'Padding',
|
||||||
animate: 'Animate'
|
animate: 'Animate'
|
||||||
|
},
|
||||||
|
nodeOuterFrame: {
|
||||||
|
outerFrameSetting: 'Setting',
|
||||||
|
deleteOuterFrame: 'Delete outer frame',
|
||||||
|
boxStyle: 'Box style',
|
||||||
|
boxColor: 'Box color',
|
||||||
|
fillColor: 'Fill color'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -263,6 +263,7 @@ export default {
|
|||||||
painter: '格式刷',
|
painter: '格式刷',
|
||||||
formula: '公式',
|
formula: '公式',
|
||||||
attachment: '附件',
|
attachment: '附件',
|
||||||
|
outerFrame: '外框',
|
||||||
more: '更多',
|
more: '更多',
|
||||||
selectFileTip: '请选择文件',
|
selectFileTip: '请选择文件',
|
||||||
notSupportTip: '你的浏览器不支持该功能,或者当前页面非https协议',
|
notSupportTip: '你的浏览器不支持该功能,或者当前页面非https协议',
|
||||||
@ -349,5 +350,12 @@ export default {
|
|||||||
lineWidth: '线宽',
|
lineWidth: '线宽',
|
||||||
padding: '内边距',
|
padding: '内边距',
|
||||||
animate: '开启动画'
|
animate: '开启动画'
|
||||||
|
},
|
||||||
|
nodeOuterFrame: {
|
||||||
|
outerFrameSetting: '外框设置',
|
||||||
|
deleteOuterFrame: '删除外框',
|
||||||
|
boxStyle: '边框样式',
|
||||||
|
boxColor: '边框颜色',
|
||||||
|
fillColor: '填充颜色'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -36,6 +36,7 @@
|
|||||||
<Scrollbar v-if="isShowScrollbar && mindMap" :mindMap="mindMap"></Scrollbar>
|
<Scrollbar v-if="isShowScrollbar && mindMap" :mindMap="mindMap"></Scrollbar>
|
||||||
<FormulaSidebar v-if="mindMap" :mindMap="mindMap"></FormulaSidebar>
|
<FormulaSidebar v-if="mindMap" :mindMap="mindMap"></FormulaSidebar>
|
||||||
<SourceCodeEdit v-if="mindMap" :mindMap="mindMap"></SourceCodeEdit>
|
<SourceCodeEdit v-if="mindMap" :mindMap="mindMap"></SourceCodeEdit>
|
||||||
|
<NodeOuterFrame v-if="mindMap" :mindMap="mindMap"></NodeOuterFrame>
|
||||||
<div
|
<div
|
||||||
class="dragMask"
|
class="dragMask"
|
||||||
v-if="showDragMask"
|
v-if="showDragMask"
|
||||||
@ -68,6 +69,7 @@ import ScrollbarPlugin from 'simple-mind-map/src/plugins/Scrollbar.js'
|
|||||||
import Formula from 'simple-mind-map/src/plugins/Formula.js'
|
import Formula from 'simple-mind-map/src/plugins/Formula.js'
|
||||||
import RainbowLines from 'simple-mind-map/src/plugins/RainbowLines.js'
|
import RainbowLines from 'simple-mind-map/src/plugins/RainbowLines.js'
|
||||||
import Demonstrate from 'simple-mind-map/src/plugins/Demonstrate.js'
|
import Demonstrate from 'simple-mind-map/src/plugins/Demonstrate.js'
|
||||||
|
import OuterFrame from 'simple-mind-map/src/plugins/OuterFrame.js'
|
||||||
// 协同编辑插件
|
// 协同编辑插件
|
||||||
// import Cooperate from 'simple-mind-map/src/plugins/Cooperate.js'
|
// import Cooperate from 'simple-mind-map/src/plugins/Cooperate.js'
|
||||||
// 手绘风格插件,该插件为付费插件,详情请查看开发文档
|
// 手绘风格插件,该插件为付费插件,详情请查看开发文档
|
||||||
@ -109,6 +111,7 @@ import exampleData from 'simple-mind-map/example/exampleData'
|
|||||||
import FormulaSidebar from './FormulaSidebar.vue'
|
import FormulaSidebar from './FormulaSidebar.vue'
|
||||||
import SourceCodeEdit from './SourceCodeEdit.vue'
|
import SourceCodeEdit from './SourceCodeEdit.vue'
|
||||||
import NodeAttachment from './NodeAttachment.vue'
|
import NodeAttachment from './NodeAttachment.vue'
|
||||||
|
import NodeOuterFrame from './NodeOuterFrame.vue'
|
||||||
|
|
||||||
// 注册插件
|
// 注册插件
|
||||||
MindMap.usePlugin(MiniMap)
|
MindMap.usePlugin(MiniMap)
|
||||||
@ -127,6 +130,7 @@ MindMap.usePlugin(MiniMap)
|
|||||||
.usePlugin(Formula)
|
.usePlugin(Formula)
|
||||||
.usePlugin(RainbowLines)
|
.usePlugin(RainbowLines)
|
||||||
.usePlugin(Demonstrate)
|
.usePlugin(Demonstrate)
|
||||||
|
.usePlugin(OuterFrame)
|
||||||
// .usePlugin(Cooperate) // 协同插件
|
// .usePlugin(Cooperate) // 协同插件
|
||||||
|
|
||||||
// 注册自定义主题
|
// 注册自定义主题
|
||||||
@ -163,7 +167,8 @@ export default {
|
|||||||
Scrollbar,
|
Scrollbar,
|
||||||
FormulaSidebar,
|
FormulaSidebar,
|
||||||
SourceCodeEdit,
|
SourceCodeEdit,
|
||||||
NodeAttachment
|
NodeAttachment,
|
||||||
|
NodeOuterFrame
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
@ -404,7 +409,7 @@ export default {
|
|||||||
cssText,
|
cssText,
|
||||||
height: 30
|
height: 30
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
// createNodePrefixContent: (node) => {
|
// createNodePrefixContent: (node) => {
|
||||||
// const el = document.createElement('div')
|
// const el = document.createElement('div')
|
||||||
// el.style.width = '50px'
|
// el.style.width = '50px'
|
||||||
|
|||||||
358
web/src/pages/Edit/components/NodeOuterFrame.vue
Normal file
358
web/src/pages/Edit/components/NodeOuterFrame.vue
Normal file
@ -0,0 +1,358 @@
|
|||||||
|
<template>
|
||||||
|
<div
|
||||||
|
class="nodeOuterFrameContainer"
|
||||||
|
ref="elRef"
|
||||||
|
:style="position"
|
||||||
|
v-show="show"
|
||||||
|
:class="{ isDark: isDark }"
|
||||||
|
>
|
||||||
|
<div class="btn" @click="showPanel = !showPanel">
|
||||||
|
<span class="iconfont iconjingzi"></span>
|
||||||
|
</div>
|
||||||
|
<div class="panel" v-if="showPanel">
|
||||||
|
<div class="panelHeader">
|
||||||
|
<span class="name">{{ $t('nodeOuterFrame.outerFrameSetting') }}</span>
|
||||||
|
<span class="deleteBtn" @click="deleteOuterFrame">
|
||||||
|
{{ $t('nodeOuterFrame.deleteOuterFrame') }}
|
||||||
|
<span class="iconfont iconshanchu"></span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="panelBody">
|
||||||
|
<div class="row">
|
||||||
|
<div class="rowItem">
|
||||||
|
<span class="name">{{ $t('nodeOuterFrame.boxStyle') }}</span>
|
||||||
|
<!-- 宽度 -->
|
||||||
|
<el-select
|
||||||
|
size="mini"
|
||||||
|
style="width: 80px"
|
||||||
|
v-model="styleConfig.strokeWidth"
|
||||||
|
placeholder=""
|
||||||
|
@change="
|
||||||
|
value => {
|
||||||
|
updateOuterFrame('strokeWidth', value)
|
||||||
|
}
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="item in lineWidthList"
|
||||||
|
:key="item"
|
||||||
|
:label="item"
|
||||||
|
:value="item"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
v-if="item > 0"
|
||||||
|
class="borderLine"
|
||||||
|
:class="{ isDark: isDark }"
|
||||||
|
:style="{ height: item + 'px' }"
|
||||||
|
></span>
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
<!-- 实现虚线 -->
|
||||||
|
<el-select
|
||||||
|
size="mini"
|
||||||
|
style="width: 80px;margin-left: 4px;"
|
||||||
|
v-model="styleConfig.strokeDasharray"
|
||||||
|
placeholder=""
|
||||||
|
@change="
|
||||||
|
value => {
|
||||||
|
updateOuterFrame('strokeDasharray', value)
|
||||||
|
}
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="item in borderDasharrayList"
|
||||||
|
:key="item.value"
|
||||||
|
:label="item.name"
|
||||||
|
:value="item.value"
|
||||||
|
>
|
||||||
|
<svg width="120" height="34">
|
||||||
|
<line
|
||||||
|
x1="10"
|
||||||
|
y1="17"
|
||||||
|
x2="110"
|
||||||
|
y2="17"
|
||||||
|
stroke-width="2"
|
||||||
|
:stroke="
|
||||||
|
styleConfig.strokeDasharray === item.value
|
||||||
|
? '#409eff'
|
||||||
|
: isDark
|
||||||
|
? '#fff'
|
||||||
|
: '#000'
|
||||||
|
"
|
||||||
|
:stroke-dasharray="item.value"
|
||||||
|
></line>
|
||||||
|
</svg>
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="rowItem">
|
||||||
|
<span class="name">{{ $t('nodeOuterFrame.boxColor') }}</span>
|
||||||
|
<span
|
||||||
|
class="block"
|
||||||
|
v-popover:popover
|
||||||
|
:style="{ backgroundColor: styleConfig.strokeColor }"
|
||||||
|
></span>
|
||||||
|
<el-popover ref="popover" placement="bottom" trigger="click">
|
||||||
|
<Color
|
||||||
|
:color="styleConfig.strokeColor"
|
||||||
|
@change="
|
||||||
|
color => {
|
||||||
|
updateOuterFrame('strokeColor', color)
|
||||||
|
}
|
||||||
|
"
|
||||||
|
></Color>
|
||||||
|
</el-popover>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="rowItem">
|
||||||
|
<span class="name">{{ $t('nodeOuterFrame.fillColor') }}</span>
|
||||||
|
<span
|
||||||
|
class="block"
|
||||||
|
v-popover:popover2
|
||||||
|
:style="{ backgroundColor: styleConfig.fill }"
|
||||||
|
></span>
|
||||||
|
<el-popover ref="popover2" placement="bottom" trigger="click">
|
||||||
|
<Color
|
||||||
|
:color="styleConfig.fill"
|
||||||
|
@change="
|
||||||
|
color => {
|
||||||
|
updateOuterFrame('fill', color)
|
||||||
|
}
|
||||||
|
"
|
||||||
|
></Color>
|
||||||
|
</el-popover>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import Color from './Color'
|
||||||
|
import { mapState } from 'vuex'
|
||||||
|
import { lineWidthList, borderDasharrayList } from '@/config'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
Color
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
mindMap: {
|
||||||
|
type: Object
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
lineWidthList,
|
||||||
|
show: false,
|
||||||
|
showPanel: false,
|
||||||
|
position: {
|
||||||
|
left: 0,
|
||||||
|
top: 0
|
||||||
|
},
|
||||||
|
styleConfig: {
|
||||||
|
radius: 5,
|
||||||
|
strokeWidth: 2,
|
||||||
|
strokeColor: '#0984e3',
|
||||||
|
strokeDasharray: '5,5',
|
||||||
|
fill: 'rgba(9,132,227,0.05)'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
...mapState({
|
||||||
|
isDark: state => state.localConfig.isDark,
|
||||||
|
borderDasharrayList() {
|
||||||
|
return borderDasharrayList[this.$i18n.locale] || borderDasharrayList.zh
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.mindMap.on('outer_frame_active', this.onOuterFrameActive)
|
||||||
|
this.mindMap.on('scale', this.hide)
|
||||||
|
this.mindMap.on('translate', this.hide)
|
||||||
|
this.mindMap.on('svg_mousedown', this.hide)
|
||||||
|
this.mindMap.on('expand_btn_click', this.hide)
|
||||||
|
this.mindMap.on('outer_frame_delete', this.hide)
|
||||||
|
},
|
||||||
|
beforeDestroy() {
|
||||||
|
this.mindMap.off('outer_frame_active', this.onOuterFrameActive)
|
||||||
|
this.mindMap.off('scale', this.hide)
|
||||||
|
this.mindMap.off('translate', this.hide)
|
||||||
|
this.mindMap.off('svg_mousedown', this.hide)
|
||||||
|
this.mindMap.off('expand_btn_click', this.hide)
|
||||||
|
this.mindMap.off('outer_frame_delete', this.hide)
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
document.body.appendChild(this.$refs.elRef)
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
onOuterFrameActive(el, parentNode, range) {
|
||||||
|
// 取范围内第一个节点的外框样式
|
||||||
|
const firstNode = parentNode.children[range[0]]
|
||||||
|
const firstNodeOuterFrame = firstNode.getData('outerFrame')
|
||||||
|
Object.keys(firstNodeOuterFrame).forEach(key => {
|
||||||
|
this.styleConfig[key] = firstNodeOuterFrame[key]
|
||||||
|
})
|
||||||
|
// 获取外框的位置大小信息
|
||||||
|
const { x, y, width } = el.rbox()
|
||||||
|
this.position.left = x + width + 'px'
|
||||||
|
this.position.top = y + 'px'
|
||||||
|
this.show = true
|
||||||
|
},
|
||||||
|
|
||||||
|
updateOuterFrame(key, val) {
|
||||||
|
this.styleConfig[key] = val
|
||||||
|
this.mindMap.outerFrame.updateActiveOuterFrame({
|
||||||
|
[key]: val
|
||||||
|
})
|
||||||
|
this.hide()
|
||||||
|
},
|
||||||
|
|
||||||
|
deleteOuterFrame() {
|
||||||
|
this.mindMap.outerFrame.removeActiveOuterFrame()
|
||||||
|
},
|
||||||
|
|
||||||
|
hide() {
|
||||||
|
this.show = false
|
||||||
|
this.showPanel = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less">
|
||||||
|
.el-select-dropdown__item.selected {
|
||||||
|
.borderLine {
|
||||||
|
background-color: #409eff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.nodeOuterFrameContainer {
|
||||||
|
position: fixed;
|
||||||
|
transform: translate(-12px, -12px);
|
||||||
|
|
||||||
|
&.isDark {
|
||||||
|
.panel {
|
||||||
|
background-color: #262a2e;
|
||||||
|
border-left-color: hsla(0, 0%, 100%, 0.1);
|
||||||
|
|
||||||
|
.panelHeader {
|
||||||
|
.name {
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.panelBody {
|
||||||
|
.row {
|
||||||
|
.rowItem {
|
||||||
|
.name {
|
||||||
|
color: hsla(0, 0%, 100%, 0.6);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 50%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
cursor: pointer;
|
||||||
|
box-shadow: 0 2px 16px 0 rgba(0, 0, 0, 0.06);
|
||||||
|
border: 1px solid rgba(0, 0, 0, 0.06);
|
||||||
|
}
|
||||||
|
|
||||||
|
.panel {
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 24px;
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 5px;
|
||||||
|
box-shadow: 0 2px 16px 0 rgba(0, 0, 0, 0.06);
|
||||||
|
border: 1px solid rgba(0, 0, 0, 0.06);
|
||||||
|
width: 250px;
|
||||||
|
padding: 12px;
|
||||||
|
|
||||||
|
.panelHeader {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
|
||||||
|
.name {
|
||||||
|
font-size: 16px;
|
||||||
|
font-family: PingFangSC-Medium, PingFang SC;
|
||||||
|
font-weight: 500;
|
||||||
|
color: rgba(26, 26, 26, 0.9);
|
||||||
|
}
|
||||||
|
|
||||||
|
.deleteBtn {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
color: #909090;
|
||||||
|
font-size: 14px;
|
||||||
|
cursor: pointer;
|
||||||
|
user-select: none;
|
||||||
|
|
||||||
|
.iconfont {
|
||||||
|
margin-left: 2px;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.panelBody {
|
||||||
|
.row {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
|
||||||
|
&:last-of-type {
|
||||||
|
margin-bottom: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rowItem {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.name {
|
||||||
|
font-size: 12px;
|
||||||
|
margin-right: 10px;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.block {
|
||||||
|
display: inline-block;
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
border: 1px solid #dcdfe6;
|
||||||
|
border-radius: 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.borderLine {
|
||||||
|
display: inline-block;
|
||||||
|
width: 100%;
|
||||||
|
background-color: #000;
|
||||||
|
|
||||||
|
&.isDark {
|
||||||
|
background-color: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -194,7 +194,8 @@ export default {
|
|||||||
'associativeLine',
|
'associativeLine',
|
||||||
'formula',
|
'formula',
|
||||||
// 'attachment',
|
// 'attachment',
|
||||||
'annotation'
|
'annotation',
|
||||||
|
'outerFrame'
|
||||||
],
|
],
|
||||||
horizontalList: [],
|
horizontalList: [],
|
||||||
verticalList: [],
|
verticalList: [],
|
||||||
|
|||||||
@ -167,6 +167,17 @@
|
|||||||
<span class="icon iconfont iconfujian"></span>
|
<span class="icon iconfont iconfujian"></span>
|
||||||
<span class="text">{{ $t('toolbar.attachment') }}</span>
|
<span class="text">{{ $t('toolbar.attachment') }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
<div
|
||||||
|
v-if="item === 'outerFrame'"
|
||||||
|
class="toolbarBtn"
|
||||||
|
:class="{
|
||||||
|
disabled: activeNodes.length <= 0 || hasGeneralization
|
||||||
|
}"
|
||||||
|
@click="$bus.$emit('execCommand', 'ADD_OUTER_FRAME')"
|
||||||
|
>
|
||||||
|
<span class="icon iconfont iconwaikuang"></span>
|
||||||
|
<span class="text">{{ $t('toolbar.outerFrame') }}</span>
|
||||||
|
</div>
|
||||||
<NodeAnnotationBtn
|
<NodeAnnotationBtn
|
||||||
v-if="item === 'annotation' && supportMark"
|
v-if="item === 'annotation' && supportMark"
|
||||||
:isDark="isDark"
|
:isDark="isDark"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user