@electerm/electerm-react 2.3.6 → 2.3.30

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 (50) hide show
  1. package/client/common/constants.js +1 -1
  2. package/client/common/has-active-input.js +10 -0
  3. package/client/common/ui-theme.js +25 -12
  4. package/client/components/ai/ai.styl +1 -3
  5. package/client/components/bg/custom-css.jsx +2 -2
  6. package/client/components/common/highlight.styl +1 -2
  7. package/client/components/common/input-context-menu.jsx +294 -0
  8. package/client/components/file-transfer/transfer.styl +6 -8
  9. package/client/components/footer/footer.styl +2 -5
  10. package/client/components/layout/layout.styl +2 -3
  11. package/client/components/main/error-wrapper.jsx +3 -3
  12. package/client/components/main/main.jsx +2 -1
  13. package/client/components/main/ui-theme.jsx +46 -6
  14. package/client/components/main/upgrade.styl +4 -6
  15. package/client/components/main/wrapper.styl +5 -27
  16. package/client/components/quick-commands/qm.styl +3 -5
  17. package/client/components/session/session.styl +11 -13
  18. package/client/components/setting-panel/list.styl +5 -5
  19. package/client/components/setting-panel/setting-wrap.styl +1 -6
  20. package/client/components/setting-panel/terminal-bg-config.jsx +3 -0
  21. package/client/components/setting-sync/setting-sync-form.jsx +0 -1
  22. package/client/components/sftp/file-item.jsx +8 -5
  23. package/client/components/sftp/sftp-entry.jsx +18 -4
  24. package/client/components/sftp/sftp.styl +24 -28
  25. package/client/components/sftp/transfer-tag.styl +3 -5
  26. package/client/components/side-panel-r/right-side-panel.styl +7 -9
  27. package/client/components/sidebar/index.jsx +6 -0
  28. package/client/components/sidebar/info.styl +0 -12
  29. package/client/components/sidebar/sidebar.styl +15 -16
  30. package/client/components/sys-menu/sub-tab-menu.jsx +2 -2
  31. package/client/components/sys-menu/sys-menu.styl +11 -11
  32. package/client/components/tabs/add-btn.jsx +258 -0
  33. package/client/components/tabs/add-btn.styl +12 -0
  34. package/client/components/tabs/index.jsx +8 -56
  35. package/client/components/tabs/tabs.styl +30 -31
  36. package/client/components/terminal/term-search.styl +3 -3
  37. package/client/components/terminal/terminal.jsx +2 -2
  38. package/client/components/terminal/terminal.styl +21 -22
  39. package/client/components/terminal-info/terminal-info.styl +7 -7
  40. package/client/components/theme/terminal-theme-list.styl +2 -2
  41. package/client/components/theme/theme-list-item.jsx +62 -20
  42. package/client/components/tree-list/tree-expander.jsx +4 -2
  43. package/client/css/basic.styl +5 -8
  44. package/client/css/includes/theme.styl +16 -0
  45. package/client/store/ui-theme.js +0 -35
  46. package/package.json +1 -1
  47. package/client/components/common/native-input.styl +0 -7
  48. package/client/components/setting-sync/sync.styl +0 -7
  49. package/client/css/antd-overwrite.styl +0 -10
  50. package/client/css/includes/theme-default.styl +0 -20
@@ -177,7 +177,7 @@ export const defaultTheme = {
177
177
  brightCyan: '#BCAAFE',
178
178
  brightWhite: '#E6E6E6'
179
179
  },
180
- uiThemeConfig: getUiThemeConfig(window.et.stylus)
180
+ uiThemeConfig: getUiThemeConfig()
181
181
  }
182
182
 
