Skip to content

Commit 83391ad

Browse files
authored
Merge pull request #265 from Dan0xE/dev
feat: add darkmode to site and add theme prop
2 parents 33c7ed8 + 80e705c commit 83391ad

File tree

13 files changed

+260
-61
lines changed

13 files changed

+260
-61
lines changed

README.md

Lines changed: 27 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -106,31 +106,32 @@ plugins: [
106106

107107
## Props
108108

109-
| Property | Description | Type | Default |
110-
|---------------------------|---------------------------------------------------------------------------------|-----------------------------------| ------- |
111-
| data(v-model) | JSON data, support v-model when use editable | JSON object | - |
112-
| collapsedNodeLength | Objects or arrays which length is greater than this threshold will be collapsed | number | - |
113-
| deep | Paths greater than this depth will be collapsed | number | - |
114-
| showLength | Show the length when collapsed | boolean | false |
115-
| showLine | Show the line | boolean | true |
116-
| showLineNumber | Show the line number | boolean | false |
117-
| showIcon | Show the icon | boolean | false |
118-
| showDoubleQuotes | Show doublequotes on key | boolean | true |
119-
| virtual | Use virtual scroll | boolean | false |
120-
| height | The height of list when using virtual | number | 400 |
121-
| itemHeight | The height of node when using virtual | number | 20 |
122-
| selectedValue(v-model) | Selected data path | string, array | - |
123-
| rootPath | Root data path | string | `root` |
124-
| nodeSelectable | Defines whether a node supports selection | (node) => boolean | - |
125-
| selectableType | Support path select, default none | `multiple` \| `single` | - |
126-
| showSelectController | Show the select controller | boolean | false |
127-
| selectOnClickNode | Trigger select when click node | boolean | true |
128-
| highlightSelectedNode | Support highlighting selected nodes | boolean | true |
129-
| collapsedOnClickBrackets | Support click brackets to collapse | boolean | true |
130-
| renderNodeKey | render node key, or use slot #renderNodeKey | ({ node, defaultKey }) => vNode | - |
131-
| renderNodeValue | render node value, or use slot #renderNodeValue | ({ node, defaultValue }) => vNode | - |
132-
| editable | Support editable | boolean | false |
133-
| editableTrigger | Trigger | `click` \| `dblclick` | `click` |
109+
| Property | Description | Type | Default |
110+
| ------------------------ | ----------------------------------------------------------------------------------------------------------------------- | --------------------------------- | ------- |
111+
| data(v-model) | JSON data, support v-model when use editable | JSON object | - |
112+
| collapsedNodeLength | Objects or arrays which length is greater than this threshold will be collapsed | number | - |
113+
| deep | Paths greater than this depth will be collapsed | number | - |
114+
| showLength | Show the length when collapsed | boolean | false |
115+
| showLine | Show the line | boolean | true |
116+
| showLineNumber | Show the line number | boolean | false |
117+
| showIcon | Show the icon | boolean | false |
118+
| showDoubleQuotes | Show doublequotes on key | boolean | true |
119+
| virtual | Use virtual scroll | boolean | false |
120+
| height | The height of list when using virtual | number | 400 |
121+
| itemHeight | The height of node when using virtual | number | 20 |
122+
| selectedValue(v-model) | Selected data path | string, array | - |
123+
| rootPath | Root data path | string | `root` |
124+
| nodeSelectable | Defines whether a node supports selection | (node) => boolean | - |
125+
| selectableType | Support path select, default none | `multiple` \| `single` | - |
126+
| showSelectController | Show the select controller | boolean | false |
127+
| selectOnClickNode | Trigger select when click node | boolean | true |
128+
| highlightSelectedNode | Support highlighting selected nodes | boolean | true |
129+
| collapsedOnClickBrackets | Support click brackets to collapse | boolean | true |
130+
| renderNodeKey | render node key, or use slot #renderNodeKey | ({ node, defaultKey }) => vNode | - |
131+
| renderNodeValue | render node value, or use slot #renderNodeValue | ({ node, defaultValue }) => vNode | - |
132+
| editable | Support editable | boolean | false |
133+
| editableTrigger | Trigger | `click` \| `dblclick` | `click` |
134+
| theme | Sets the theme of the component. Options are 'light' or 'dark', with dark mode enhancing visibility on dark backgrounds | `'light' \| 'dark'` | `light` |
134135

135136
## Events
136137

@@ -145,7 +146,7 @@ plugins: [
145146

146147
| Slot Name | Description | Parameters |
147148
| --------------- | ----------------- | ---------------------- |
148-
| renderNodeKey | render node key | { node, defaultKey } |
149+
| renderNodeKey | render node key | { node, defaultKey } |
149150
| renderNodeValue | render node value | { node, defaultValue } |
150151

151152
## Contributors

example/App.tsx

Lines changed: 42 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1-
import { defineComponent, reactive } from 'vue';
1+
import { defineComponent, reactive, provide, onMounted, watch } from 'vue';
22
import Basic from './Basic.vue';
33
import VirtualList from './VirtualList.vue';
44
import SelectControl from './SelectControl.vue';
55
import Editable from './Editable.vue';
66
// import Tsx from './Tsx';
77
import './styles.less';
8+
import { MoonIcon, SunIcon } from './Icons';
89

910
const list = [
1011
{
@@ -41,24 +42,48 @@ export default defineComponent({
4142
opened: [list[0].key],
4243
});
4344

45+
const globalDarkModeState = reactive({
46+
isDarkMode: window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches,
47+
});
48+
49+
provide('darkModeState', globalDarkModeState);
50+
4451
const onActiveChange = (key: string) => {
4552
state.activeKey = key;
4653
if (!state.opened.includes(key)) {
4754
state.opened.push(key);
4855
}
4956
};
5057

58+
const toggleDarkMode = () => {
59+
globalDarkModeState.isDarkMode = !globalDarkModeState.isDarkMode;
60+
};
61+
62+
onMounted(() => {
63+
document.body.classList.toggle('dark-mode', globalDarkModeState.isDarkMode);
64+
});
65+
66+
watch(
67+
() => globalDarkModeState.isDarkMode,
68+
newVal => {
69+
document.body.classList.toggle('dark-mode', newVal);
70+
},
71+
{ immediate: true },
72+
);
73+
5174
return {
5275
state,
5376
onActiveChange,
77+
toggleDarkMode,
78+
globalDarkModeState,
5479
};
5580
},
5681

5782
render() {
58-
const { state, onActiveChange } = this;
83+
const { state, onActiveChange, toggleDarkMode, globalDarkModeState } = this;
5984

6085
return (
61-
<div class="example">
86+
<div class={`example ${state.isDarkMode ? 'dark-mode' : ''}`}>
6287
<h1>Vue Json Pretty</h1>
6388
<p>
6489
Welcome to the demo space of Vue Json Pretty, here we provide the following different
@@ -67,15 +92,20 @@ export default defineComponent({
6792

6893
<div class="tabs">
6994
<div class="tabs-header">
70-
{list.map(({ title, key }) => (
71-
<div
72-
key={key}
73-
class={`tabs-header-item ${key === state.activeKey ? 'is-active' : ''}`}
74-
onClick={() => onActiveChange(key)}
75-
>
76-
{title}
77-
</div>
78-
))}
95+
<div class="tabs-items-container">
96+
{list.map(({ title, key }) => (
97+
<div
98+
key={key}
99+
class={`tabs-header-item ${key === state.activeKey ? 'is-active' : ''}`}
100+
onClick={() => onActiveChange(key)}
101+
>
102+
{title}
103+
</div>
104+
))}
105+
</div>
106+
<div class="dark-mode-toggle" onClick={toggleDarkMode}>
107+
{globalDarkModeState.isDarkMode ? <SunIcon /> : <MoonIcon />}
108+
</div>
79109
</div>
80110

81111
<div class="tabs-content">

example/Basic.vue

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<div class="example-box">
33
<div class="block">
44
<h3>JSON:</h3>
5-
<textarea v-model="state.val" />
5+
<textarea :class="{ 'dark-textarea': globalDarkModeState }" v-model="state.val"></textarea>
66

77
<h3>Options:</h3>
88
<div class="options">
@@ -46,6 +46,13 @@
4646
<label>setPathCollapsible</label>
4747
<input v-model="state.setPathCollapsible" type="checkbox" />
4848
</div>
49+
<div>
50+
<label>theme</label>
51+
<select v-model="localDarkMode">
52+
<option value="light">light</option>
53+
<option value="dark">dark</option>
54+
</select>
55+
</div>
4956
</div>
5057

5158
<h3>Slots:</h3>
@@ -63,6 +70,7 @@
6370
<div class="block">
6471
<h3>vue-json-pretty:</h3>
6572
<vue-json-pretty
73+
:theme="localDarkMode"
6674
:data="state.data"
6775
:deep="state.deep"
6876
:path-collapsible="state.setPathCollapsible ? pathCollapsible : undefined"
@@ -95,6 +103,7 @@
95103

96104
<script>
97105
import { defineComponent, reactive, watch } from 'vue';
106+
import { useDarkMode } from './useDarkMode';
98107
import VueJsonPretty from 'src';
99108
100109
const defaultData = {
@@ -147,6 +156,8 @@ export default defineComponent({
147156
showKeyValueSpace: true,
148157
});
149158
159+
const { localDarkMode, toggleLocalDarkMode, globalDarkModeState } = useDarkMode();
160+
150161
const pathCollapsible = node => {
151162
return node.key === 'members';
152163
};
@@ -165,6 +176,9 @@ export default defineComponent({
165176
return {
166177
state,
167178
pathCollapsible,
179+
localDarkMode,
180+
toggleLocalDarkMode,
181+
globalDarkModeState,
168182
};
169183
},
170184
});

example/Editable.vue

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<div class="example-box">
33
<div class="block">
44
<h3>JSON:</h3>
5-
<textarea v-model="state.val" />
5+
<textarea :class="{ 'dark-textarea': globalDarkModeState }" v-model="state.val"></textarea>
66

77
<h3>Options:</h3>
88
<div class="options">
@@ -34,11 +34,19 @@
3434
</select>
3535
</div>
3636
</div>
37+
<div>
38+
<label>theme</label>
39+
<select v-model="localDarkMode">
40+
<option value="light">light</option>
41+
<option value="dark">dark</option>
42+
</select>
43+
</div>
3744
</div>
3845
<div class="block">
3946
<h3>vue-json-pretty:</h3>
4047
<vue-json-pretty
4148
v-model:data="state.data"
49+
:theme="localDarkMode"
4250
:deep="state.deep"
4351
:show-double-quotes="true"
4452
:show-line="state.showLine"
@@ -53,6 +61,7 @@
5361
<script>
5462
import { defineComponent, reactive, watch } from 'vue';
5563
import VueJsonPretty from 'src';
64+
import { useDarkMode } from './useDarkMode';
5665
5766
const defaultData = {
5867
status: 200,
@@ -98,6 +107,8 @@ export default defineComponent({
98107
deep: 3,
99108
});
100109
110+
const { localDarkMode, toggleLocalDarkMode, globalDarkModeState } = useDarkMode();
111+
101112
watch(
102113
() => state.val,
103114
newVal => {
@@ -122,7 +133,11 @@ export default defineComponent({
122133
123134
return {
124135
state,
136+
localDarkMode,
137+
toggleLocalDarkMode,
138+
globalDarkModeState,
125139
};
126140
},
127141
});
128142
</script>
143+
./useDarkMode

example/Icons.tsx

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
export const SunIcon = () => (
2+
<svg
3+
xmlns="http://www.w3.org/2000/svg"
4+
width="24"
5+
height="24"
6+
viewBox="0 0 24 24"
7+
fill="none"
8+
stroke="currentColor"
9+
strokeWidth="2"
10+
strokeLinecap="round"
11+
strokeLinejoin="round"
12+
>
13+
<circle cx="12" cy="12" r="5"></circle>
14+
<line x1="12" y1="1" x2="12" y2="3"></line>
15+
<line x1="12" y1="21" x2="12" y2="23"></line>
16+
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
17+
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
18+
<line x1="1" y1="12" x2="3" y2="12"></line>
19+
<line x1="21" y1="12" x2="23" y2="12"></line>
20+
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
21+
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
22+
</svg>
23+
);
24+
25+
export const MoonIcon = () => (
26+
<svg
27+
xmlns="http://www.w3.org/2000/svg"
28+
width="24"
29+
height="24"
30+
viewBox="0 0 24 24"
31+
fill="none"
32+
stroke="currentColor"
33+
strokeWidth="2"
34+
strokeLinecap="round"
35+
strokeLinejoin="round"
36+
>
37+
<path d="M21 12.79A9 9 0 0112.21 3C11.66 3 11.11 3.05 10.58 3.15A9 9 0 1021 12.79z"></path>
38+
</svg>
39+
);

example/SelectControl.vue

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<div class="example-box">
33
<div class="block">
44
<h3>JSON:</h3>
5-
<textarea v-model="state.val" />
5+
<textarea :class="{ 'dark-textarea': globalDarkModeState }" v-model="state.val"></textarea>
66

77
<h3>Options:</h3>
88
<div class="options">
@@ -57,6 +57,13 @@
5757
<option :value="4">4</option>
5858
</select>
5959
</div>
60+
<div>
61+
<label>theme</label>
62+
<select v-model="localDarkMode">
63+
<option value="light">light</option>
64+
<option value="dark">dark</option>
65+
</select>
66+
</div>
6067
</div>
6168
<h3>v-model:selectedValue:</h3>
6269
<div>{{ state.selectedValue }}</div>
@@ -68,6 +75,7 @@
6875
<vue-json-pretty
6976
v-if="state.renderOK"
7077
v-model:selectedValue="state.selectedValue"
78+
:theme="localDarkMode"
7179
:data="state.data"
7280
:root-path="state.rootPath"
7381
:deep="state.deep"
@@ -94,6 +102,7 @@
94102
<script>
95103
import { defineComponent, reactive, watch, nextTick } from 'vue';
96104
import VueJsonPretty from 'src';
105+
import { useDarkMode } from './useDarkMode';
97106
98107
const defaultData = {
99108
status: 200,
@@ -148,6 +157,8 @@ export default defineComponent({
148157
showIcon: false,
149158
});
150159
160+
const { localDarkMode, toggleLocalDarkMode, globalDarkModeState } = useDarkMode();
161+
151162
const handleNodeClick = node => {
152163
state.node = node;
153164
};
@@ -186,6 +197,9 @@ export default defineComponent({
186197
state,
187198
handleNodeClick,
188199
handleAll,
200+
localDarkMode,
201+
toggleLocalDarkMode,
202+
globalDarkModeState,
189203
};
190204
},
191205
});

0 commit comments

Comments
 (0)