@appscode/design-system 1.0.43-alpha.13 → 1.0.43-alpha.132

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.
Files changed (104) hide show
  1. package/base/utilities/_default.scss +283 -21
  2. package/base/utilities/_derived-variables.scss +0 -13
  3. package/base/utilities/_initial-variables.scss +78 -56
  4. package/base/utilities/_mixin.scss +10 -17
  5. package/base/utilities/_typography.scss +23 -7
  6. package/base/utilities/dark-theme.scss +25 -0
  7. package/components/_ac-accordion.scss +1 -0
  8. package/components/_ac-alert-box.scss +18 -10
  9. package/components/_ac-card.scss +55 -20
  10. package/components/_ac-code-highlight.scss +7 -1
  11. package/components/_ac-content-layout.scss +4 -4
  12. package/components/_ac-drag.scss +6 -6
  13. package/components/_ac-input.scss +74 -40
  14. package/components/_ac-modal.scss +5 -4
  15. package/components/_ac-multi-select.scss +195 -13
  16. package/components/_ac-options.scss +31 -16
  17. package/components/_ac-select-box.scss +15 -5
  18. package/components/_ac-table.scss +42 -36
  19. package/components/_ac-tabs.scss +72 -23
  20. package/components/_ac-tags.scss +2 -2
  21. package/components/_ac-terminal.scss +272 -0
  22. package/components/_app-drawer.scss +6 -6
  23. package/components/_breadcumb.scss +7 -2
  24. package/components/_buttons.scss +60 -27
  25. package/components/_card-body-wrapper.scss +3 -3
  26. package/components/_dashboard-header.scss +33 -1
  27. package/components/_direct-deploy.scss +69 -0
  28. package/components/_go-to-top.scss +1 -1
  29. package/components/_graph.scss +45 -0
  30. package/components/_image-upload.scss +6 -4
  31. package/components/_left-sidebar-menu.scss +200 -46
  32. package/components/_monaco-editor.scss +1 -1
  33. package/components/_navbar.scss +129 -26
  34. package/components/_overview-info.scss +4 -4
  35. package/components/_overview-page.scss +1 -2
  36. package/components/_pagination.scss +10 -2
  37. package/components/_payment-card.scss +28 -12
  38. package/components/_preview-modal.scss +19 -8
  39. package/components/_pricing-table.scss +1 -1
  40. package/components/_progress-bar.scss +5 -5
  41. package/components/_subscription-card.scss +15 -8
  42. package/components/_table-of-content.scss +1 -1
  43. package/components/_tfa.scss +69 -0
  44. package/components/_transitions.scss +261 -0
  45. package/components/_widget-menu.scss +9 -9
  46. package/components/_wizard.scss +31 -19
  47. package/components/ac-toaster/_ac-toasted.scss +5 -5
  48. package/components/bbum/_card-team.scss +18 -10
  49. package/components/bbum/_information-center.scss +17 -3
  50. package/components/bbum/_mobile-desktop.scss +6 -6
  51. package/components/bbum/_post.scss +5 -4
  52. package/components/bbum/_sign-up-notification.scss +6 -6
  53. package/components/bbum/_single-post-preview.scss +9 -9
  54. package/components/bbum/_user-profile.scss +97 -90
  55. package/components/ui-builder/_ui-builder.scss +29 -10
  56. package/components/ui-builder/_vue-open-api.scss +98 -0
  57. package/layouts/_404.scss +2 -1
  58. package/layouts/_code-preview.scss +14 -7
  59. package/main.scss +4 -0
  60. package/package.json +2 -7
  61. package/plugins/theme.js +130 -128
  62. package/vue-components/v2/banner/Banner.vue +2 -2
  63. package/vue-components/v2/breadcrumbs/Breadcrumb.vue +97 -0
  64. package/vue-components/v2/button/Button.vue +5 -0
  65. package/vue-components/v2/button/DownloadBtn.vue +45 -0
  66. package/vue-components/v2/card/PaymentCards.vue +11 -2
  67. package/vue-components/v2/content/ContentTable.vue +12 -7
  68. package/vue-components/v2/editor/Editor.vue +29 -1
  69. package/vue-components/v2/editor/FilteredFileEditor.vue +153 -0
  70. package/vue-components/v2/editor/ResourceKeyValueEditor.vue +196 -0
  71. package/vue-components/v2/loaders/ResourceLoader.vue +90 -0
  72. package/vue-components/v2/loaders/SidebarLoader.vue +32 -0
  73. package/vue-components/v2/modal/Modal.vue +33 -12
  74. package/vue-components/v2/modals/DeleteConfirmationModal.vue +77 -0
  75. package/vue-components/v2/modals/JsonShowModal.vue +12 -2
  76. package/vue-components/v2/navbar/Appdrawer.vue +10 -9
  77. package/vue-components/v2/navbar/ThemeMode.vue +120 -0
  78. package/vue-components/v2/navbar/User.vue +154 -12
  79. package/vue-components/v2/preloader/Preloader.vue +5 -5
  80. package/vue-components/v2/sidebar/ClusterSwitcher.vue +126 -0
  81. package/vue-components/v2/sidebar/SidebarItem.vue +23 -1
  82. package/vue-components/v2/sidebar/SidebarItemWithDropDown.vue +19 -20
  83. package/vue-components/v2/table/Table.vue +43 -8
  84. package/vue-components/v2/table/TableRow.vue +17 -8
  85. package/vue-components/v2/table/table-cell/CellValue.vue +31 -4
  86. package/vue-components/v2/table/table-cell/GenericCell.vue +56 -0
  87. package/vue-components/v2/table/table-cell/ObjectCell.vue +4 -1
  88. package/vue-components/v2/tabs/EditorTabs.vue +1 -1
  89. package/vue-components/v3/button/Button.vue +5 -0
  90. package/vue-components/v3/dropdown/DropdownMenu.vue +1 -1
  91. package/vue-components/v3/editor/Editor.vue +32 -11
  92. package/vue-components/v3/modal/Modal.vue +10 -1
  93. package/vue-components/v3/modals/JsonShowModal.vue +13 -4
  94. package/vue-components/v3/navbar/Appdrawer.vue +12 -7
  95. package/vue-components/v3/navbar/ThemeMode.vue +128 -0
  96. package/vue-components/v3/navbar/User.vue +154 -12
  97. package/vue-components/v3/sidebar/ClusterSwitcher.vue +133 -0
  98. package/vue-components/v3/sidebar/SidebarItemWithDropDown.vue +120 -0
  99. package/vue-components/v3/table/Table.vue +27 -5
  100. package/vue-components/v3/table/TableRow.vue +1 -1
  101. package/vue-components/v3/table/table-cell/CellValue.vue +26 -3
  102. package/vue-components/v3/table/table-cell/GenericCell.vue +62 -0
  103. package/vue-components/v3/table/table-cell/ObjectCell.vue +5 -1
  104. package/vue-components/v3/tabs/EditorTabs.vue +1 -1
