diff --git a/example/app.js b/example/app.js
index 0951a2d1..674c3fde 100644
--- a/example/app.js
+++ b/example/app.js
@@ -14,6 +14,7 @@ import HideSeconds from './demo/HideSeconds.vue';
import MinuteStep from './demo/MinuteStep.vue';
import FixedTimeList from './demo/FixedTimeList.vue';
import Disabled from './demo/Disabled.vue';
+import ShadowDom from './demo/ShadowDom.vue';
import docEn from './en.md';
import docZhCN from './zh-cn.md';
@@ -74,6 +75,11 @@ const components = [
component: ControlOpen,
code: fs.readFileSync(`${__dirname}/demo/ControlOpen.vue`, 'utf8'),
},
+ {
+ id: 'ShadowDom',
+ component: ShadowDom,
+ code: fs.readFileSync(`${__dirname}/demo/ShadowDom.vue`, 'utf8'),
+ },
];
function transformMd(text) {
diff --git a/example/demo/ShadowDom.vue b/example/demo/ShadowDom.vue
new file mode 100644
index 00000000..601aad59
--- /dev/null
+++ b/example/demo/ShadowDom.vue
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
diff --git a/example/en.md b/example/en.md
index 1f64814d..8e3c7fab 100644
--- a/example/en.md
+++ b/example/en.md
@@ -81,3 +81,9 @@ Set custom time options by `hourOptions` `minuteOptions` `secondOptions`.
### Select fixed time list
You can provide a list of fixed time for users to choose by `timePickerOptions`
+
+
+
+### Shadow DOM
+
+If you use the component inside shadow DOM, you should set the `:append-to-body="false"`.
diff --git a/example/zh-cn.md b/example/zh-cn.md
index 6822ef58..550295de 100644
--- a/example/zh-cn.md
+++ b/example/zh-cn.md
@@ -81,3 +81,9 @@
### 固定的时间列表
可以通过 `timePickerOptions` 提供一个固定的时间列表选择
+
+
+
+### Shadow DOM
+
+If you use the component inside shadow DOM, you should set the `:append-to-body="false"`.
diff --git a/src/popup.vue b/src/popup.vue
index 731adf6d..d3dc5faf 100644
--- a/src/popup.vue
+++ b/src/popup.vue
@@ -37,6 +37,25 @@ export default {
left: '',
};
},
+ computed: {
+ hasShadowParent() {
+ if (!document.head.attachShadow) {
+ return false;
+ }
+
+ let element = this.$el;
+
+ while (element) {
+ if (element instanceof ShadowRoot) {
+ return true;
+ }
+
+ element = element.parentNode;
+ }
+
+ return false;
+ },
+ },
watch: {
visible: {
immediate: true,
@@ -76,10 +95,18 @@ export default {
},
methods: {
handleClickOutside(evt) {
- if (!this.visible) return;
+ if (!this.visible) {
+ return;
+ }
+
const { target } = evt;
const el = this.$el;
+
if (el && !el.contains(target)) {
+ if (this.hasShadowParent && evt.composedPath().includes(el)) {
+ return;
+ }
+
this.$emit('clickoutside', evt);
}
},