@electerm/electerm-react 2.3.136 → 2.3.151

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.
@@ -11,9 +11,9 @@ import {
11
11
  Input,
12
12
  Button,
13
13
  Table,
14
- Drawer,
15
14
  Tabs
16
15
  } from 'antd'
16
+ import Drawer from '../common/drawer'
17
17
  import {
18
18
  sidebarWidth,
19
19
  statusMap,
@@ -672,15 +672,10 @@ export default class BatchOp extends PureComponent {
672
672
  const pops = {
673
673
  open: showBatchOp,
674
674
  onClose: this.handleCancel,
675
- className: 'setting-wrap',
675
+ className: 'setting-wrap batch-op-wrap',
676
676
  size: innerWidth - sidebarWidth,
677
677
  zIndex: 888,
678
- placement: 'left',
679
- styles: {
680
- header: {
681
- display: 'none'
682
- }
683
- }
678
+ placement: 'left'
684
679
  }
685
680
  return (
686
681
  <Drawer
@@ -1,6 +1,5 @@
1
1
  import React, { useState } from 'react'
2
- import { Popover } from 'antd'
3
- import { HexColorPicker, RgbaColorPicker } from 'react-colorful'
2
+ import { Popover, ColorPicker as AntColorPicker } from 'antd'
4
3
  import { defaultColors, getRandomHexColor } from '../../../common/rand-hex-color.js'
5
4
  import { HexInput } from './hex-input.jsx'
6
5
  import './color-picker.styl'
@@ -18,8 +17,11 @@ export const ColorPicker = React.forwardRef((props, ref) => {
18
17
  setVisible(vis)
19
18
  }
20
19
 
20
+ function onColorChange (color) {
21
+ handleChange(props.isRgba ? color.toRgbString() : color.toHexString())
22
+ }
23
+
21
24
  function renderContent () {
22
- const Picker = props.isRgba ? RgbaColorPicker : HexColorPicker
23
25
  return (
24
26
  <div className='color-picker-box'>
25
27
  <div className='fix'>
@@ -40,7 +42,10 @@ export const ColorPicker = React.forwardRef((props, ref) => {
40
42
  }
41
43
  </div>
42
44
  <div className='fright'>
43
- <Picker color={value} onChange={handleChange} />
45
+ <AntColorPicker
46
+ value={value}
47
+ onChange={onColorChange}
48
+ />
44
49
  </div>
45
50
  </div>
46
51
  <div className='pd1y'>
@@ -57,7 +62,13 @@ export const ColorPicker = React.forwardRef((props, ref) => {
57
62
  if (props.disabled) return inner
58
63
 
59
64
  return (
60
- <Popover content={renderContent()} trigger='click' open={visible} placement='bottomLeft' onOpenChange={handleVisibleChange}>
65
+ <Popover
66
+ content={renderContent()}
67
+ trigger='click'
68
+ open={visible}
69
+ placement='bottomLeft'
70
+ onOpenChange={handleVisibleChange}
71
+ >
61
72
  {inner}
62
73
  </Popover>
63
74
  )
@@ -10,8 +10,7 @@
10
10
  width 92px
11
11
  .color-picker-box
12
12
  width 420px
13
- .react-colorful
14
- height 200px
13
+
15
14
  .color-picker-defaults
16
15
  width 200px
17
16
  .color-picker-choose
@@ -180,6 +180,7 @@ export default function renderConnectionHopping (props) {
180
180
  form={formChild}
181
181
  onFinish={handleFinish}
182
182
  initialValues={initialValues}
183
+ component='div'
183
184
  >
184
185
  {renderList()}
185
186
  {renderWarn()}
@@ -219,6 +219,7 @@ export const commonFields = {
219
219
  export const terminalSettings = [
220
220
  commonFields.envLang,
221
221
  commonFields.terminalType,
222
+ commonFields.proxy,
222
223
  commonFields.displayRaw,
223
224
  commonFields.fontFamily,
224
225
  commonFields.fontSize,
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Simple drawer component without animation
3
+ * Replaces antd Drawer for better performance
4
+ */
5
+
6
+ import classnames from 'classnames'
7
+ import './drawer.styl'
8
+
9
+ export default function Drawer (props) {
10
+ const {
11
+ open,
12
+ placement = 'left',
13
+ size,
14
+ zIndex = 1000,
15
+ className,
16
+ children,
17
+ styles = {},
18
+ onClose
19
+ } = props
20
+
21
+ function handleMaskClick (e) {
22
+ if (e.target === e.currentTarget && onClose) {
23
+ onClose()
24
+ }
25
+ }
26
+
27
+ if (!open) {
28
+ return null
29
+ }
30
+
31
+ const drawerStyle = {
32
+ zIndex
33
+ }
34
+
35
+ const contentStyle = {
36
+ width: typeof size === 'number' ? `${size}px` : size,
37
+ ...styles.content
38
+ }
39
+
40
+ const cls = classnames(
41
+ 'custom-drawer',
42
+ `custom-drawer-${placement}`,
43
+ className
44
+ )
45
+
46
+ return (
47
+ <div className={cls} style={drawerStyle}>
48
+ <div
49
+ className='custom-drawer-mask'
50
+ onClick={handleMaskClick}
51
+ />
52
+ <div
53
+ className='custom-drawer-content-wrapper'
54
+ style={contentStyle}
55
+ >
56
+ <div className='custom-drawer-content'>
57
+ {children}
58
+ </div>
59
+ </div>
60
+ </div>
61
+ )
62
+ }
@@ -0,0 +1,34 @@
1
+ .custom-drawer
2
+ position fixed
3
+ top 0
4
+ left 43px
5
+ right 0
6
+ bottom 0
7
+
8
+ .custom-drawer-mask
9
+ position absolute
10
+ top 0
11
+ left 0
12
+ right 0
13
+ bottom 0
14
+ background rgba(0, 0, 0, 0.45)
15
+
16
+ .custom-drawer-content-wrapper
17
+ position absolute
18
+ top 0
19
+ bottom 0
20
+ background var(--main)
21
+ box-shadow 2px 0 8px rgba(0, 0, 0, 0.15)
22
+ overflow auto
23
+ color var(--text)
24
+
25
+ .custom-drawer-left .custom-drawer-content-wrapper
26
+ left 0
27
+
28
+ .custom-drawer-right .custom-drawer-content-wrapper
29
+ right 0
30
+
31
+ .custom-drawer-content
32
+ position relative
33
+ height 100%
34
+ width 100%
@@ -12,7 +12,7 @@ export default class ProfleFormIndex extends PureComponent {
12
12
  this.setState({
13
13
  ready: true
14
14
  })
15
- }, 200)
15
+ }, 0)
16
16
  }
17
17
 
18
18
  componentWillUnmount () {
@@ -20,11 +20,12 @@
20
20
  .fil-keyword
21
21
  .fil-label
22
22
  .qm-item
23
- color var(--text-light)
23
+ color var(--text-disabled)
24
24
  .qm-item
25
25
  &.name-match
26
26
  &.label-match
27
27
  font-weight bold
28
+ color var(--text)
28
29
 
29
30
  .qm-search-input
30
31
  max-width 200px
@@ -12,7 +12,7 @@ export default class QuickCommandFormIndex extends PureComponent {
12
12
  this.setState({
13
13
  ready: true
14
14
  })
15
- }, 200)
15
+ }, 0)
16
16
  }
17
17
 
18
18
  componentWillUnmount () {
@@ -29,7 +29,7 @@ export default class ItemList extends React.PureComponent {
29
29
  this.setState({
30
30
  ready: true
31
31
  })
32
- }, 200)
32
+ }, 0)
33
33
  }
34
34
 
35
35
  componentWillUnmount () {
@@ -66,7 +66,7 @@ export default class SettingCommon extends Component {
66
66
  this.setState({
67
67
  ready: true
68
68
  })
69
- }, 200)
69
+ }, 0)
70
70
  }
