Skip to content

Commit c64a772

Browse files
committed
feat: move live demo into iframes
1 parent f3d1224 commit c64a772

File tree

8 files changed

+194
-83
lines changed

8 files changed

+194
-83
lines changed

components/OneDemo.vue

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@
1010
width="calc(100% - 40px)"
1111
height="400px"
1212
>
13-
<slot/>
13+
<one-iframe global-style="body { margin: 0 !important; } .veui-layout { min-width: auto !important; }">
14+
<slot/>
15+
</one-iframe>
1416
</browser-window>
1517
<slot v-else/>
1618
</section>
@@ -104,6 +106,7 @@ import toast from 'veui/plugins/toast'
104106
import { BrowserWindow } from 'vue-windows'
105107
import { getLocale } from '../common/i18n'
106108
import { play } from '../common/play'
109+
import OneIframe from './OneIframe'
107110
import OneEditLink from './OneEditLink'
108111
import OneRepl from './OneRepl'
109112
import 'veui-theme-dls-icons/copy'
@@ -119,6 +122,7 @@ export default {
119122
'veui-button': Button,
120123
'veui-icon': Icon,
121124
BrowserWindow,
125+
OneIframe,
122126
OneEditLink,
123127
OneRepl
124128
},
@@ -223,12 +227,10 @@ Icon.register({
223227
padding 30px
224228
225229
& >>> .style-module_body__14MV-
230+
overflow hidden
226231
transform translate(0, 0)
227232
padding 0
228233
229-
& >>> .veui-layout
230-
min-width auto
231-
232234
.desc
233235
border 1px solid #eee
234236
padding 18px 20px

components/OneIframe.vue

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
<template>
2+
<fragment>
3+
<iframe
4+
ref="iframe"
5+
class="one-iframe"
6+
/>
7+
<slot/>
8+
</fragment>
9+
</template>
10+
11+
<script>
12+
import { Fragment } from 'vue-frag'
13+
14+
export default {
15+
name: 'one-iframe',
16+
components: {
17+
Fragment
18+
},
19+
props: {
20+
globalStyle: String
21+
},
22+
watch: {
23+
globalStyle (value) {
24+
if (this.style) {
25+
this.style.textContent = value
26+
}
27+
}
28+
},
29+
beforeDestroy () {
30+
if (this.contents) {
31+
this.contents.forEach(node => {
32+
this.$refs.iframe.parentNode.appendChild(node)
33+
})
34+
}
35+
36+
if (this.mo) {
37+
this.mo.disconnect()
38+
}
39+
},
40+
mounted () {
41+
const links = document.querySelectorAll('link[rel=stylesheet]')
42+
const styles = document.querySelectorAll('style')
43+
const { iframe } = this.$refs
44+
const { body, head } = iframe.contentDocument
45+
this.contents = this.$el.frag.filter(node => node !== iframe);
46+
[...links, ...styles].forEach(node => {
47+
const clone = node.cloneNode(true)
48+
head.appendChild(clone)
49+
})
50+
51+
this.contents.forEach(node => {
52+
body.appendChild(node)
53+
})
54+
55+
if (this.globalStyle) {
56+
const style = document.createElement('style')
57+
style.textContent = this.globalStyle
58+
head.appendChild(style)
59+
this.style = style
60+
}
61+
62+
this.watchLiveStyle(head)
63+
},
64+
methods: {
65+
watchLiveStyle (head) {
66+
this.liveStyle = document.createComment('')
67+
head.appendChild(this.liveStyle)
68+
69+
this.mo = new MutationObserver(mutations => {
70+
for (const mutation of mutations) {
71+
if (mutation.target === document.head) {
72+
const style = (this.liveSource = [...mutation.addedNodes].find(
73+
node => node.nodeName === 'STYLE' && node.dataset.cssscoper
74+
))
75+
if (style) {
76+
const liveStyle = style.cloneNode(true)
77+
head.replaceChild(liveStyle, this.liveStyle)
78+
this.liveStyle = liveStyle
79+
}
80+
} else if (mutation.target === this.liveSource) {
81+
this.liveStyle.textContent = this.liveSource.textContent
82+
}
83+
}
84+
})
85+
this.mo.observe(document.head, { childList: true })
86+
}
87+
}
88+
}
89+
</script>
90+
91+
<style lang="stylus" scoped>
92+
.one-iframe
93+
display block
94+
width 100%
95+
height 100%
96+
border none
97+
overflow auto
98+
</style>

components/OneLive.vue

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -68,14 +68,16 @@
6868
'live-preview-browser': browser
6969
}"
7070
>
71-
<v-live-preview
72-
class="editor-preview"
73-
:code="transformedCode"
74-
:requires="imports"
75-
:check-variable-availability="false"
76-
@success="dismissError"
77-
@error="handleError"
78-
/>
71+
<one-iframe global-style="body { margin: 0 !important; } body > article { margin: 24px 36px; } .veui-layout { min-width: auto !important; }">
72+
<v-live-preview
73+
class="editor-preview"
74+
:code="transformedCode"
75+
:requires="imports"
76+
:check-variable-availability="false"
77+
@success="dismissError"
78+
@error="handleError"
79+
/>
80+
</one-iframe>
7981
<transition name="editor-error">
8082
<veui-alert
8183
v-if="error"
@@ -113,6 +115,7 @@ import { getLocale } from '../common/i18n'
113115
import { play } from '../common/play'
114116
import { transformLessCode } from '../common/transform'
115117
import { loadPref, savePref } from '../common/util'
118+
import OneIframe from './OneIframe'
116119
117120
Vue.use(toast)
118121
@@ -158,7 +161,8 @@ export default {
158161
'v-splitpanes': Splitpanes,
159162
'v-pane': Pane,
160163
'v-monaco-editor': MonacoEditor,
161-
'v-live-preview': VueLivePreview
164+
'v-live-preview': VueLivePreview,
165+
OneIframe
162166
},
163167
directives: {
164168
tooltip

components/OneMenu.vue

Lines changed: 55 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -4,50 +4,48 @@
44
class="one-nav"
55
:class="{ expanded }"
66
>
7+
<header>
8+
<h2>VEUI</h2>
9+
<section class="desc">
10+
<a href="https://github.com/ecomfe/veui">
11+
<img
12+
alt="VEUI on GitHub"
13+
src="https://img.shields.io/github/stars/ecomfe/veui?label=stars&logo=github"
14+
height="20"
15+
>
16+
</a>
17+
<nuxt-link
18+
:class="{
19+
'locale-swith': true,
20+
disabled: altLocale.disabled,
21+
}"
22+
:to="altLocale.disabled ? '' : altLocale.to"
23+
>
24+
{{ altLocale.label }}
25+
</nuxt-link>
26+
</section>
27+
<section class="search">
28+
<one-search/>
29+
</section>
30+
<div
31+
class="toggle"
32+
@click="toggleMenu"
33+
>
34+
<veui-icon
35+
class="expanded-icon"
36+
name="chevron-left"
37+
/>
38+
<veui-icon
39+
class="collapsed-icon"
40+
name="hamburger"
41+
/>
42+
</div>
43+
</header>
744
<veui-menu
845
class="one-menu"
946
:items="menuItems"
1047
:expanded.sync="menuExpanded"
1148
>
12-
<template #before>
13-
<header>
14-
<h2>VEUI</h2>
15-
<section class="desc">
16-
<a href="https://github.com/ecomfe/veui">
17-
<img
18-
alt="VEUI on GitHub"
19-
src="https://img.shields.io/github/stars/ecomfe/veui?label=stars&logo=github"
20-
height="20"
21-
>
22-
</a>
23-
<nuxt-link
24-
:class="{
25-
'locale-swith': true,
26-
disabled: altLocale.disabled,
27-
}"
28-
:to="altLocale.disabled ? '' : altLocale.to"
29-
>
30-
{{ altLocale.label }}
31-
</nuxt-link>
32-
</section>
33-
<section class="search">
34-
<one-search/>
35-
</section>
36-
<div
37-
class="toggle"
38-
@click="toggleMenu"
39-
>
40-
<veui-icon
41-
class="expanded-icon"
42-
name="chevron-left"
43-
/>
44-
<veui-icon
45-
class="collapsed-icon"
46-
name="hamburger"
47-
/>
48-
</div>
49-
</header>
50-
</template>
5149
<template #item-label="{ label, sub }">
5250
{{ label }}<small>{{ sub }}</small>
5351
</template>
@@ -147,31 +145,14 @@ export default {
147145
top 0
148146
bottom 0
149147
left 0
148+
display flex
149+
flex-direction column
150150
width 280px
151151
z-index 1
152152
153-
.one-menu
154-
width 100%
155-
height 100%
156-
background-color #fff
157-
158-
& >>> .veui-menu-tree-wrapper
159-
display flex
160-
flex-direction column
161-
flex-grow 1
162-
height 100%
163-
overflow visible
164-
165-
.veui-menu-tree
166-
overflow auto
167-
168-
& >>> .DocSearch
169-
margin 0
170-
border-radius 6px
171-
font inherit
172-
173153
header
174154
padding 32px 20px 20px
155+
flex none
175156
176157
h2
177158
display flex
@@ -191,10 +172,6 @@ export default {
191172
img
192173
display block
193174
194-
small
195-
margin-left 8px
196-
opacity 0.7
197-
198175
.locale-swith
199176
display block
200177
margin-left 12px
@@ -215,6 +192,21 @@ export default {
215192
margin-right 12px
216193
flex-shrink 0
217194
195+
.one-menu
196+
flex 1 1 auto
197+
width 100%
198+
overflow auto
199+
background-color #fff
200+
201+
& >>> .DocSearch
202+
margin 0
203+
border-radius 6px
204+
font inherit
205+
206+
small
207+
margin-left 8px
208+
opacity 0.7
209+
218210
.toggle
219211
display none
220212

components/OneRepl.vue

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -121,9 +121,6 @@ Icon.register({
121121
flex 1 1 auto
122122
height calc(100% - 48px)
123123
124-
& >>> .live-preview
125-
padding 24px 36px
126-
127124
& >>> .VueLive-error
128125
display none
129126

one/docs/demo/layout/sticky.vue

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,7 @@
44
Header
55
</veui-header>
66
<veui-layout>
7-
<veui-sidebar
8-
sticky
9-
style="max-height: 320px;"
10-
>
7+
<veui-sidebar sticky>
118
<div class="center full">
129
Sidebar
1310
</div>

0 commit comments

Comments
 (0)