Skip to content

Commit ffe3d46

Browse files
authored
Merge pull request #9 from to0simple/addcodebox
feat(codebox): add codebox
2 parents 3e4ba2c + 412c56a commit ffe3d46

File tree

8 files changed

+310
-10
lines changed

8 files changed

+310
-10
lines changed

devui/button/demo/button-demo.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,14 @@ import { defineComponent } from 'vue'
22
import CodeBox from '../../shared/devui-codebox/devui-codebox'
33
import ButtonPrimary from './primary/primary'
44
import ButtonCommon from './common/common'
5+
import PrimaryCode from './primary/primary.tsx?raw'
6+
import CommonCode from './common/common.tsx?raw'
57

68
export default defineComponent({
79
name: 'd-button-demo',
810
setup() {
9-
const primarySource = {};
10-
const commonSource = {};
11-
11+
const primarySource: any[] = [{title: 'TSX', language: 'TSX', code: PrimaryCode}];
12+
const commonSource: any[] = [{title: 'TSX', language: 'TSX', code: CommonCode}];
1213
return () => {
1314
return <div class="demo-container">
1415
<div class="demo-example">
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { defineComponent } from 'vue';
2+
export default defineComponent({
3+
setup() {
4+
return () => {
5+
return (
6+
<svg width="16px" height="16px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg">
7+
<path
8+
d="M1003.46892,474.447037 L750.118678,246.329458 C730.418156,228.591027 700.067888,230.181618 682.329458,249.88214 L682.329458,249.88214 L682.329458,249.88214 C664.591027,269.582663 666.181618,299.932931 685.88214,317.671361 L902.31217,512.545835 L686.384104,706.968338 C666.683581,724.706768 665.092991,755.057036 682.831421,774.757559 C700.569852,794.458082 730.92012,796.048672 750.620642,778.310241 L1006.26246,548.129313 C1025.96298,530.390883 1027.55357,500.040615 1009.81514,480.340092 C1007.84473,478.151722 1005.71869,476.186813 1003.46892,474.447037 Z M120.832433,512.545835 L337.262462,317.671361 C356.962985,299.932931 358.553575,269.582663 340.815145,249.88214 L340.815145,249.88214 L340.815145,249.88214 C323.076714,230.181618 292.726447,228.591027 273.025924,246.329458 L19.6756857,474.447037 C17.4259125,476.186813 15.2998752,478.151722 13.3294577,480.340092 L13.3294577,480.340092 L13.3294577,480.340092 C-4.40897251,500.040615 -2.81838236,530.390883 16.8821402,548.129313 L272.52396,778.310241 C292.224483,796.048672 322.574751,794.458082 340.313181,774.757559 C358.051611,755.057036 356.461021,724.706768 336.760498,706.968338 L120.832433,512.545835 Z"
9+
id="Combined-Shape"
10+
></path>
11+
</svg>
12+
)
13+
}
14+
}
15+
})
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { defineComponent } from 'vue';
2+
export default defineComponent({
3+
setup() {
4+
return () => {
5+
return (
6+
<svg xmlns="http://www.w3.org/2000/svg" width="16px" height="16px" viewBox="0 0 16 16" version="1.1">
7+
<defs>
8+
<polygon
9+
id="path-1"
10+
points="6.53553391 9.77817459 12.1923882 4.12132034 13.6066017 5.53553391 6.53553391 12.6066017 3 9.07106781 4.41421356 7.65685425 6.53553391 9.77817459"
11+
/>
12+
</defs>
13+
<g id="status/whiteBG/correct" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
14+
<mask id="mask-2" fill="white">
15+
<use xlinkHref="#path-1" />
16+
</mask>
17+
<use id="Mask" fill="#3DCCA6" xlinkHref="#path-1" />
18+
</g>
19+
</svg>
20+
)
21+
}
22+
}
23+
})
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { defineComponent } from 'vue';
2+
export default defineComponent({
3+
setup() {
4+
return () => {
5+
return (
6+
<svg class="devui-code-copy" version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
7+
<path
8+
d="M10 4v-4h-7l-3 3v9h6v4h10v-12h-6zM3 1.414v1.586h-1.586l1.586-1.586zM1 11v-7h3v-3h5v3l-3 3v4h-5zM9 5.414v1.586h-1.586l1.586-1.586zM15 15h-8v-7h3v-3h5v10z"
9+
></path>
10+
</svg>
11+
)
12+
}
13+
}
14+
})
Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
@import '../../style/theme/color';
2+
@import '../../style/core/font';
3+
4+
.code-box {
5+
border: 1px solid $devui-line;
6+
border-radius: 4px;
7+
display: inline-block;
8+
width: 100%;
9+
position: relative;
10+
margin: 4px 0;
11+
transition: all 0.2s;
12+
}
13+
14+
.devui-code-copy {
15+
fill: $devui-text;
16+
}
17+
18+
.code-box-demo {
19+
border-bottom: 1px solid $devui-dividing-line;
20+
padding: 42px 20px 50px;
21+
}
22+
23+
.code-box-meta.markdown {
24+
position: relative;
25+
padding: 10px 40px;
26+
border-radius: 0 0 4px 4px;
27+
transition: background-color 0.4s;
28+
width: 100%;
29+
font-size: $devui-font-size;
30+
margin-bottom: 0;
31+
overflow-x: unset;
32+
}
33+
34+
.code-box.expand .code-box-meta {
35+
border-radius: 0;
36+
border-bottom: 1px dashed $devui-dividing-line;
37+
}
38+
39+
.code-box-title {
40+
position: absolute;
41+
top: -14px;
42+
padding: 1px 8px;
43+
color: #777777;
44+
border-radius: 4px 4px 0 0;
45+
background: $devui-base-bg;
46+
transition: background-color 0.4s;
47+
}
48+
49+
.code-box-title > a {
50+
color: rgba(0, 0, 0, 0.65);
51+
font-size: $devui-font-size-card-title;
52+
font-weight: 500;
53+
text-decoration: none;
54+
}
55+
56+
.code-box .collapse {
57+
display: block; /* .collapse conflick with bootstrap */
58+
position: absolute;
59+
left: 15px;
60+
// background: $devui-block;
61+
top: -9px;
62+
cursor: pointer;
63+
width: 16px;
64+
height: 16px;
65+
line-height: 16px;
66+
opacity: 0.55;
67+
text-align: center;
68+
transition: all 0.3s;
69+
-webkit-user-select: none;
70+
-moz-user-select: none;
71+
-ms-user-select: none;
72+
user-select: none;
73+
74+
& > svg > path {
75+
fill: $devui-text;
76+
}
77+
}
78+
79+
.dark-mode .code-box .collapse {
80+
opacity: 1;
81+
}
82+
83+
.code-box .highlight-wrapper {
84+
display: none;
85+
overflow: auto;
86+
border-radius: 0 0 4px 4px;
87+
}
88+
89+
.code-box .highlight-wrapper-expand {
90+
display: block;
91+
}
92+
93+
.code-box .highlight {
94+
padding: 5px;
95+
position: relative;
96+
}
97+
98+
.code-box-actions {
99+
position: absolute;
100+
top: 10px;
101+
right: 12px;
102+
text-align: right;
103+
cursor: pointer;
104+
}
105+
106+
.code-box-code-copy:hover {
107+
color: #108ee9;
108+
-webkit-transform: scale(1.2);
109+
transform: scale(1.2);
110+
}
111+
112+
.code-box-code-copy {
113+
font-size: $devui-font-size-card-title;
114+
cursor: pointer;
115+
color: #222222;
116+
transition: all 0.24s;
117+
background: $devui-base-bg;
118+
width: 20px;
119+
height: 20px;
120+
line-height: 20px;
121+
text-align: center;
122+
border-radius: 20px;
123+
opacity: 0;
124+
}
125+
126+
.code-box .highlight pre {
127+
margin: 0;
128+
padding: 0;
129+
}
130+
131+
.code-box pre {
132+
margin: 0;
133+
width: auto;
134+
border: none;
135+
margin-top: 10px;
136+
}
137+
138+
.code-box pre code {
139+
border: none;
140+
}
141+
142+
.highlight-wrapper:hover .code-box-code-copy,
143+
.highlight-wrapper:hover .code-box-codepen,
144+
.highlight-wrapper:hover .code-box-riddle {
145+
opacity: 0.66;
146+
}
147+
148+
.code-box.expand .collapse {
149+
-webkit-transform: rotate(90deg);
150+
transform: rotate(90deg);
151+
}
Lines changed: 90 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,101 @@
1-
import { defineComponent } from 'vue'
1+
import { defineComponent, ref } from 'vue'
2+
import { DevuiSourceData } from './devui-source-data';
3+
import CollapseIcon from './codebox-collapse-icon';
4+
import CopyIcon from './codebox-copy-icon';
5+
import CopiedIcon from './codebox-copied-icon';
6+
import DevuiTabs from '../../tabs/tabs';
7+
import DevuiTab from '../../tabs/tab';
8+
import DevuiHighlight from '../devui-highlight/devui-highlight';
9+
10+
import './devui-codebox.scss';
211

312
export default defineComponent({
413
name: 'd-codebox',
514
props: {
615
id: String,
7-
sourceData: Object
16+
sourceData: {
17+
type: Array as () => DevuiSourceData[],
18+
default: []
19+
}
820
},
921
setup(props, ctx) {
22+
const sourceData = props.sourceData;
23+
const expanded = ref(false);
24+
const _copied = ref(false);
25+
let codeTabID = 'TSX';
26+
let componentCode: Array<any>;
27+
28+
const toggleCode = () => {
29+
expanded.value = !expanded.value;
30+
}
31+
32+
const copyCode = (code: string) => {
33+
copy(code).then(() => {
34+
_copied.value = true;
35+
setTimeout(() => {
36+
_copied.value = false;
37+
}, 1000)
38+
})
39+
}
40+
const copy = (value: string): Promise<string> => {
41+
const promise = new Promise<string>((resolve, reject): void => {
42+
let copyTextArea = null as unknown as HTMLTextAreaElement;
43+
try {
44+
copyTextArea = document.createElement('textarea');
45+
copyTextArea.style.height = '0px';
46+
copyTextArea.style.opacity = '0';
47+
copyTextArea.style.width = '0px';
48+
document.body.appendChild(copyTextArea);
49+
copyTextArea.value = value;
50+
copyTextArea.select();
51+
document.execCommand('copy');
52+
resolve(value);
53+
} finally {
54+
if (copyTextArea && copyTextArea.parentNode) {
55+
copyTextArea.parentNode.removeChild(copyTextArea);
56+
}
57+
}
58+
})
59+
return (promise);
60+
}
61+
1062
return () => {
11-
return <div>
12-
devui-codebox
13-
{ctx.slots.default?.()}
14-
</div>
63+
return (
64+
<section class={{'code-box': true, 'expand': expanded.value}}>
65+
<section class='code-box-demo'>
66+
<div>
67+
{ctx.slots.default && ctx.slots.default()}
68+
</div>
69+
</section>
70+
<section class="code-box-meta markdown">
71+
{/* TODO: 待添加tootltip */}
72+
<span class="collapse" onClick={toggleCode}>
73+
<CollapseIcon></CollapseIcon>
74+
</span>
75+
</section>
76+
<section class={{ 'highlight-wrapper': true, 'highlight-wrapper-expand': expanded.value }}>
77+
<div style="padding: 0 20px">
78+
{/* TODO: 待完善tabs */}
79+
<DevuiTabs>
80+
{sourceData.map(item => {
81+
return (
82+
<DevuiTab>
83+
<div class="highlight">
84+
<div class="code-box-actions">
85+
<span onClick={() => copyCode(item.code.default || item.code)}>
86+
{ !_copied.value ? <CopyIcon></CopyIcon> : <CopiedIcon></CopiedIcon>}
87+
</span>
88+
</div>
89+
<DevuiHighlight code={item.code.default || item.code} language={item.language}></DevuiHighlight>
90+
</div>
91+
</DevuiTab>
92+
)
93+
})}
94+
</DevuiTabs>
95+
</div>
96+
</section>
97+
</section>
98+
)
1599
}
16100
}
17101
})
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
export interface DevuiSourceData {
2+
title?: string;
3+
language?: string;
4+
code?: any
5+
}

devui/shared/devui-highlight/devui-highlight.tsx

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,17 @@ import { defineComponent } from 'vue'
33
export default defineComponent({
44
name: 'd-highlight',
55
props: {
6+
code: String,
7+
language: String
68
},
79
setup(props, ctx) {
810
return () => {
9-
return <div>devui-highlight</div>
11+
return (
12+
<pre class={`language-${props.language}`}>
13+
{/* 暂做处理避免tsx语法被解析为html标签 */}
14+
<code innerHTML={props.code?.replace(/(<)/g, '&lt;')}></code>
15+
</pre>
16+
)
1017
}
1118
}
1219
})

0 commit comments

Comments
 (0)