cl-popup 添加 teleport 支持
This commit is contained in:
@@ -30,6 +30,25 @@
|
|||||||
></cl-select>
|
></cl-select>
|
||||||
</demo-item>
|
</demo-item>
|
||||||
|
|
||||||
|
<demo-item :label="t('弹窗中使用')">
|
||||||
|
<cl-button @tap="visible3 = true">打开</cl-button>
|
||||||
|
|
||||||
|
<cl-popup v-model="visible3" direction="center" size="80%" :title="t('选择地区')">
|
||||||
|
<view class="p-3 pt-0">
|
||||||
|
<demo-tips>
|
||||||
|
H5 和 APP 端通过 teleport 实现弹窗内的选择器使用,小程序端则通过
|
||||||
|
root-portal 实现。
|
||||||
|
</demo-tips>
|
||||||
|
|
||||||
|
<cl-select
|
||||||
|
v-model="form.selected3"
|
||||||
|
:options="options3"
|
||||||
|
:column-count="3"
|
||||||
|
></cl-select>
|
||||||
|
</view>
|
||||||
|
</cl-popup>
|
||||||
|
</demo-item>
|
||||||
|
|
||||||
<demo-item :label="t('自定义')">
|
<demo-item :label="t('自定义')">
|
||||||
<cl-text
|
<cl-text
|
||||||
:pt="{
|
:pt="{
|
||||||
@@ -359,4 +378,6 @@ function openSelect2() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const visible3 = ref(false);
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -548,7 +548,7 @@ function onTouchCancel() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.cl-button {
|
.cl-button {
|
||||||
@apply flex flex-row items-center justify-center relative;
|
@apply flex flex-row items-center justify-center relative box-border;
|
||||||
@apply border border-transparent border-solid;
|
@apply border border-transparent border-solid;
|
||||||
overflow: visible;
|
overflow: visible;
|
||||||
transition-duration: 0.3s;
|
transition-duration: 0.3s;
|
||||||
|
|||||||
@@ -1,106 +1,123 @@
|
|||||||
<template>
|
<template>
|
||||||
<view
|
<!-- #ifdef H5 -->
|
||||||
class="cl-popup-wrapper"
|
<teleport to="#app">
|
||||||
:class="[`cl-popup-wrapper--${direction}`]"
|
<!-- #endif -->
|
||||||
:style="{
|
|
||||||
zIndex,
|
|
||||||
pointerEvents
|
|
||||||
}"
|
|
||||||
v-show="visible"
|
|
||||||
v-if="keepAlive ? true : visible"
|
|
||||||
@touchmove.stop.prevent
|
|
||||||
>
|
|
||||||
<view
|
|
||||||
class="cl-popup-mask"
|
|
||||||
:class="[
|
|
||||||
{
|
|
||||||
'is-open': status == 1,
|
|
||||||
'is-close': status == 2
|
|
||||||
},
|
|
||||||
pt.mask?.className
|
|
||||||
]"
|
|
||||||
@tap="maskClose"
|
|
||||||
v-if="showMask"
|
|
||||||
></view>
|
|
||||||
|
|
||||||
<view
|
<!-- #ifdef MP -->
|
||||||
class="cl-popup"
|
<root-portal>
|
||||||
:class="[
|
<!-- #endif -->
|
||||||
{
|
|
||||||
'is-open': status == 1,
|
|
||||||
'is-close': status == 2,
|
|
||||||
'is-custom-navbar': router.isCustomNavbarPage(),
|
|
||||||
'stop-transition': swipe.isTouch
|
|
||||||
},
|
|
||||||
pt.className
|
|
||||||
]"
|
|
||||||
:style="popupStyle"
|
|
||||||
@touchstart="onTouchStart"
|
|
||||||
@touchmove="onTouchMove"
|
|
||||||
@touchend="onTouchEnd"
|
|
||||||
@touchcancel="onTouchEnd"
|
|
||||||
>
|
|
||||||
<view
|
<view
|
||||||
class="cl-popup__inner"
|
class="cl-popup-wrapper"
|
||||||
:class="[
|
:class="[`cl-popup-wrapper--${direction}`]"
|
||||||
{
|
|
||||||
'is-dark': isDark
|
|
||||||
},
|
|
||||||
pt.inner?.className
|
|
||||||
]"
|
|
||||||
:style="{
|
:style="{
|
||||||
paddingBottom
|
zIndex,
|
||||||
|
pointerEvents
|
||||||
}"
|
}"
|
||||||
|
v-show="visible"
|
||||||
|
v-if="keepAlive ? true : visible"
|
||||||
|
@touchmove.stop.prevent
|
||||||
>
|
>
|
||||||
<view
|
<view
|
||||||
class="cl-popup__draw"
|
class="cl-popup-mask"
|
||||||
:class="[
|
:class="[
|
||||||
{
|
{
|
||||||
'!bg-surface-400': swipe.isMove
|
'is-open': status == 1,
|
||||||
|
'is-close': status == 2
|
||||||
},
|
},
|
||||||
pt.draw?.className
|
pt.mask?.className
|
||||||
]"
|
]"
|
||||||
v-if="isSwipeClose"
|
@tap="maskClose"
|
||||||
|
v-if="showMask"
|
||||||
></view>
|
></view>
|
||||||
|
|
||||||
<view class="cl-popup__header" :class="[pt.header?.className]" v-if="showHeader">
|
|
||||||
<slot name="header">
|
|
||||||
<cl-text
|
|
||||||
:pt="{
|
|
||||||
className: `text-lg font-bold ${pt.header?.text?.className}`
|
|
||||||
}"
|
|
||||||
>{{ title }}</cl-text
|
|
||||||
>
|
|
||||||
</slot>
|
|
||||||
|
|
||||||
<cl-icon
|
|
||||||
name="close-circle-fill"
|
|
||||||
:size="40"
|
|
||||||
:pt="{
|
|
||||||
className:
|
|
||||||
'absolute right-[24rpx] !text-surface-400 dark:!text-surface-50'
|
|
||||||
}"
|
|
||||||
@tap="close"
|
|
||||||
@touchmove.stop
|
|
||||||
v-if="isOpen && showClose"
|
|
||||||
></cl-icon>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<view
|
<view
|
||||||
class="cl-popup__container"
|
class="cl-popup"
|
||||||
:class="[pt.container?.className]"
|
:class="[
|
||||||
@touchmove.stop
|
{
|
||||||
|
'is-open': status == 1,
|
||||||
|
'is-close': status == 2,
|
||||||
|
'is-custom-navbar': router.isCustomNavbarPage(),
|
||||||
|
'stop-transition': swipe.isTouch
|
||||||
|
},
|
||||||
|
pt.className
|
||||||
|
]"
|
||||||
|
:style="popupStyle"
|
||||||
|
@touchstart="onTouchStart"
|
||||||
|
@touchmove="onTouchMove"
|
||||||
|
@touchend="onTouchEnd"
|
||||||
|
@touchcancel="onTouchEnd"
|
||||||
>
|
>
|
||||||
<slot></slot>
|
<view
|
||||||
|
class="cl-popup__inner"
|
||||||
|
:class="[
|
||||||
|
{
|
||||||
|
'is-dark': isDark
|
||||||
|
},
|
||||||
|
pt.inner?.className
|
||||||
|
]"
|
||||||
|
:style="{
|
||||||
|
paddingBottom
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<view
|
||||||
|
class="cl-popup__draw"
|
||||||
|
:class="[
|
||||||
|
{
|
||||||
|
'!bg-surface-400': swipe.isMove
|
||||||
|
},
|
||||||
|
pt.draw?.className
|
||||||
|
]"
|
||||||
|
v-if="isSwipeClose"
|
||||||
|
></view>
|
||||||
|
|
||||||
|
<view
|
||||||
|
class="cl-popup__header"
|
||||||
|
:class="[pt.header?.className]"
|
||||||
|
v-if="showHeader"
|
||||||
|
>
|
||||||
|
<slot name="header">
|
||||||
|
<cl-text
|
||||||
|
:pt="{
|
||||||
|
className: `text-lg font-bold ${pt.header?.text?.className}`
|
||||||
|
}"
|
||||||
|
>{{ title }}</cl-text
|
||||||
|
>
|
||||||
|
</slot>
|
||||||
|
|
||||||
|
<cl-icon
|
||||||
|
name="close-circle-fill"
|
||||||
|
:size="40"
|
||||||
|
:pt="{
|
||||||
|
className:
|
||||||
|
'absolute right-[24rpx] !text-surface-400 dark:!text-surface-50'
|
||||||
|
}"
|
||||||
|
@tap="close"
|
||||||
|
@touchmove.stop
|
||||||
|
v-if="isOpen && showClose"
|
||||||
|
></cl-icon>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view
|
||||||
|
class="cl-popup__container"
|
||||||
|
:class="[pt.container?.className]"
|
||||||
|
@touchmove.stop
|
||||||
|
>
|
||||||
|
<slot></slot>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
<!-- #ifdef MP -->
|
||||||
</view>
|
</root-portal>
|
||||||
|
<!-- #endif -->
|
||||||
|
<!-- #ifdef H5 -->
|
||||||
|
</teleport>
|
||||||
|
<!-- #endif -->
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { computed, reactive, ref, watch, type PropType } from "vue";
|
import { computed, reactive, ref, watch, type PropType } from "vue";
|
||||||
import { getSafeAreaHeight, getTabBarHeight, hasCustomTabBar, parsePt, parseRpx } from "@/cool";
|
import { getSafeAreaHeight, parsePt, parseRpx } from "@/cool";
|
||||||
import type { ClPopupDirection, PassThroughProps } from "../../types";
|
import type { ClPopupDirection, PassThroughProps } from "../../types";
|
||||||
import { isDark, router } from "@/cool";
|
import { isDark, router } from "@/cool";
|
||||||
import { config } from "../../config";
|
import { config } from "../../config";
|
||||||
@@ -543,7 +560,7 @@ defineExpose({
|
|||||||
.cl-popup {
|
.cl-popup {
|
||||||
@apply left-0 top-0;
|
@apply left-0 top-0;
|
||||||
|
|
||||||
&__inner {
|
.cl-popup__inner {
|
||||||
@apply rounded-b-2xl;
|
@apply rounded-b-2xl;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -554,7 +571,7 @@ defineExpose({
|
|||||||
&--left,
|
&--left,
|
||||||
&--right,
|
&--right,
|
||||||
&--top {
|
&--top {
|
||||||
.cl-popup {
|
& > .cl-popup {
|
||||||
// #ifdef H5
|
// #ifdef H5
|
||||||
top: 44px;
|
top: 44px;
|
||||||
// #endif
|
// #endif
|
||||||
@@ -567,7 +584,7 @@ defineExpose({
|
|||||||
|
|
||||||
&--left,
|
&--left,
|
||||||
&--right {
|
&--right {
|
||||||
.cl-popup {
|
& > .cl-popup {
|
||||||
// #ifdef H5
|
// #ifdef H5
|
||||||
height: calc(100% - 44px) !important;
|
height: calc(100% - 44px) !important;
|
||||||
// #endif
|
// #endif
|
||||||
@@ -575,11 +592,11 @@ defineExpose({
|
|||||||
}
|
}
|
||||||
|
|
||||||
&--bottom {
|
&--bottom {
|
||||||
.cl-popup {
|
& > .cl-popup {
|
||||||
@apply left-0 bottom-0;
|
@apply left-0 bottom-0;
|
||||||
transform: translateY(100%);
|
transform: translateY(100%);
|
||||||
|
|
||||||
&__inner {
|
.cl-popup__inner {
|
||||||
@apply rounded-t-2xl;
|
@apply rounded-t-2xl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -588,11 +605,11 @@ defineExpose({
|
|||||||
&--center {
|
&--center {
|
||||||
@apply flex flex-col items-center justify-center;
|
@apply flex flex-col items-center justify-center;
|
||||||
|
|
||||||
.cl-popup {
|
& > .cl-popup {
|
||||||
transform: scale(1.3);
|
transform: scale(1.3);
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
|
|
||||||
&__inner {
|
.cl-popup__inner {
|
||||||
@apply rounded-2xl;
|
@apply rounded-2xl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -148,7 +148,7 @@ function open() {
|
|||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.cl-select-trigger {
|
.cl-select-trigger {
|
||||||
@apply flex flex-row items-center w-full;
|
@apply flex flex-row items-center w-full box-border;
|
||||||
@apply border border-solid border-surface-200 rounded-lg bg-white;
|
@apply border border-solid border-surface-200 rounded-lg bg-white;
|
||||||
height: 66rpx;
|
height: 66rpx;
|
||||||
padding: 0 20rpx;
|
padding: 0 20rpx;
|
||||||
|
|||||||
Reference in New Issue
Block a user