71
71
 
72
72
  componentWillUnmount () {
@@ -52,7 +52,7 @@ export default class SettingTerminal extends Component {
52
52
  this.setState({
53
53
  ready: true
54
54
  })
55
- }, 200)
55
+ }, 0)
56
56
  }
57
57
 
58
58
  componentWillUnmount () {
@@ -3,7 +3,7 @@
3
3
  */
4
4
 
5
5
  import { Component } from 'react'
6
- import { Drawer } from 'antd'
6
+ import Drawer from '../common/drawer'
7
7
  import { CloseCircleOutlined } from '@ant-design/icons'
8
8
  import { sidebarWidth } from '../../common/constants'
9
9
  import AppDrag from '../tabs/app-drag'
@@ -23,13 +23,7 @@ export default class SettingWrap extends Component {
23
23
  className: 'setting-wrap',
24
24
  size: this.props.innerWidth - sidebarWidth,
25
25
  zIndex: 888,
26
- placement: 'left',
27
- destroyOnHidden: true,
28
- styles: {
29
- header: {
30
- display: 'none'
31
- }
32
- }
26
+ placement: 'left'
33
27
  }
34
28
  return (
35
29
  <Drawer
@@ -40,13 +34,13 @@ export default class SettingWrap extends Component {
40
34
  onClick={this.props.onCancel}
41
35
  />
42
36
  <CloseCircleOutlined
43
- className='close-setting-wrap-icon alt-close-setting-wrap'
37
+ className='close-setting-wrap alt-close-setting-wrap'
44
38
  onClick={this.props.onCancel}
45
39
  />
46
40
  {
47
41
  this.props.useSystemTitleBar ? null : <AppDrag />
48
42
  }
49
- {this.props.visible ? this.props.children : null}
43
+ {this.props.children}
50
44
  </Drawer>
51
45
  )
52
46
  }
@@ -1,18 +1,20 @@
1
1
 
2
- body .ant-drawer .ant-drawer-content-wrapper
3
- left 43px
4
- .close-setting-wrap-icon
2
+
3
+ .close-setting-wrap
5
4
  position absolute
6
5
  top 70px
7
6
  font-size 16px
8
7
  cursor pointer
9
8
  z-index 889
9
+ right 20px
10
10
  &:hover
11
11
  color var(--success)
12
12
  .alt-close-setting-wrap
13
- right 20px
14
- .close-setting-wrap
15
- top 70px
13
+ left 20px
14
+ right auto
15
+ .batch-op-wrap .close-setting-wrap
16
+ top 40px
17
+ right 30px
16
18
  .setting-row
17
19
  position absolute
18
20
  top 127px
@@ -37,8 +37,9 @@ export default class ScrollFiles extends Component {
37
37
  current: this.state.page,
38
38
  pageSize: this.state.pageSize,
39
39
  total: this.props.list.length,
40
+ showLessItems: true,
40
41
  showSizeChanger: false,
41
- simple: true,
42
+ simple: false,
42
43
  onChange: this.onChange
43
44
  }
44
45
  return (
@@ -63,7 +63,7 @@ export default class Sftp extends Component {
63
63
  this.setState({
64
64
  ready: true
65
65
  })
66
- }, 100)
66
+ }, 0)
67
67
  }