183
183
  export const commonBaudRates = [
@@ -0,0 +1,10 @@
1
+ export default function hasActiveInput (className = 'ant-input-search') {
2
+ const activeElement = document.activeElement
3
+ const isInput = activeElement && (
4
+ activeElement.tagName === 'INPUT' ||
5
+ activeElement.tagName === 'TEXTAREA'
6
+ )
7
+ const hasClass = className ? activeElement.classList.contains(className) : true
8
+ const hasInputDropDown = document.querySelector('.ant-dropdown:not(.ant-dropdown-hidden)')
9
+ return (isInput && hasClass) || hasInputDropDown
10
+ }
@@ -2,19 +2,32 @@
2
2
  * ui theme related
3
3
  */
4
4
 
5
- export function getUiThemeConfig (stylus) {
6
- const reg = /[^\n]+ = [^\n]+\n/g
7
- const arr = stylus.match(reg)
8
- const sep = ' = '
9
- return arr.reduce((p, x) => {
10
- if (!x.includes(sep)) {
11
- return p
12
- }
13
- const [k, v] = x.split(sep)
14
- return {
15
- ...p,
16
- [k.trim()]: v.trim()
5
+ const defaultUiThemeStylus = `
6
+ --main #141314
7
+ --main-dark #000
8
+ --main-light #2E3338
9
+ --text #ddd
10
+ --text-light #fff
11
+ --text-dark #888
12
+ --text-disabled #777
13
+ --primary #08c
14
+ --info #FFD166
15
+ --success #06D6A0
16
+ --error #EF476F
17
+ --warn #E55934
18
+ `
19
+
20
+ export function getUiThemeConfig (conf = defaultUiThemeStylus) {
21
+ const lines = conf.split('\n').filter(line => line.trim())
22
+ return lines.reduce((p, line) => {
23
+ const [k, v] = line.trim().replace('--', '').split(' ')
24
+ if (k && v) {
25
+ return {
26
+ ...p,
27
+ [k]: v
28
+ }
17
29
  }
30
+ return p
18
31
  }, {})
19
32
  }
20
33
 
@@ -1,9 +1,7 @@
1
- @require '../../css/includes/theme-default'
2
1
  .ai-chat-container
3
2
  height 100%
4
3
  display flex
5
4
  flex-direction column
6
- color text
7
5
 
8
6
  .ai-chat-history
9
7
  flex-grow 1
@@ -17,7 +15,7 @@
17
15
 
18
16
  .chat-history-item
19
17
  .code-block
20
- border 1px dashed text
18
+ border 1px dashed var(--main-darker)
21
19
  padding 5px
22
20
  border-radius 3px
23
21
  pre
@@ -14,8 +14,8 @@ export default function CustomCss (props) {
14
14
  const delta = useDelta(customCss)
15
15
 
16
16
  async function applyTheme () {
17
- const stylus = document.getElementById(themeDomId)
18
- stylus.innerHTML = customCss
17
+ const style = document.getElementById(themeDomId)
18
+ style.innerHTML = customCss
19
19
  }
20
20
 
21
21
  useEffect(() => {
@@ -1,3 +1,2 @@
1
- @require '../../css/includes/theme-default'
2
1
  .highlight
3
- color error
2
+ color var(--error)
@@ -0,0 +1,294 @@
1
+ /**
2
+ * Standalone Input/TextArea Context Menu Module
3
+ * Automatically adds context menus to all input/textarea elements without code modification
4
+ * Just import this module and render <InputContextMenu /> in your React app to activate
5
+ */
6
+
7
+ import React, { useState, useEffect, useRef } from 'react'
8
+ import { Dropdown } from 'antd'
9
+ import iconsMap from '../sys-menu/icons-map.jsx'
10
+ import { copy, readClipboard, readClipboardAsync } from '../../common/clipboard.js'
11
+
12
+ const e = window.translate
13
+
14
+ /**
15
+ * Check if element is input or textarea
16
+ */
17
+ function isInputElement (element) {
18
+ if (!element) return false
19
+ const tagName = element.tagName.toLowerCase()
20
+ return tagName === 'input' || tagName === 'textarea'
21
+ }
22
+
23
+ /**
24
+ * Get input element state
25
+ */
26
+ function getInputState (element) {
27
+ if (!isInputElement(element)) return null
28
+
29
+ const hasText = element.value && element.value.length > 0
30
+ const hasSelection = element.selectionStart !== element.selectionEnd
31
+ const isReadOnly = element.readOnly || element.disabled
32
+
33
+ let hasClipboard = false
34
+ try {
35
+ const content = readClipboard()
36
+ hasClipboard = content && content.length > 0
37
+ } catch (error) {
38
+ hasClipboard = false
39
+ }
40
+
41
+ return {
42
+ hasText,
43
+ hasSelection,
44
+ hasClipboard,
45
+ isReadOnly
46
+ }
47
+ }
48
+
49
+ /**
50
+ * Handle copy operation
51
+ */
52
+ function handleCopy (element) {
53
+ if (!isInputElement(element)) return
54
+
55
+ const selectedText = element.value.substring(element.selectionStart, element.selectionEnd)
56
+ if (selectedText) {
57
+ copy(selectedText)
58
+ }
59
+ }
60
+
61
+ /**
62
+ * Handle paste operation
63
+ */
64
+ async function handlePaste (element) {
65
+ if (!isInputElement(element) || element.readOnly || element.disabled) return
66
+
67
+ element.focus()
68
+ const clipboardText = await readClipboardAsync()
69
+
70
+ if (clipboardText) {
71
+ insertTextAtCursor(element, clipboardText)
72
+ }
73
+ }
74
+
75
+ /**
76
+ * Insert text at cursor position in input/textarea
77
+ */
78
+ function insertTextAtCursor (element, text) {
79
+ if (!isInputElement(element)) return
80
+
81
+ element.focus()
82
+
83
+ // Try modern approach first - using execCommand
84
+ if (document.execCommand && document.queryCommandSupported('insertText')) {
85
+ try {
86
+ element.setSelectionRange(element.selectionStart, element.selectionEnd)
87
+ const success = document.execCommand('insertText', false, text)
88
+ if (success) {
89
+ triggerInputEvents(element)
90
+ }
91
+ } catch (error) {
92
+ console.log('execCommand insertText failed:', error)
93
+ }
94
+ }
95
+ }
96
+
97
+ /**
98
+ * Trigger input events for React and other frameworks
99
+ */
100
+ function triggerInputEvents (element) {
101
+ const inputEvent = new Event('input', { bubbles: true, cancelable: true })
102
+ element.dispatchEvent(inputEvent)
103
+
104
+ const changeEvent = new Event('change', { bubbles: true, cancelable: true })
105
+ element.dispatchEvent(changeEvent)
106
+
107
+ // Handle React's internal event handlers
108
+ const reactHandlers = Object.keys(element).find(key => key.startsWith('__reactProps') || key.startsWith('__reactEventHandlers'))
109
+ if (reactHandlers) {
110
+ const handler = element[reactHandlers]
111
+ if (handler?.onChange) {
112
+ handler.onChange({ target: element, currentTarget: element })
113
+ }
114
+ }
115
+ }
116
+
117
+ /**
118
+ * Handle cut operation
119
+ */
120
+ function handleCut (element) {
121
+ if (!isInputElement(element) || element.readOnly || element.disabled) return
122
+
123
+ const { selectionStart, selectionEnd } = element
124
+ const selectedText = element.value.substring(selectionStart, selectionEnd)
125
+
126
+ if (selectedText) {
127
+ element.focus()
128
+ element.setSelectionRange(selectionStart, selectionEnd)
129
+
130
+ // Try using execCommand for cut
131
+ if (document.execCommand && document.queryCommandSupported('cut')) {
132
+ try {
133
+ const success = document.execCommand('cut')
134
+ if (success) {
135
+ triggerInputEvents(element)
136
+ }
137
+ } catch (error) {
138
+ console.log('execCommand cut failed:', error)
139
+ }
140
+ }
141
+ }
142
+ }
143
+
144
+ /**
145
+ * Handle select all operation
146
+ */
147
+ function handleSelectAll (element) {
148
+ if (!isInputElement(element)) return
149
+ element.select()
150
+ element.focus()
151
+ }
152
+
153
+ /**
154
+ * Create context menu items based on input state
155
+ */
156
+ function createContextMenuItems (element) {
157
+ const state = getInputState(element)
158
+ if (!state) return []
159
+
160
+ const { hasText, hasSelection, hasClipboard, isReadOnly } = state
161
+
162
+ return [
163
+ {
164
+ key: 'copy',
165
+ icon: 'CopyOutlined',
166
+ label: e('copy'),
167
+ disabled: !hasSelection
168
+ },
169
+ {
170
+ key: 'cut',
171
+ icon: 'FileExcelOutlined',
172
+ label: e('cut'),
173
+ disabled: !hasSelection || isReadOnly
174
+ },
175
+ {
176
+ key: 'paste',
177
+ icon: 'SwitcherOutlined',
178
+ label: e('paste'),
179
+ disabled: !hasClipboard || isReadOnly
180
+ },
181
+ {
182
+ key: 'selectAll',
183
+ icon: 'CheckSquareOutlined',
184
+ label: e('selectall'),
185
+ disabled: !hasText
186
+ }
187
+ ]
188
+ }
189
+
190
+ /**
191
+ * React Component for Input Context Menu
192
+ * Mount this component in your app to enable context menus on all input/textarea elements
193
+ */
194
+ const InputContextMenu = () => {
195
+ const [visible, setVisible] = useState(false)
196
+ const [position, setPosition] = useState({ x: 0, y: 0 })
197
+ const [targetElement, setTargetElement] = useState(null)
198
+ const menuRef = useRef(null)
199
+
200
+ const handleMenuClick = async ({ key }) => {
201
+ // Keep reference to current element before closing menu
202
+ const currentElement = targetElement
203
+ // Close menu first
204
+ setVisible(false)
205
+ setTargetElement(null)
206
+ // Execute action with preserved element reference
207
+ if (currentElement) {
208
+ setTimeout(async () => {
209
+ try {
210
+ switch (key) {
211
+ case 'copy':
212
+ handleCopy(currentElement)
213
+ break
214
+ case 'cut':
215
+ handleCut(currentElement)
216
+ break
217
+ case 'paste':
218
+ await handlePaste(currentElement)
219
+ break
220
+ case 'selectAll':
221
+ handleSelectAll(currentElement)
222
+ break
223
+ default:
224
+ console.warn('Unknown menu action:', key)
225
+ }
226
+ } catch (error) {
227
+ console.error('Menu action failed:', error)
228
+ }
229
+ }, 10) // Small delay to ensure menu is closed
230
+ }
231
+ }
232
+
233
+ useEffect(() => {
234
+ const handleContextMenu = (event) => {
235
+ const target = event.target
236
+ if (isInputElement(target)) {
237
+ event.preventDefault()
238
+ event.stopPropagation()
239
+ setPosition({ x: event.clientX, y: event.clientY })
240
+ setTargetElement(target)
241
+ setVisible(true)
242
+ } else {
243
+ setVisible(false)
244
+ setTargetElement(null)
245
+ }
246
+ }
247
+
248
+ const handleClick = (event) => {
249
+ if (visible && menuRef.current && !menuRef.current.contains(event.target)) {
250
+ setVisible(false)
251
+ setTargetElement(null)
252
+ }
253
+ }
254
+
255
+ document.addEventListener('contextmenu', handleContextMenu, true)
256
+ document.addEventListener('click', handleClick, true)
257
+ return () => {
258
+ document.removeEventListener('contextmenu', handleContextMenu, true)
259
+ document.removeEventListener('click', handleClick, true)
260
+ }
261
+ }, [visible])
262
+ const items = createContextMenuItems(targetElement) || []
263
+ const menuItems = items.map(item => {
264
+ const IconComponent = item.icon && iconsMap[item.icon]
265
+ return {
266
+ ...item,
267
+ icon: IconComponent ? <IconComponent /> : null
268
+ }
269
+ })
270
+ return (
271
+ <div
272
+ ref={menuRef}
273
+ style={{
274
+ position: 'fixed',
275
+ left: position.x,
276
+ top: position.y,
277
+ zIndex: 9999
278
+ }}
279
+ >
280
+ <Dropdown
281
+ menu={{
282
+ items: menuItems,
283
+ onClick: handleMenuClick
284
+ }}
285
+ open={visible}
286
+ placement='bottomLeft'
287
+ >
288
+ <div style={{ width: 1, height: 1 }} />
289
+ </Dropdown>
290
+ </div>
291
+ )
292
+ }
293
+
294
+ export default InputContextMenu
@@ -1,11 +1,10 @@
1
- @require '../../css/includes/theme-default'
2
1
  .transports-wrap
3
2
  position absolute
4
3
  left 60px
5
4
  top 3px
6
5
  right 60px
7
6
  height 36px
8
- color text
7
+
9
8
  .transports-circle-wrap
10
9
  text-align center
11
10
  position relative
@@ -16,7 +15,7 @@
16
15
  right 0
17
16
  overflow-y scroll
18
17
  z-index 11
19
- background main
18
+ background var(--main)
20
19
 
21
20
  .transports-wrap
22
21
  .transports-dd
@@ -25,7 +24,7 @@
25
24
  display block
26
25
 
27
26
  .transports-title
28
- border-bottom 1px solid primary
27
+ border-bottom 1px solid var(--primary)
29
28
  padding 10px 15px
30
29
  .transports-content
31
30
  max-height 200px
@@ -34,11 +33,10 @@
34
33
  display flex
35
34
  padding 8px 5px
36
35
  &:hover
37
- background main-dark
36
+ background var(--primary)
37
+ color var(--primary-contrast)
38
38
  .sftp-transport .transfer-control-icon:hover
39
- color primary
40
- .transports-count
41
- color text
39
+ color var(--primary)
42
40
 
43
41
  .flex-child + .flex-child
44
42
  margin-left 5px
@@ -1,13 +1,10 @@
1
- @require '../../css/includes/theme-default'
2
-
3
1
  .main-footer
4
- background main
2
+ background var(--main)
5
3
  height 36px
6
4
  position absolute
7
5
  left 44px
8
6
  right 0
9
7
  bottom 0
10
- color text
11
8
  z-index 200
12
9
  .pinned
13
10
  .main-footer
@@ -52,4 +49,4 @@
52
49
  right 0
53
50
  bottom 0
54
51
  z-index 100
55
- background main
52
+ background var(--main)
@@ -1,8 +1,7 @@
1
- @require '../../css/includes/theme-default'
2
1
  .layout-wrap
3
2
  .layout-item
4
3
  position absolute
5
- background main
4
+ background var(--main)
6
5
  overflow hidden
7
6
  &.drag-over
8
- border 2px solid #08c
7
+ border 2px solid var(--primary)
@@ -20,9 +20,9 @@ const troubleshootContent = {
20
20
  windows: 'path\\to\\electerm.exe'
21
21
  },
22
22
  clearConfig: {
23
- mac: 'rm -rf ~/Library/Application\\ Support/electerm/users/default_user/electerm.data.nedb',
24
- linux: 'rm -rf ~/.config/electerm/users/default_user/electerm.data.nedb',
25
- windows: 'Delete C:\\Users\\your-user-name\\AppData\\Roaming\\electerm\\users\\default_user\\electerm.data.nedb'
23
+ mac: 'rm -rf ~/Library/Application\\ Support/electerm/users/default_user/electerm_data.db && rm -rf ~/Library/Application\\ Support/electerm/users/default_user/electerm.data.nedb',
24
+ linux: 'rm -rf ~/.config/electerm/users/default_user/electerm_data.db && rm -rf ~/.config/electerm/users/default_user/electerm.data.nedb',
25
+ windows: 'Delete C:\\Users\\your-user-name\\AppData\\Roaming\\electerm\\users\\default_user\\electerm_data.db && Delete C:\\Users\\your-user-name\\AppData\\Roaming\\electerm\\users\\default_user\\electerm.data.nedb'
26
26
  },
27
27
  clearData: {
28
28
  mac: 'rm -rf ~/Library/Application\\ Support/electerm*',
@@ -29,6 +29,7 @@ import SshConfigLoadNotify from '../ssh-config/ssh-config-load-notify'
29
29
  import LoadSshConfigs from '../ssh-config/load-ssh-configs'
30
30
  import AIChat from '../ai/ai-chat'
31
31
  import Opacity from '../common/opacity'
32
+ import InputContextMenu from '../common/input-context-menu'
32
33
  import { pick } from 'lodash-es'
33
34
  import deepCopy from 'json-deep-copy'
34
35
  import './wrapper.styl'
@@ -248,6 +249,7 @@ export default auto(function Index (props) {
248
249
  theme={uiThemeConfig}
249
250
  >
250
251
  <div {...ext1}>
252
+ <InputContextMenu />
251
253
  <ShortcutControl config={config} />
252
254
  <TermFullscreenControl
253
255
  terminalFullScreen={terminalFullScreen}
@@ -260,7 +262,6 @@ export default auto(function Index (props) {
260
262
  <TerminalInteractive />
261
263
  <UiTheme
262
264
  {...themeProps}
263
- buildTheme={store.buildTheme}
264
265
  />
265
266
  <CustomCss customCss={config.customCss} />
266
267
  <TextEditor />
@@ -5,20 +5,60 @@
5
5
  import { useEffect } from 'react'
6
6
  import { useDelta, useConditionalEffect } from 'react-delta-hooks'
7
7
  import eq from 'fast-deep-equal'
8
+ import isColorDark from '../../common/is-color-dark'
8
9
 
9
10
  const themeDomId = 'theme-css'
10
11
 
12
+ function darker (color, amount = 0.1) {
13
+ let usePound = false
14
+
15
+ if (color[0] === '#') {
16
+ color = color.slice(1)
17
+ usePound = true
18
+ }
19
+
20
+ const num = parseInt(color, 16)
21
+
22
+ let r = (num >> 16) - Math.round(255 * amount)
23
+ if (r < 0) r = 0
24
+ let b = ((num >> 8) & 0x00FF) - Math.round(255 * amount)
25
+ if (b < 0) b = 0
26
+ let g = (num & 0x0000FF) - Math.round(255 * amount)
27
+ if (g < 0) g = 0
28
+
29
+ return (usePound ? '#' : '') + (g | (b << 8) | (r << 16)).toString(16)
30
+ }
31
+
32
+ function buildTheme (themeConfig) {
33
+ const keys = Object.keys(themeConfig || {})
34
+ const themeCss = keys.map(key => {
35
+ const val = themeConfig[key]
36
+ if (key === 'primary') {
37
+ const contrast = isColorDark(val) ? '#fff' : '#000'
38
+ return `--${key}-contrast: ${contrast};\n--${key}: ${val};`
39
+ } else if (key === 'main') {
40
+ const darkerMain = darker(val, 0.3)
41
+ const lighterMain = darker(val, -0.3)
42
+ return `--${key}-darker: ${darkerMain};\n--${key}-lighter: ${lighterMain};\n--${key}: ${val};`
43
+ }
44
+ return `--${key}: ${val};`
45
+ }).join('\n')
46
+ if (themeCss) {
47
+ const css = `:root {\n${themeCss}\n}\n`
48
+ return Promise.resolve(css)
49
+ }
50
+ return Promise.resolve('')
51
+ }
52
+
11
53
  export default function UiTheme (props) {
12
- const { themeConfig, buildTheme } = props
54
+ const { themeConfig } = props
13
55
 
14
56
  const delta = useDelta(themeConfig)
15
57
 
16
58
  async function applyTheme () {
17
- const stylus = document.getElementById(themeDomId)
18
- const {
19
- stylusCss
20
- } = await buildTheme(themeConfig)
21
- stylus.innerHTML = stylusCss
59
+ const style = document.getElementById(themeDomId)
60
+ const css = await buildTheme(themeConfig)
61
+ style.innerHTML = css
22
62
  }
23
63
 
24
64
  useEffect(() => {
@@ -1,13 +1,11 @@
1
- @require '../../css/includes/theme-default'
2
1
  .upgrade-panel
3
2
  position fixed
4
3
  right 10px
5
4
  bottom 10px
6
5
  z-index 9999
7
- background main
8
- color text
6
+ background var(--main)
9
7
  border-radius 5px
10
- border 1px solid darken(main, 30%)
8
+ border 1px solid var(--main-darker)
11
9
  padding 0
12
10
  width 440px
13
11
  .upgrade-panel-hide
@@ -17,12 +15,12 @@
17
15
  bottom auto
18
16
  .close-upgrade-panel
19
17
  &:hover
20
- color success
18
+ color var(--success)
21
19
  .upgrade-panel-title
22
20
  .upgrade-panel-body
23
21
  padding 10px 15px
24
22
  .upgrade-panel-title
25
- border-bottom 1px solid darken(main, 30%)
23
+ border-bottom 1px solid var(--main-darker)
26
24
  .markdown-wrap
27
25
  max-height 40vh
28
26
  overflow-y auto
@@ -1,4 +1,3 @@
1
- @require '../../css/includes/theme-default'
2
1
  .common-err-desc
3
2
  &:hover
4
3
  text-overflow clip
@@ -6,43 +5,22 @@
6
5
  white-space pre
7
6
  max-height 300px
8
7
  overflow scroll
9
- // .pinned .sessions
10
- // margin-left 343px
8
+
11
9
  .error-wrapper
12
- background main
10
+ background var(--main)
13
11
  height 100%
14
12
  position fixed
15
- color text
16
13
  overflow-y scroll
17
- .init-wrap
18
- .loading-data
19
- position fixed
20
- left 0
21
- top 0
22
- width 100%
23
- height 100%
24
- background-color main-light
25
- .loading-data
26
- text-align center
27
- font-size 30px
28
- color text
29
- padding 50px
30
- z-index 210
31
- .ant-tag
32
- border-radius 3px
33
- padding 4px
34
- font-size 14px
35
- .loaded
36
- .loading-data
37
- display none
38
14
 
39
15
  #container
16
+ .xterm
17
+ padding 10px
40
18
  .session-batch-active
41
19
  .xterm-screen
42
20
  &::before
43
21
  font-size 30vmin
44
22
  font-weight bold
45
- color lighten(text, 15%)
23
+ color var(--text)
46
24
  display flex
47
25
  justify-content center
48
26
  align-items center
@@ -1,13 +1,11 @@
1
- @require '../../css/includes/theme-default'
2
1
  .qm-list-wrap
3
2
  max-height calc(100vh - 100px)
4
3
  overflow-y scroll
5
4
  .qm-wrap-tooltip
6
- background main
5
+ background var(--main)
7
6
  position absolute
8
7
  left 43px
9
8
  right 0
10
- color text
11
9
  z-index 89
12
10
  height auto
13
11
  bottom 36px
@@ -21,7 +19,7 @@
21
19
  .fil-keyword
22
20
  .fil-label
23
21
  .qm-item
24
- color lighten(text, 30%)
22
+ color var(--text-light)
25
23
  .qm-item
26
24
  &.name-match
27
25
  &.label-match
@@ -31,4 +29,4 @@
31
29
  width 100px
32
30
 
33
31
  .item-list-unit.dragover
34
- border: 1px dashed primary
32
+ border: 1px dashed var(--primary)