@appscode/design-system 1.0.43-alpha.150 → 1.0.43-alpha.153
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/components/_ac-input.scss +8 -0
- package/package.json +1 -1
- package/vue-components/v2/navbar/User.vue +46 -22
- package/vue-components/v3/editor/MonacoEditor.vue +56 -49
- package/vue-components/v3/form/Form.vue +63 -0
- package/vue-components/v3/form-fields/Input.vue +10 -10
- package/vue-components/v3/modals/DeleteConfirmationModal.vue +83 -0
- package/vue-components/v3/navbar/ThemeMode.vue +21 -26
|
@@ -714,6 +714,14 @@ input#captcha {
|
|
|
714
714
|
}
|
|
715
715
|
}
|
|
716
716
|
|
|
717
|
+
.ac-single-switch.is-small .switch[type="checkbox"] + label,
|
|
718
|
+
.buttons.are-small
|
|
719
|
+
.ac-single-switch.button.ac-button
|
|
720
|
+
.switch[type="checkbox"]
|
|
721
|
+
+ label {
|
|
722
|
+
height: 19px;
|
|
723
|
+
}
|
|
724
|
+
|
|
717
725
|
// transparent input
|
|
718
726
|
.transparent-input {
|
|
719
727
|
display: flex;
|
package/package.json
CHANGED
|
@@ -8,14 +8,27 @@
|
|
|
8
8
|
</div>
|
|
9
9
|
</button>
|
|
10
10
|
<navbar-item-content class="navbar-dropdown-wrapper">
|
|
11
|
-
<div
|
|
11
|
+
<div
|
|
12
|
+
v-if="user.username"
|
|
13
|
+
class="user-profile-wrapper"
|
|
14
|
+
@mouseleave="onMouseLeave()"
|
|
15
|
+
>
|
|
12
16
|
<div class="profile-area">
|
|
13
17
|
<div class="profile-photo">
|
|
14
|
-
<img
|
|
18
|
+
<img
|
|
19
|
+
:src="user.avatar_url"
|
|
20
|
+
alt="User Photo"
|
|
21
|
+
class="width-50 height-50"
|
|
22
|
+
/>
|
|
15
23
|
<button class="camera-icon"></button>
|
|
16
24
|
</div>
|
|
17
25
|
<div class="profile-info" style="width: calc(100% - 60px);">
|
|
18
|
-
<
|
|
26
|
+
<a
|
|
27
|
+
:href="`/${user.username}`"
|
|
28
|
+
:title="user.username.toUpperCase()"
|
|
29
|
+
class="line-break-anywhere is-ellipsis-1"
|
|
30
|
+
>{{ user.username.toUpperCase() }}</a
|
|
31
|
+
>
|
|
19
32
|
<a :href="`mailto:${user.email}`"> {{ user.email }}</a>
|
|
20
33
|
</div>
|
|
21
34
|
</div>
|
|
@@ -26,8 +39,13 @@
|
|
|
26
39
|
<li v-if="user.is_admin" key="site-admin">
|
|
27
40
|
<a :href="`${serverDomain}/admin`">Site Administration</a>
|
|
28
41
|
</li>
|
|
29
|
-
<li
|
|
30
|
-
|
|
42
|
+
<li
|
|
43
|
+
v-if="showAccountSwitcher"
|
|
44
|
+
:class="`is-${dropDownStatus}`"
|
|
45
|
+
key="switcher"
|
|
46
|
+
>
|
|
47
|
+
<a
|
|
48
|
+
class="
|
|
31
49
|
ac-dropdown-button
|
|
32
50
|
is-fullwidth
|
|
33
51
|
is-flex
|
|
@@ -39,13 +57,15 @@
|
|
|
39
57
|
<span>Switch Account</span>
|
|
40
58
|
<span
|
|
41
59
|
><i
|
|
42
|
-
:class="
|
|
43
|
-
dropDownStatus === 'open' ? 'up' : 'down'
|
|
44
|
-
|
|
60
|
+
:class="
|
|
61
|
+
`fa fa-angle-${dropDownStatus === 'open' ? 'up' : 'down'}`
|
|
62
|
+
"
|
|
45
63
|
></i
|
|
46
64
|
></span>
|
|
47
65
|
</a>
|
|
48
|
-
<transition-group
|
|
66
|
+
<transition-group
|
|
67
|
+
name="list"
|
|
68
|
+
tag="ul"
|
|
49
69
|
class="ac-vscrollbar"
|
|
50
70
|
ref="dropdownItems"
|
|
51
71
|
:style="{ maxHeight: dropDownSectionHeight }"
|
|
@@ -75,7 +95,11 @@
|
|
|
75
95
|
"
|
|
76
96
|
>
|
|
77
97
|
<div class="org-info">
|
|
78
|
-
<strong
|
|
98
|
+
<strong
|
|
99
|
+
:title="org.username"
|
|
100
|
+
class="line-break-anywhere is-ellipsis-1"
|
|
101
|
+
>{{ org.username }}</strong
|
|
102
|
+
>
|
|
79
103
|
<p>
|
|
80
104
|
{{
|
|
81
105
|
org.isPersonalAccount
|
|
@@ -118,32 +142,32 @@ export default {
|
|
|
118
142
|
// active user info
|
|
119
143
|
user: {
|
|
120
144
|
type: Object,
|
|
121
|
-
default: () => ({})
|
|
145
|
+
default: () => ({})
|
|
122
146
|
},
|
|
123
147
|
serverDomain: {
|
|
124
148
|
type: String,
|
|
125
|
-
default: ""
|
|
149
|
+
default: ""
|
|
126
150
|
},
|
|
127
151
|
showAccountSwitcher: {
|
|
128
152
|
type: Boolean,
|
|
129
|
-
default: false
|
|
153
|
+
default: false
|
|
130
154
|
},
|
|
131
155
|
// all available organization list including personal account
|
|
132
156
|
organizations: {
|
|
133
157
|
type: Array,
|
|
134
|
-
default: () => []
|
|
135
|
-
}
|
|
158
|
+
default: () => []
|
|
159
|
+
}
|
|
136
160
|
},
|
|
137
161
|
|
|
138
162
|
components: {
|
|
139
163
|
NavbarItem: () => import("./NavbarItem.vue"),
|
|
140
|
-
NavbarItemContent: () => import("./NavbarItemContent.vue")
|
|
164
|
+
NavbarItemContent: () => import("./NavbarItemContent.vue")
|
|
141
165
|
},
|
|
142
166
|
|
|
143
167
|
computed: {
|
|
144
168
|
formattedOrganizations() {
|
|
145
169
|
let activeUser;
|
|
146
|
-
const filteredList = this.organizations.filter(
|
|
170
|
+
const filteredList = this.organizations.filter(item => {
|
|
147
171
|
if (item.username === this.user.username) {
|
|
148
172
|
activeUser = item;
|
|
149
173
|
} else {
|
|
@@ -155,13 +179,13 @@ export default {
|
|
|
155
179
|
filteredList.unshift(activeUser);
|
|
156
180
|
|
|
157
181
|
return filteredList || [];
|
|
158
|
-
}
|
|
182
|
+
}
|
|
159
183
|
},
|
|
160
184
|
|
|
161
185
|
data() {
|
|
162
186
|
return {
|
|
163
187
|
dropDownStatus: "close",
|
|
164
|
-
dropDownSectionHeight: null
|
|
188
|
+
dropDownSectionHeight: null
|
|
165
189
|
};
|
|
166
190
|
},
|
|
167
191
|
|
|
@@ -194,9 +218,9 @@ export default {
|
|
|
194
218
|
} else {
|
|
195
219
|
this.dropDownSectionHeight = null;
|
|
196
220
|
}
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
}
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
200
224
|
};
|
|
201
225
|
</script>
|
|
202
226
|
<style lang="scss" scoped>
|
|
@@ -3,69 +3,76 @@
|
|
|
3
3
|
</template>
|
|
4
4
|
|
|
5
5
|
<script>
|
|
6
|
-
import { defineComponent, computed, toRefs } from
|
|
7
|
-
import * as monaco from
|
|
6
|
+
import { defineComponent, computed, toRefs } from "vue";
|
|
7
|
+
import * as monaco from "monaco-editor";
|
|
8
8
|
|
|
9
9
|
export default defineComponent({
|
|
10
10
|
name: "MonacoEditor",
|
|
11
11
|
props: {
|
|
12
12
|
diffEditor: { type: Boolean, default: false },
|
|
13
|
-
width: {type: [String, Number], default:
|
|
14
|
-
height: {type: [String, Number], default:
|
|
15
|
-
original: String,
|
|
13
|
+
width: { type: [String, Number], default: "100%" },
|
|
14
|
+
height: { type: [String, Number], default: "100%" },
|
|
15
|
+
original: String,
|
|
16
16
|
value: String,
|
|
17
|
-
language: {type: String, default:
|
|
18
|
-
theme: {type: String, default:
|
|
19
|
-
options: {
|
|
17
|
+
language: { type: String, default: "javascript" },
|
|
18
|
+
theme: { type: String, default: "vs" },
|
|
19
|
+
options: {
|
|
20
|
+
type: Object,
|
|
21
|
+
default() {
|
|
22
|
+
return {};
|
|
23
|
+
},
|
|
24
|
+
},
|
|
20
25
|
},
|
|
21
|
-
emits: [
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
26
|
+
emits: ["editorWillMount", "editorDidMount", "change"],
|
|
27
|
+
setup(props) {
|
|
28
|
+
const { width, height } = toRefs(props);
|
|
29
|
+
const style = computed(() => {
|
|
30
|
+
const fixedWidth = width.value.toString().includes("%")
|
|
31
|
+
? width.value
|
|
32
|
+
: `${width.value}px`;
|
|
33
|
+
const fixedHeight = height.value.toString().includes("%")
|
|
34
|
+
? height.value
|
|
35
|
+
: `${height.value}px`;
|
|
31
36
|
return {
|
|
32
37
|
width: fixedWidth,
|
|
33
38
|
height: fixedHeight,
|
|
34
|
-
|
|
35
|
-
}
|
|
36
|
-
})
|
|
39
|
+
"text-align": "left",
|
|
40
|
+
};
|
|
41
|
+
});
|
|
37
42
|
return {
|
|
38
|
-
style
|
|
39
|
-
}
|
|
43
|
+
style,
|
|
44
|
+
};
|
|
40
45
|
},
|
|
41
46
|
mounted() {
|
|
42
|
-
this.initMonaco()
|
|
47
|
+
this.initMonaco();
|
|
43
48
|
},
|
|
44
|
-
|
|
49
|
+
beforeUnmount() {
|
|
45
50
|
this.editor && this.editor.dispose();
|
|
46
51
|
},
|
|
47
52
|
methods: {
|
|
48
|
-
initMonaco(){
|
|
49
|
-
this.$emit(
|
|
53
|
+
initMonaco() {
|
|
54
|
+
this.$emit("editorWillMount", this.monaco);
|
|
50
55
|
const { value, language, theme, options } = this;
|
|
51
|
-
this.editor = monaco.editor[
|
|
56
|
+
this.editor = monaco.editor[
|
|
57
|
+
this.diffEditor ? "createDiffEditor" : "create"
|
|
58
|
+
](this.$el, {
|
|
52
59
|
value: value,
|
|
53
60
|
language: language,
|
|
54
61
|
theme: theme,
|
|
55
|
-
...options
|
|
62
|
+
...options,
|
|
56
63
|
});
|
|
57
64
|
this.diffEditor && this._setModel(this.value, this.original);
|
|
58
65
|
|
|
59
66
|
// @event `change`
|
|
60
|
-
const editor = this._getEditor()
|
|
61
|
-
editor.onDidChangeModelContent(event => {
|
|
62
|
-
const value = editor.getValue()
|
|
67
|
+
const editor = this._getEditor();
|
|
68
|
+
editor.onDidChangeModelContent((event) => {
|
|
69
|
+
const value = editor.getValue();
|
|
63
70
|
if (this.value !== value) {
|
|
64
|
-
this.$emit(
|
|
71
|
+
this.$emit("change", value, event);
|
|
65
72
|
}
|
|
66
|
-
})
|
|
73
|
+
});
|
|
67
74
|
|
|
68
|
-
this.$emit(
|
|
75
|
+
this.$emit("editorDidMount", this.editor);
|
|
69
76
|
},
|
|
70
77
|
_setModel(value, original) {
|
|
71
78
|
const { language } = this;
|
|
@@ -73,52 +80,52 @@ export default defineComponent({
|
|
|
73
80
|
const modifiedModel = monaco.editor.createModel(value, language);
|
|
74
81
|
this.editor.setModel({
|
|
75
82
|
original: originalModel,
|
|
76
|
-
modified: modifiedModel
|
|
83
|
+
modified: modifiedModel,
|
|
77
84
|
});
|
|
78
85
|
},
|
|
79
86
|
_setValue(value) {
|
|
80
87
|
let editor = this._getEditor();
|
|
81
|
-
if(editor) return editor.setValue(value);
|
|
88
|
+
if (editor) return editor.setValue(value);
|
|
82
89
|
},
|
|
83
90
|
_getValue() {
|
|
84
91
|
let editor = this._getEditor();
|
|
85
|
-
if(!editor) return
|
|
92
|
+
if (!editor) return "";
|
|
86
93
|
return editor.getValue();
|
|
87
94
|
},
|
|
88
95
|
_getEditor() {
|
|
89
|
-
if(!this.editor) return null;
|
|
96
|
+
if (!this.editor) return null;
|
|
90
97
|
return this.diffEditor ? this.editor.getModifiedEditor() : this.editor;
|
|
91
98
|
},
|
|
92
|
-
_setOriginal(){
|
|
93
|
-
const { original } = this.editor.getModel()
|
|
94
|
-
original.setValue(this.original)
|
|
95
|
-
}
|
|
99
|
+
_setOriginal() {
|
|
100
|
+
const { original } = this.editor.getModel();
|
|
101
|
+
original.setValue(this.original);
|
|
102
|
+
},
|
|
96
103
|
},
|
|
97
104
|
watch: {
|
|
98
105
|
options: {
|
|
99
106
|
deep: true,
|
|
100
107
|
handler(options) {
|
|
101
108
|
this.editor.updateOptions(options);
|
|
102
|
-
}
|
|
109
|
+
},
|
|
103
110
|
},
|
|
104
111
|
value() {
|
|
105
112
|
this.value !== this._getValue() && this._setValue(this.value);
|
|
106
113
|
},
|
|
107
114
|
original() {
|
|
108
|
-
this._setOriginal()
|
|
115
|
+
this._setOriginal();
|
|
109
116
|
},
|
|
110
117
|
language() {
|
|
111
|
-
if(!this.editor) return;
|
|
112
|
-
if(this.diffEditor){
|
|
118
|
+
if (!this.editor) return;
|
|
119
|
+
if (this.diffEditor) {
|
|
113
120
|
const { original, modified } = this.editor.getModel();
|
|
114
121
|
monaco.editor.setModelLanguage(original, this.language);
|
|
115
122
|
monaco.editor.setModelLanguage(modified, this.language);
|
|
116
|
-
}else
|
|
123
|
+
} else
|
|
117
124
|
monaco.editor.setModelLanguage(this.editor.getModel(), this.language);
|
|
118
125
|
},
|
|
119
126
|
theme() {
|
|
120
127
|
monaco.editor.setTheme(this.theme);
|
|
121
128
|
},
|
|
122
|
-
}
|
|
129
|
+
},
|
|
123
130
|
});
|
|
124
131
|
</script>
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="form-wrapper">
|
|
3
|
+
<div
|
|
4
|
+
:class="{
|
|
5
|
+
'pt-20': !reducePaddingTop,
|
|
6
|
+
'pt-10': reducePaddingTop,
|
|
7
|
+
'pl-20': !isContainer,
|
|
8
|
+
'form-content': !isContainer,
|
|
9
|
+
container: isContainer,
|
|
10
|
+
}"
|
|
11
|
+
>
|
|
12
|
+
<slot />
|
|
13
|
+
</div>
|
|
14
|
+
<div
|
|
15
|
+
class="form-footer b-t-1 pt-10 pb-10 pl-20 pr-20 mt-15"
|
|
16
|
+
v-if="hasFooter"
|
|
17
|
+
>
|
|
18
|
+
<div
|
|
19
|
+
class="ac-vcentered"
|
|
20
|
+
:class="{
|
|
21
|
+
'form-content': !isContainer,
|
|
22
|
+
container: isContainer,
|
|
23
|
+
}"
|
|
24
|
+
>
|
|
25
|
+
<form-footer-controls>
|
|
26
|
+
<slot name="form-left-controls" />
|
|
27
|
+
</form-footer-controls>
|
|
28
|
+
<form-footer-controls>
|
|
29
|
+
<slot name="form-right-controls" />
|
|
30
|
+
</form-footer-controls>
|
|
31
|
+
</div>
|
|
32
|
+
</div>
|
|
33
|
+
</div>
|
|
34
|
+
</template>
|
|
35
|
+
|
|
36
|
+
<script>
|
|
37
|
+
import { defineComponent, defineAsyncComponent, h } from "vue";
|
|
38
|
+
|
|
39
|
+
export default defineComponent({
|
|
40
|
+
props: {
|
|
41
|
+
isContainer: {
|
|
42
|
+
type: Boolean,
|
|
43
|
+
default: false,
|
|
44
|
+
},
|
|
45
|
+
hasFooter: {
|
|
46
|
+
type: Boolean,
|
|
47
|
+
default: true,
|
|
48
|
+
},
|
|
49
|
+
reducePaddingTop: {
|
|
50
|
+
type: Boolean,
|
|
51
|
+
default: false,
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
|
|
55
|
+
components: {
|
|
56
|
+
FormFooterControls: defineAsyncComponent(() =>
|
|
57
|
+
import("../../v2/form/FormFooterControl.vue").then(
|
|
58
|
+
(module) => module.default
|
|
59
|
+
)
|
|
60
|
+
),
|
|
61
|
+
},
|
|
62
|
+
});
|
|
63
|
+
</script>
|
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<input
|
|
2
|
+
<input
|
|
3
|
+
class="ac-input"
|
|
4
|
+
:value="modelValue"
|
|
5
|
+
@input="$emit('update:modelValue', $event.target.value)"
|
|
6
|
+
/>
|
|
3
7
|
</template>
|
|
4
8
|
|
|
5
9
|
<script>
|
|
6
10
|
import { defineComponent } from "vue";
|
|
7
11
|
|
|
8
12
|
export default defineComponent({
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
return Object.assign({}, this.$attrs, {
|
|
14
|
-
onInput: (event) => {
|
|
15
|
-
this.$emit("update:modelValue", event.target.value);
|
|
16
|
-
},
|
|
17
|
-
});
|
|
13
|
+
props: {
|
|
14
|
+
modelValue: {
|
|
15
|
+
type: null,
|
|
16
|
+
default: "",
|
|
18
17
|
},
|
|
19
18
|
},
|
|
19
|
+
emits: ["update:modelValue"],
|
|
20
20
|
});
|
|
21
21
|
</script>
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<!-- modal start -->
|
|
3
|
+
<modal
|
|
4
|
+
:title="title"
|
|
5
|
+
modifier-classes="is-normal"
|
|
6
|
+
:open="open"
|
|
7
|
+
@closemodal="closeModal"
|
|
8
|
+
>
|
|
9
|
+
<!-- freedom content start -->
|
|
10
|
+
<div class="action-message pt-35 pb-35 has-text-centered">
|
|
11
|
+
<h5 class="is-message">{{ message }} {{ itemName ? "" : "?" }}</h5>
|
|
12
|
+
<p class="is-description">{{ itemName }} {{ itemName ? "?" : "" }}</p>
|
|
13
|
+
</div>
|
|
14
|
+
|
|
15
|
+
<!-- freedom content end -->
|
|
16
|
+
|
|
17
|
+
<!-- modal footer start -->
|
|
18
|
+
<template #modal-footer-controls>
|
|
19
|
+
<ac-button
|
|
20
|
+
@click.stop="closeModal"
|
|
21
|
+
title="Cancel"
|
|
22
|
+
modifier-classes="is-outlined"
|
|
23
|
+
/>
|
|
24
|
+
<ac-button
|
|
25
|
+
modifier-classes="is-danger"
|
|
26
|
+
:is-loader-active="isDeleteActive"
|
|
27
|
+
title="Yes"
|
|
28
|
+
@click.stop="confirm(true)"
|
|
29
|
+
/>
|
|
30
|
+
</template>
|
|
31
|
+
</modal>
|
|
32
|
+
<!-- modal end -->
|
|
33
|
+
</template>
|
|
34
|
+
|
|
35
|
+
<script>
|
|
36
|
+
import { defineComponent, defineAsyncComponent } from "vue";
|
|
37
|
+
export default defineComponent({
|
|
38
|
+
components: {
|
|
39
|
+
Modal: defineAsyncComponent(() =>
|
|
40
|
+
import("../modal/Modal.vue").then((module) => module.default)
|
|
41
|
+
),
|
|
42
|
+
AcButton: defineAsyncComponent(() =>
|
|
43
|
+
import("../button/Button.vue").then((module) => module.default)
|
|
44
|
+
),
|
|
45
|
+
},
|
|
46
|
+
props: {
|
|
47
|
+
open: {
|
|
48
|
+
type: Boolean,
|
|
49
|
+
default: false,
|
|
50
|
+
},
|
|
51
|
+
title: {
|
|
52
|
+
type: String,
|
|
53
|
+
default: "",
|
|
54
|
+
},
|
|
55
|
+
message: {
|
|
56
|
+
type: String,
|
|
57
|
+
default: "",
|
|
58
|
+
},
|
|
59
|
+
itemName: {
|
|
60
|
+
type: String,
|
|
61
|
+
default: "",
|
|
62
|
+
},
|
|
63
|
+
isLoading: {
|
|
64
|
+
type: Boolean,
|
|
65
|
+
default: false,
|
|
66
|
+
},
|
|
67
|
+
isDeleteActive: {
|
|
68
|
+
type: Boolean,
|
|
69
|
+
default: false,
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
emits: ["closemodal", "delete-confirmation-modal$confirm"],
|
|
73
|
+
methods: {
|
|
74
|
+
confirm(response) {
|
|
75
|
+
this.$emit("delete-confirmation-modal$confirm", response);
|
|
76
|
+
},
|
|
77
|
+
closeModal() {
|
|
78
|
+
this.confirm(false);
|
|
79
|
+
this.$emit("closemodal", true);
|
|
80
|
+
},
|
|
81
|
+
},
|
|
82
|
+
});
|
|
83
|
+
</script>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div>
|
|
3
|
-
<button
|
|
4
|
-
v-if="themeMode"
|
|
3
|
+
<button
|
|
4
|
+
v-if="themeMode"
|
|
5
5
|
class="button ac-nav-button"
|
|
6
6
|
@click="toggleTheme"
|
|
7
7
|
:title="themeModes[themeMode].displayName"
|
|
@@ -10,11 +10,11 @@
|
|
|
10
10
|
</button>
|
|
11
11
|
<div class="ac-menu-content theme-choice">
|
|
12
12
|
<ul class="is-flex is-flex-direction-row is-justify-content-space-around">
|
|
13
|
-
<li
|
|
13
|
+
<li
|
|
14
14
|
v-for="theme of Object.keys(themeModes)"
|
|
15
15
|
:title="themeModes[theme].displayName"
|
|
16
16
|
@click="themeMode = theme"
|
|
17
|
-
:class="{'is-active': themeMode === theme}"
|
|
17
|
+
:class="{ 'is-active': themeMode === theme }"
|
|
18
18
|
:key="theme"
|
|
19
19
|
>
|
|
20
20
|
<i :class="['fa', themeModes[theme].iconClass]" />
|
|
@@ -42,19 +42,19 @@ export default defineComponent({
|
|
|
42
42
|
dark: {
|
|
43
43
|
displayName: "Dark Theme",
|
|
44
44
|
iconClass: "fa-moon-o",
|
|
45
|
-
}
|
|
46
|
-
}
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
47
|
};
|
|
48
48
|
},
|
|
49
49
|
|
|
50
|
-
emits: [
|
|
50
|
+
emits: ["set:theme"],
|
|
51
51
|
|
|
52
52
|
mounted() {
|
|
53
53
|
// get theme mode from localStorage or set default one
|
|
54
54
|
this.themeMode = localStorage.getItem("themeMode") || "light";
|
|
55
55
|
},
|
|
56
56
|
|
|
57
|
-
|
|
57
|
+
unmounted() {
|
|
58
58
|
this.removeColorSchemeEventListener();
|
|
59
59
|
},
|
|
60
60
|
|
|
@@ -62,19 +62,16 @@ export default defineComponent({
|
|
|
62
62
|
themeMode: {
|
|
63
63
|
handler(n) {
|
|
64
64
|
this.onThemeModeChange(n);
|
|
65
|
-
}
|
|
66
|
-
}
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
67
|
},
|
|
68
68
|
|
|
69
69
|
methods: {
|
|
70
70
|
// handle theme mode button click
|
|
71
71
|
toggleTheme() {
|
|
72
|
-
if(this.themeMode === "light")
|
|
73
|
-
|
|
74
|
-
else if(this.themeMode === "
|
|
75
|
-
this.themeMode = "system";
|
|
76
|
-
else if(this.themeMode === "system")
|
|
77
|
-
this.themeMode = "light";
|
|
72
|
+
if (this.themeMode === "light") this.themeMode = "dark";
|
|
73
|
+
else if (this.themeMode === "dark") this.themeMode = "system";
|
|
74
|
+
else if (this.themeMode === "system") this.themeMode = "light";
|
|
78
75
|
},
|
|
79
76
|
|
|
80
77
|
// triggered when theme mode is updated
|
|
@@ -82,8 +79,10 @@ export default defineComponent({
|
|
|
82
79
|
localStorage.setItem("themeMode", n);
|
|
83
80
|
|
|
84
81
|
let theme = n;
|
|
85
|
-
if(n === "system") {
|
|
86
|
-
const isDarkMode =
|
|
82
|
+
if (n === "system") {
|
|
83
|
+
const isDarkMode =
|
|
84
|
+
window.matchMedia &&
|
|
85
|
+
window.matchMedia("(prefers-color-scheme: dark)").matches;
|
|
87
86
|
this.addColorSchemeEventListener();
|
|
88
87
|
theme = isDarkMode ? "dark" : "light";
|
|
89
88
|
} else {
|
|
@@ -95,7 +94,7 @@ export default defineComponent({
|
|
|
95
94
|
|
|
96
95
|
// add proper css class to update the ui theme
|
|
97
96
|
handleDarkThemeClass(currentTheme) {
|
|
98
|
-
if(currentTheme === "light") {
|
|
97
|
+
if (currentTheme === "light") {
|
|
99
98
|
document.documentElement.classList.remove("is-dark-theme");
|
|
100
99
|
} else {
|
|
101
100
|
document.documentElement.classList.add("is-dark-theme");
|
|
@@ -106,23 +105,19 @@ export default defineComponent({
|
|
|
106
105
|
addColorSchemeEventListener() {
|
|
107
106
|
window
|
|
108
107
|
.matchMedia("(prefers-color-scheme: dark)")
|
|
109
|
-
.addEventListener(
|
|
110
|
-
"change", this.handleSystemThemeChange
|
|
111
|
-
);
|
|
108
|
+
.addEventListener("change", this.handleSystemThemeChange);
|
|
112
109
|
},
|
|
113
110
|
|
|
114
111
|
// remove system theme listener event
|
|
115
112
|
removeColorSchemeEventListener() {
|
|
116
113
|
window
|
|
117
114
|
.matchMedia("(prefers-color-scheme: dark)")
|
|
118
|
-
.removeEventListener(
|
|
119
|
-
"change", this.handleSystemThemeChange
|
|
120
|
-
);
|
|
115
|
+
.removeEventListener("change", this.handleSystemThemeChange);
|
|
121
116
|
},
|
|
122
117
|
|
|
123
118
|
handleSystemThemeChange() {
|
|
124
119
|
this.onThemeModeChange(this.themeMode);
|
|
125
120
|
},
|
|
126
|
-
}
|
|
121
|
+
},
|
|
127
122
|
});
|
|
128
123
|
</script>
|