68
68
 
69
69
  componentDidUpdate (prevProps, prevState) {
@@ -164,6 +164,19 @@
164
164
  .pager-wrap
165
165
  z-index 4
166
166
  position relative
167
+
168
+ .sftp-has-pager
169
+ .sftp-table-content
170
+ position static
171
+ padding-bottom 42px
172
+ .pager-wrap
173
+ position absolute
174
+ bottom 0
175
+ left 0
176
+ width 100%
177
+ background var(--main)
178
+ border-top 1px solid var(--main-darker)
179
+
167
180
  .file-header-context-menu
168
181
  position fixed
169
182
  z-index 999
@@ -1,17 +1,62 @@
1
- // render bookmark select, use antd tree select
1
+ // render bookmark select, use antd tree
2
2
  import { useState, useEffect } from 'react'
3
3
  import {
4
- MergeOutlined
4
+ MergeOutlined,
5
+ SearchOutlined
5
6
  } from '@ant-design/icons'
6
7
  import buildGroupData from '../bookmark-form/common/bookmark-group-tree-format'
7
- import { TreeSelect, Modal, Button } from 'antd'
8
+ import { Tree, Modal, Button, Input } from 'antd'
8
9
  import { auto } from 'manate/react'
9
10
  const e = window.translate
10
11
 
11
12
  const rootId = '__root__'
12
13
 
14
+ // Helper function to filter tree data based on search text
15
+ function filterTreeData (data, searchText) {
16
+ if (!searchText) {
17
+ return data
18
+ }
19
+ const lowerSearch = searchText.toLowerCase()
20
+
21
+ function filterNodes (nodes) {
22
+ return nodes.reduce((acc, node) => {
23
+ const titleText = typeof node.title === 'string'
24
+ ? node.title
25
+ : (node.title?.props?.children?.[1] || node.title?.props?.children || '')
26
+ const titleStr = String(titleText).toLowerCase()
27
+ const children = node.children ? filterNodes(node.children) : []
28
+
29
+ if (titleStr.includes(lowerSearch) || children.length > 0) {
30
+ acc.push({
31
+ ...node,
32
+ children: children.length > 0 ? children : node.children
33
+ })
34
+ }
35
+ return acc
36
+ }, [])
37
+ }
38
+
39
+ return filterNodes(data)
40
+ }
41
+
42
+ // Helper function to get all keys from tree data
43
+ function getAllKeys (data) {
44
+ const keys = []
45
+ function traverse (nodes) {
46
+ for (const node of nodes) {
47
+ keys.push(node.key)
48
+ if (node.children) {
49
+ traverse(node.children)
50
+ }
51
+ }
52
+ }
53
+ traverse(data)
54
+ return keys
55
+ }
56
+
13
57
  export default auto(function MoveItemModal (props) {
14
58
  const [groupId, setGroupId] = useState(undefined)
59
+ const [searchText, setSearchText] = useState('')
15
60
  const {
16
61
  openMoveModal,
17
62
  moveItem,
@@ -27,10 +72,11 @@ export default auto(function MoveItemModal (props) {
27
72
  })
28
73
  }
29
74
 
30
- // Reset groupId when modal opens
75
+ // Reset groupId and search when modal opens
31
76
  useEffect(() => {
32
77
  if (openMoveModal) {
33
78
  setGroupId(undefined)
79
+ setSearchText('')
34
80
  }
35
81
  }, [openMoveModal])
36
82
 
@@ -60,6 +106,31 @@ export default auto(function MoveItemModal (props) {
60
106
  disabled: false
61
107
  })
62
108
  }
109
+
110
+ // Filter tree data based on search
111
+ const filteredData = filterTreeData(data, searchText)
112
+ const expandedKeys = getAllKeys(filteredData)
113
+
114
+ function onTreeSelect (selectedKeys) {
115
+ if (selectedKeys.length > 0) {
116
+ // Find the node to check if it's disabled
117
+ const findNode = (nodes, key) => {
118
+ for (const node of nodes) {
119
+ if (node.key === key) return node
120
+ if (node.children) {
121
+ const found = findNode(node.children, key)
122
+ if (found) return found
123
+ }
124
+ }
125
+ return null
126
+ }
127
+ const node = findNode(data, selectedKeys[0])
128
+ if (node && !node.disabled) {
129
+ setGroupId(selectedKeys[0])
130
+ }
131
+ }
132
+ }
133
+
63
134
  function onSelect () {
64
135
  const {
65
136
  bookmarkGroups
@@ -109,43 +180,56 @@ export default auto(function MoveItemModal (props) {
109
180
  }
110
181
  onCancelMoveItem()
111
182
  }
183
+
184
+ const footer = (
185
+ <>
186
+ <Button
187
+ type='primary'
188
+ onClick={onSelect}
189
+ disabled={!groupId}
190
+ >
191
+ {e('ok')}
192
+ </Button>
193
+ <Button
194
+ onClick={onCancelMoveItem}
195
+ className='mg1l'
196
+ >
197
+ {e('cancel')}
198
+ </Button>
199
+ </>
200
+ )
201
+
112
202
  const modalProps = {
113
203
  open: openMoveModal,
114
204
  title: e('moveTo'),
115
- footer: null,
205
+ footer,
116
206
  onCancel: onCancelMoveItem
117
207
  }
208
+
118
209
  const treeProps = {
119
- treeData: data,
120
- onChange: setGroupId,
121
- placeholder: e('moveTo'),
122
- showSearch: true,
123
- value: groupId,
124
- popupMatchSelectWidth: false,
125
- treeDefaultExpandAll: true,
126
- className: 'width-100'
210
+ treeData: filteredData,
211
+ onSelect: onTreeSelect,
212
+ selectedKeys: groupId ? [groupId] : [],
213
+ expandedKeys,
214
+ autoExpandParent: true,
215
+ className: 'width-100 move-item-tree'
127
216
  }
217
+
128
218
  return (
129
219
  <Modal {...modalProps}>
130
- <div className='pd1'>
131
- <TreeSelect
132
- {...treeProps}
220
+ <div className='pd1b'>
221
+ <Input
222
+ placeholder={e('search')}
223
+ prefix={<SearchOutlined />}
224
+ value={searchText}
225
+ onChange={e => setSearchText(e.target.value)}
226
+ allowClear
133
227
  />
134
228
  </div>
135
- <div className='pd1'>
136
- <Button
137
- type='primary'
138
- onClick={onSelect}
139
- disabled={!groupId}
140
- >
141
- {e('ok')}
142
- </Button>
143
- <Button
144
- onClick={onCancelMoveItem}
145
- className='mg1l'
146
- >
147
- {e('cancel')}
148
- </Button>
229
+ <div className='move-item-tree-wrap'>
230
+ <Tree
231
+ {...treeProps}
232
+ />
149
233
  </div>
150
234
  </Modal>
151
235
  )
@@ -55,7 +55,7 @@ export default class ItemListTree extends Component {
55
55
  this.setState({
56
56
  ready: true
57
57
  })
58
- }, 100)
58
+ }, 0)
59
59
  }
60
60
 
61
61
  componentWillUnmount () {
@@ -78,4 +78,9 @@
78
78
  margin-right 6px
79
79
  border-radius 2px
80
80
  border 1px solid #1a1a1a
81
- vertical-align middle
81
+ vertical-align middle
82
+
83
+ .move-item-tree-wrap
84
+ max-height 300px
85
+ overflow-y auto
86
+ padding 8px
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@electerm/electerm-react",
3
- "version": "2.3.136",
3
+ "version": "2.3.151",
4
4
  "description": "react components src for electerm",
5
5
  "main": "./client/components/main/main.jsx",
6
6
  "license": "MIT",