@@ -23,12 +23,40 @@
23
23
  :key="idx"
24
24
  :class="{
25
25
  sorting: headerSortables[idx] && headerSortables[idx].enabled,
26
- 'sorting-desc': headerSortables[idx] && headerSortables[idx].mode === 'desc',
27
- 'sorting-asc': headerSortables[idx] && headerSortables[idx].mode === 'asc',
26
+ 'sorting-desc':
27
+ headerSortables[idx] && headerSortables[idx].mode === 'desc',
28
+ 'sorting-asc':
29
+ headerSortables[idx] && headerSortables[idx].mode === 'asc',
30
+ 'has-text-centered':
31
+ typeof tableHeader === 'string'
32
+ ? false
33
+ : tableHeader.textAlign === 'center',
34
+ 'has-text-left':
35
+ typeof tableHeader === 'string'
36
+ ? false
37
+ : tableHeader.textAlign === 'left',
38
+ 'has-text-right':
39
+ typeof tableHeader === 'string'
40
+ ? false
41
+ : tableHeader.textAlign === 'right',
28
42
  }"
29
- @click.prevent="headerSortables[idx] && headerSortables[idx].enabled && emitSortEvent(idx)"
43
+ @click.prevent="
44
+ headerSortables[idx] &&
45
+ headerSortables[idx].enabled &&
46
+ emitSortEvent(idx)
47
+ "
48
+ :title="tableHeader.dashboard && tableHeader.dashboard.message"
30
49
  >
31
50
  {{ headerLabels[idx] }}
51
+ <span
52
+ v-if="
53
+ tableHeader.dashboard &&
54
+ tableHeader.dashboard.status !== 'Success'
55
+ "
56
+ class="icon has-text-danger"
57
+ >
58
+ <i class="fa fa-exclamation-triangle" />
59
+ </span>
32
60
  </th>
33
61
  <th
34
62
  ref="action-section"
@@ -146,7 +174,7 @@ export default {
146
174
  },
147
175
  headerLabels() {
148
176
  return this.tableHeaders.map((th) =>
149
- typeof th === "string" ? th : th.label || "Label"
177
+ typeof th === "string" ? th : th.name || "Label"
150
178
  );
151
179
  },
152
180
  },
@@ -157,8 +185,15 @@ export default {
157
185
  handler(n) {
158
186
  if (this.headerSortables.length === n.length) {
159
187
  n.forEach((th, idx) => {
160
- if (this.headerSortables[idx].enabled !== !!th.sortable) {
161
- this.headerSortables[idx].enabled = !!th.sortable;
188
+ if (
189
+ this.headerSortables[idx].enabled !==
190
+ !!(th && th.sort && th.sort.enable)
191
+ ) {
192
+ this.headerSortables[idx].enabled = !!(
193
+ th &&
194
+ th.sort &&
195
+ th.sort.enable
196
+ );
162
197
  this.headerSortables[idx].mode = "";
163
198
  }
164
199
  });
@@ -171,7 +206,7 @@ export default {
171
206
  };
172
207
  } else {
173
208
  return {
174
- enabled: !!th.sortable,
209
+ enabled: !!(th && th.sort && th.sort.enable),
175
210
  mode: "",
176
211
  };
177
212
  }
@@ -198,7 +233,7 @@ export default {
198
233
  emitSortEvent(index) {
199
234
  const emitValue = {
200
235
  index,
201
- label: this.tableHeaders[index].label,
236
+ label: this.tableHeaders[index].name,
202
237
  mode: "",
203
238
  };
204
239
 
@@ -6,7 +6,7 @@
6
6
  custom
7
7
  v-slot="{ navigate }"
8
8
  >
9
- <tr @click="navigate">
9
+ <tr class="is-link" @click="navigate">
10
10
  <slot />
11
11
  <fake-table-cell
12
12
  v-if="fakeCellWidth > 0"
@@ -14,9 +14,14 @@
14
14
  />
15
15
  </tr>
16
16
  </router-link>
17
+
17
18
  <tr
18
19
  v-else
19
- :class="{ 'is-selected': isSelected, 'is-hoverless': !isSelected }"
20
+ :class="{
21
+ 'is-selected': isSelected,
22
+ 'is-hoverless': !isSelected,
23
+ 'is-disabled': isDisabled
24
+ }"
20
25
  @click.prevent="$emit('rowselect', true)"
21
26
  >
22
27
  <slot />
@@ -32,21 +37,25 @@ export default {
32
37
  props: {
33
38
  link: {
34
39
  type: String,
35
- default: "",
40
+ default: ""
36
41
  },
37
42
  isSelected: {
38
43
  type: Boolean,
39
- default: false,
44
+ default: false
45
+ },
46
+ isDisabled: {
47
+ type: Boolean,
48
+ default: false
40
49
  },
41
50
  fakeCellWidth: {
42
51
  type: Number,
43
- default: 0,
44
- },
52
+ default: 0
53
+ }
45
54
  },
46
55
 
47
56
  components: {
48
57
  TableCell: () => import("./TableCell.vue"),
49
- FakeTableCell: () => import("./FakeTableCell.vue"),
50
- },
58
+ FakeTableCell: () => import("./FakeTableCell.vue")
59
+ }
51
60
  };
52
61
  </script>
@@ -1,8 +1,13 @@
1
1
  <template>
2
2
  <div v-if="isLoaderActive" ref="cellLoaderDiv" :style="{ maxWidth: '300px' }">
3
- <content-loader :height="10" :width="computedCellWidth || 300" />
3
+ <content-loader
4
+ :height="10"
5
+ :width="computedCellWidth || 300"
6
+ :primaryColor="primaryColor"
7
+ :secondaryColor="secondaryColor"
8
+ />
4
9
  </div>
5
- <div v-else class="haha" ref="cellDiv">
10
+ <div v-else ref="cellDiv">
6
11
  <object-cell
7
12
  v-if="valueType === 'object'"
8
13
  :obj="value"
@@ -16,7 +21,7 @@
16
21
  :max-character-length="maxCharacterLength"
17
22
  />
18
23
  <template v-else>
19
- <span class="is-ellipsis-1" :title="value">{{
24
+ <span class="is-ellipsis-1" :title="tooltip">{{
20
25
  value || (value === 0 ? 0 : "-")
21
26
  }}</span>
22
27
  </template>
@@ -24,6 +29,13 @@
24
29
  </template>
25
30
 
26
31
  <script>
32
+ import {
33
+ loaderLightThemePrimaryColor,
34
+ loaderDarkThemePrimaryColor,
35
+ loaderLightThemeSecondaryColor,
36
+ loaderDarkThemeSecondaryColor,
37
+ } from "@appscode/design-system/plugins/theme";
38
+
27
39
  export default {
28
40
  props: {
29
41
  isLoaderActive: {
@@ -38,6 +50,10 @@ export default {
38
50
  type: null,
39
51
  default: "",
40
52
  },
53
+ tooltip: {
54
+ type: String,
55
+ defualt: "",
56
+ },
41
57
  },
42
58
  components: {
43
59
  ContentLoader: () =>
@@ -49,13 +65,24 @@ export default {
49
65
  computed: {
50
66
  valueType() {
51
67
  if (typeof this.value === "object") {
52
- if (Array.isArray(this.value)) return "array";
68
+ if (this.value === null) return "null";
69
+ else if (Array.isArray(this.value)) return "array";
53
70
  else return "object";
54
71
  } else return typeof this.value;
55
72
  },
56
73
  maxCharacterLength() {
57
74
  return Math.ceil(this.computedCellWidth / 8);
58
75
  },
76
+ primaryColor() {
77
+ return document.documentElement.classList.contains("is-dark-theme")
78
+ ? loaderDarkThemePrimaryColor
79
+ : loaderLightThemePrimaryColor;
80
+ },
81
+ secondaryColor() {
82
+ return document.documentElement.classList.contains("is-dark-theme")
83
+ ? loaderDarkThemeSecondaryColor
84
+ : loaderLightThemeSecondaryColor;
85
+ },
59
86
  },
60
87
 
61
88
  data() {
@@ -0,0 +1,56 @@
1
+ <template>
2
+ <span
3
+ :class="{
4
+ 'is-flex': cellDescriptor.type !== 'object',
5
+ 'is-align-items-center': cellValue.icon,
6
+ 'is-justify-content-center': cellDescriptor.textAlign === 'center',
7
+ 'is-justify-content-left': cellDescriptor.textAlign === 'left',
8
+ 'is-justify-content-right': cellDescriptor.textAlign === 'right'
9
+ }"
10
+ >
11
+ <span v-if="cellValue.icon" class="icon p-0 mr-10">
12
+ <img width="15" :src="cellValue.icon" />
13
+ </span>
14
+ <router-link v-if="cellValue.link" :to="getCellLink(cellValue)">
15
+ {{ cellValue.data }}
16
+ </router-link>
17
+ <tag v-else-if="cellValue.color" :class="`is-${cellValue.color}`">
18
+ {{ cellValue.data }}
19
+ </tag>
20
+ <cell-value
21
+ v-else
22
+ :cell-title="cellDescriptor.name"
23
+ :value="cellValue.data || '-'"
24
+ :tooltip="cellValue.tooltip || JSON.stringify(cellValue.data)"
25
+ />
26
+ </span>
27
+ </template>
28
+ <script>
29
+ export default {
30
+ components: {
31
+ Tag: () => import("../../tag/Tag.vue"),
32
+ CellValue: () => import("../table-cell/CellValue.vue")
33
+ },
34
+ props: {
35
+ cellDescriptor: {
36
+ type: Object,
37
+ default: () => ({})
38
+ },
39
+ cellValue: {
40
+ type: Object,
41
+ default: () => ({})
42
+ }
43
+ },
44
+ methods: {
45
+ getCellLink(cell) {
46
+ const inject = (str, obj) => str.replace(/\${(.*?)}/g, (x, g) => obj[g]);
47
+ const { user, cluster } = this.$route.params;
48
+ const link = inject(cell.link || "", {
49
+ username: user,
50
+ clustername: cluster
51
+ });
52
+ return link;
53
+ }
54
+ }
55
+ };
56
+ </script>
@@ -68,7 +68,10 @@ export default {
68
68
  },
69
69
  printableStringObjs() {
70
70
  return this.objKeys.map((key) => {
71
- const value = this.obj[key];
71
+ let value = this.obj[key];
72
+ if (typeof value === "object" && value !== null) {
73
+ value = JSON.stringify(value);
74
+ }
72
75
  const keyValue = `${key}: ${value}`;
73
76
  const exceededLength = keyValue.length > 30;
74
77
  const print = exceededLength ? key : keyValue;
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <tabs-body class="mt-20">
2
+ <tabs-body>
3
3
  <tabs class="is-line">
4
4
  <tab-item :is-active="activeTab === 'edit'">
5
5
  <a @click.prevent="$emit('tabchange', 'edit')">Edit</a>
@@ -4,6 +4,7 @@
4
4
  :class="`${modifierClasses}${isLoaderActive ? ' is-loading' : ''}`"
5
5
  :disabled="disabled ? true : null"
6
6
  @click="handleClick"
7
+ :title="tooltip"
7
8
  >
8
9
  <span v-if="iconClass || iconImage" class="icon is-small">
9
10
  <img
@@ -28,6 +29,10 @@ export default defineComponent({
28
29
  type: String,
29
30
  default: "",
30
31
  },
32
+ tooltip: {
33
+ type: String,
34
+ defualt: undefined
35
+ },
31
36
  // for loader
32
37
  isLoaderActive: {
33
38
  type: Boolean,
@@ -57,9 +57,9 @@ export default defineComponent({
57
57
 
58
58
  // attach click event listener on window, and close the dropdown
59
59
  function deactivateDropdown(e: Event) {
60
- e.preventDefault();
61
60
  const { target } = e;
62
61
  if (
62
+ isDropdownActive.value &&
63
63
  dropdown.value &&
64
64
  dropdown.value !== target &&
65
65
  !dropdown.value.contains(target as Node)
@@ -7,7 +7,6 @@
7
7
  />
8
8
  <monaco-editor
9
9
  v-if="activeTab === 'edit'"
10
- ref="monacoEditor"
11
10
  @editorDidMount="onEditorMount"
12
11
  key="edit"
13
12
  :class="`vh-${editorHeight} is-clipped`"
@@ -18,7 +17,9 @@
18
17
  minimap: {
19
18
  enabled: calcShowMinimap,
20
19
  },
20
+ theme: theme,
21
21
  readOnly: readOnly,
22
+ wordWrap: wordWrap,
22
23
  scrollBeyondLastLine: false,
23
24
  }"
24
25
  />
@@ -32,7 +33,9 @@
32
33
  minimap: {
33
34
  enabled: calcShowMinimap,
34
35
  },
36
+ theme: theme,
35
37
  readOnly: true,
38
+ wordWrap: wordWrap,
36
39
  scrollBeyondLastLine: false,
37
40
  }"
38
41
  :original="originalEditorContent"
@@ -43,6 +46,8 @@
43
46
 
44
47
  <script>
45
48
  import { defineComponent, defineAsyncComponent, h } from "vue";
49
+ import Preloader from "../../v2/preloader/Preloader.vue";
50
+ import Banner from "../../v2/banner/Banner.vue";
46
51
  export default defineComponent({
47
52
  props: {
48
53
  value: {
@@ -69,6 +74,14 @@ export default defineComponent({
69
74
  type: Number,
70
75
  default: 40,
71
76
  },
77
+ editorTheme: {
78
+ type: String,
79
+ default: "",
80
+ },
81
+ wordWrap: {
82
+ type: String,
83
+ default: "off",
84
+ },
72
85
  },
73
86
 
74
87
  emits: ["update:modelValue"],
@@ -77,14 +90,15 @@ export default defineComponent({
77
90
  EditorTabs: defineAsyncComponent(() =>
78
91
  import("../tabs/EditorTabs.vue").then((module) => module.default)
79
92
  ),
80
- MonacoEditor: defineAsyncComponent(() =>
81
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
82
- // @ts-ignore
83
- import("vue-monaco").then((module) => {
84
- module.default.render = () => h("div");
85
- return module.default;
86
- })
87
- ),
93
+ MonacoEditor: defineAsyncComponent({
94
+ loader: () =>
95
+ import("monaco-editor-vue3").then((module) => module.default),
96
+
97
+ loadingComponent: Preloader,
98
+ delay: 200,
99
+ errorComponent: Banner,
100
+ timeout: 20000,
101
+ }),
88
102
  },
89
103
 
90
104
  data() {
@@ -100,6 +114,14 @@ export default defineComponent({
100
114
  const noOfLines = this.editorContent.split("\n").length;
101
115
  return this.showMinimap && noOfLines * 2 > this.editorHeight;
102
116
  },
117
+ theme() {
118
+ return (
119
+ this.editorTheme ||
120
+ (document.documentElement.classList.contains("is-dark-theme")
121
+ ? "vs-dark"
122
+ : "vs")
123
+ );
124
+ },
103
125
  },
104
126
 
105
127
  watch: {
@@ -125,8 +147,7 @@ export default defineComponent({
125
147
  onChange(e) {
126
148
  if (typeof e === "string") this.editorContent = e;
127
149
  },
128
- onEditorMount() {
129
- const editor = this.$refs.monacoEditor.getEditor();
150
+ onEditorMount(editor) {
130
151
  // add event listeners
131
152
  editor.onDidBlurEditorText(() => {
132
153
  this.$emit("update:modelValue", this.editorContent);
@@ -17,6 +17,7 @@
17
17
  <header-item>
18
18
  <ac-button
19
19
  modifier-classes="is-square is-transparent"
20
+ :disabled="isCloseOptionDisabled"
20
21
  :icon-image="crossIcon"
21
22
  @click.stop="destroyModal"
22
23
  />
@@ -36,7 +37,10 @@
36
37
  <!-- modal body end -->
37
38
 
38
39
  <!-- modal footer start -->
39
- <div class="ac-modal-footer action-footer">
40
+ <div class="ac-modal-footer action-footer is-flex is-align-items-center is-justify-content-space-between">
41
+ <div>
42
+ <slot name="modal-footer-left" />
43
+ </div>
40
44
  <buttons class="has-text-right is-block">
41
45
  <slot name="modal-footer-controls" />
42
46
  </buttons>
@@ -64,6 +68,10 @@ export default defineComponent({
64
68
  type: String,
65
69
  default: "",
66
70
  },
71
+ isCloseOptionDisabled: {
72
+ type: Boolean,
73
+ default: false,
74
+ }
67
75
  },
68
76
  emits: ["closemodal"],
69
77
 
@@ -116,6 +124,7 @@ export default defineComponent({
116
124
  document.addEventListener("keydown", this.onKeyDown);
117
125
  },
118
126
  destroyModal() {
127
+ if (this.isCloseOptionDisabled) return;
119
128
  this.showModal = false;
120
129
  document.removeEventListener("keydown", this.onKeyDown);
121
130
 
@@ -10,7 +10,9 @@
10
10
  <ac-button
11
11
  modifier-classes="is-square is-primary"
12
12
  icon-class="copy"
13
- v-clipboard:copy="`${editorTitle}: &quot;${editorContent}&quot;`"
13
+ v-clipboard:copy="
14
+ `${editorTitle}: ${JSON.stringify(parsedContent, null, 4)}`
15
+ "
14
16
  v-clipboard:success="onCopy"
15
17
  v-clipboard:error="onError"
16
18
  />
@@ -28,6 +30,8 @@
28
30
  <script>
29
31
  import { defineComponent, defineAsyncComponent } from "vue";
30
32
  import { useToast } from "vue-toastification";
33
+ import Preloader from "../../v2/preloader/Preloader.vue";
34
+ import Banner from "../../v2/banner/Banner.vue";
31
35
 
32
36
  export default defineComponent({
33
37
  props: {
@@ -49,9 +53,14 @@ export default defineComponent({
49
53
  Modal: defineAsyncComponent(() =>
50
54
  import("../modal/Modal.vue").then((module) => module.default)
51
55
  ),
52
- Editor: defineAsyncComponent(() =>
53
- import("../editor/Editor.vue").then((module) => module.default)
54
- ),
56
+ Editor: defineAsyncComponent({
57
+ loader: () =>
58
+ import("../editor/Editor.vue").then((module) => module.default),
59
+ loadingComponent: Preloader,
60
+ delay: 200,
61
+ errorComponent: Banner,
62
+ timeout: 20000,
63
+ }),
55
64
  AcButton: defineAsyncComponent(() =>
56
65
  import("../button/Button.vue").then((module) => module.default)
57
66
  ),
@@ -1,10 +1,13 @@
1
1
  <template>
2
- <div class="app-drawer-wrapper">
3
- <div class="drawer-icon">
2
+ <div class="app-drawer-wrapper is-flex">
3
+ <div
4
+ class="drawer-icon is-flex is-justify-content-center is-align-items-center"
5
+ >
4
6
  <svg
5
7
  class="gb_We"
6
8
  focusable="false"
7
9
  viewBox="0 0 24 24"
10
+ style="width: 22px;margin-top: 2px;"
8
11
  :style="{ fill: 'white' }"
9
12
  >
10
13
  <path
@@ -46,13 +49,15 @@ export default defineComponent({
46
49
  props: {
47
50
  apps: {
48
51
  type: Array,
49
- default: () => [],
50
- },
52
+ default: () => []
53
+ }
51
54
  },
52
55
  components: {
53
56
  NavbarItemContent: defineAsyncComponent(() =>
54
- import("../../v2/navbar/NavbarItemContent.vue").then((module) => module.default)
55
- ),
56
- },
57
+ import("../../v2/navbar/NavbarItemContent.vue").then(
58
+ module => module.default
59
+ )
60
+ )
61
+ }
57
62
  });
58
63
  </script>
@@ -0,0 +1,128 @@
1
+ <template>
2
+ <div>
3
+ <button
4
+ v-if="themeMode"
5
+ class="button ac-nav-button"
6
+ @click="toggleTheme"
7
+ :title="themeModes[themeMode].displayName"
8
+ >
9
+ <i :class="`fa ${themeModes[themeMode].iconClass} width-15`" />
10
+ </button>
11
+ <div class="ac-menu-content theme-choice">
12
+ <ul class="is-flex is-flex-direction-row is-justify-content-space-around">
13
+ <li
14
+ v-for="theme of Object.keys(themeModes)"
15
+ :title="themeModes[theme].displayName"
16
+ @click="themeMode = theme"
17
+ :class="{'is-active': themeMode === theme}"
18
+ :key="theme"
19
+ >
20
+ <i :class="['fa', themeModes[theme].iconClass]" />
21
+ </li>
22
+ </ul>
23
+ </div>
24
+ </div>
25
+ </template>
26
+ <script>
27
+ import { defineComponent } from "vue";
28
+
29
+ export default defineComponent({
30
+ data() {
31
+ return {
32
+ themeMode: "",
33
+ themeModes: {
34
+ system: {
35
+ displayName: "System Theme",
36
+ iconClass: "fa-desktop",
37
+ },
38
+ light: {
39
+ displayName: "Light Theme",
40
+ iconClass: "fa-sun-o",
41
+ },
42
+ dark: {
43
+ displayName: "Dark Theme",
44
+ iconClass: "fa-moon-o",
45
+ }
46
+ }
47
+ };
48
+ },
49
+
50
+ emits: ['set:theme'],
51
+
52
+ mounted() {
53
+ // get theme mode from localStorage or set default one
54
+ this.themeMode = localStorage.getItem("themeMode") || "light";
55
+ },
56
+
57
+ destroyed() {
58
+ this.removeColorSchemeEventListener();
59
+ },
60
+
61
+ watch: {
62
+ themeMode: {
63
+ handler(n) {
64
+ this.onThemeModeChange(n);
65
+ }
66
+ }
67
+ },
68
+
69
+ methods: {
70
+ // handle theme mode button click
71
+ toggleTheme() {
72
+ if(this.themeMode === "light")
73
+ this.themeMode = "dark";
74
+ else if(this.themeMode === "dark")
75
+ this.themeMode = "system";
76
+ else if(this.themeMode === "system")
77
+ this.themeMode = "light";
78
+ },
79
+
80
+ // triggered when theme mode is updated
81
+ onThemeModeChange(n) {
82
+ localStorage.setItem("themeMode", n);
83
+
84
+ let theme = n;
85
+ if(n === "system") {
86
+ const isDarkMode = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
87
+ this.addColorSchemeEventListener();
88
+ theme = isDarkMode ? "dark" : "light";
89
+ } else {
90
+ this.removeColorSchemeEventListener();
91
+ }
92
+ this.$emit("set:theme", theme);
93
+ this.handleDarkThemeClass(theme);
94
+ },
95
+
96
+ // add proper css class to update the ui theme
97
+ handleDarkThemeClass(currentTheme) {
98
+ if(currentTheme === "light") {
99
+ document.documentElement.classList.remove("is-dark-theme");
100
+ } else {
101
+ document.documentElement.classList.add("is-dark-theme");
102
+ }
103
+ },
104
+
105
+ // add system theme listener event
106
+ addColorSchemeEventListener() {
107
+ window
108
+ .matchMedia("(prefers-color-scheme: dark)")
109
+ .addEventListener(
110
+ "change", this.handleSystemThemeChange
111
+ );
112
+ },
113
+
114
+ // remove system theme listener event
115
+ removeColorSchemeEventListener() {
116
+ window
117
+ .matchMedia("(prefers-color-scheme: dark)")
118
+ .removeEventListener(
119
+ "change", this.handleSystemThemeChange
120
+ );
121
+ },
122
+
123
+ handleSystemThemeChange() {
124
+ this.onThemeModeChange(this.themeMode);
125
+ },
126
+ }
127
+ });
128
+ </script>