@gm-pc/react 1.7.1 → 1.8.0-alpha.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gm-pc/react",
3
- "version": "1.7.1",
3
+ "version": "1.8.0-alpha.1",
4
4
  "description": "观麦前端基础组件库",
5
5
  "author": "liyatang <liyatang@qq.com>",
6
6
  "homepage": "https://github.com/gmfe/gm-pc#readme",
@@ -24,7 +24,7 @@
24
24
  "dependencies": {
25
25
  "@gm-common/hooks": "^2.10.0",
26
26
  "@gm-common/tool": "^2.10.0",
27
- "@gm-pc/locales": "^1.7.1",
27
+ "@gm-pc/locales": "^1.8.0-alpha.1",
28
28
  "big.js": "^6.0.1",
29
29
  "classnames": "^2.2.5",
30
30
  "lodash": "^4.17.19",
@@ -46,5 +46,5 @@
46
46
  "react-dom": "^16.14.0",
47
47
  "react-window": "^1.8.5"
48
48
  },
49
- "gitHead": "f8875bd29bb3261e9d9d835fb579d2a0d537abe8"
49
+ "gitHead": "9bce7f92e1098221071c39a89a77d6080e5909b0"
50
50
  }
@@ -10,10 +10,13 @@ const Nav: FC<NavProps> = ({
10
10
  data,
11
11
  selected,
12
12
  onSelect,
13
+ onPushCreate,
13
14
  showActive,
14
15
  other,
15
16
  className,
16
17
  style,
18
+ footerImage,
19
+ footerConfig,
17
20
  ...rest
18
21
  }) => {
19
22
  // 根据鼠标点到导航栏右边的线距离,判断移动方向
@@ -83,10 +86,25 @@ const Nav: FC<NavProps> = ({
83
86
  data={one}
84
87
  selected={selected}
85
88
  onSelect={onSelect}
89
+ onPushCreate={onPushCreate}
86
90
  />
87
91
  ))}
88
92
  {other}
89
93
  </Flex>
94
+ <div className='gm-nav-footer-iot'>
95
+ {footerConfig?.map((item) => (
96
+ <NavItem
97
+ key={item.link}
98
+ showSub={hoverLink === item.link}
99
+ onMouseMove={handleMouseMove}
100
+ data={item}
101
+ selected={selected}
102
+ onSelect={onSelect}
103
+ onPushCreate={onPushCreate}
104
+ footerImage={footerImage}
105
+ />
106
+ ))}
107
+ </div>
90
108
  <div id='gmNavPopupContainer' />
91
109
  </Flex>
92
110
  )
@@ -19,7 +19,9 @@ const NavItem: FC<NavItemProps> = ({
19
19
  selected,
20
20
  onSelect,
21
21
  onMouseMove,
22
+ onPushCreate,
22
23
  showSub,
24
+ footerImage,
23
25
  }) => {
24
26
  const ref = useRef<HTMLDivElement>(null)
25
27
  const [rect, setRect] = useState<DOMRect | null>(null)
@@ -47,6 +49,10 @@ const NavItem: FC<NavItemProps> = ({
47
49
  setRect(null)
48
50
  }
49
51
 
52
+ const handlePushCreate = (data: NavDataLevel2) => {
53
+ onPushCreate(data)
54
+ }
55
+
50
56
  let iconE = icon
51
57
  if ((rect || active) && iconActive) {
52
58
  iconE = iconActive
@@ -54,15 +60,22 @@ const NavItem: FC<NavItemProps> = ({
54
60
 
55
61
  return (
56
62
  <div ref={ref} className={classNames('gm-nav-one-box', { active, hover: !!rect })}>
57
- <A
58
- href={link}
59
- className='gm-nav-one'
60
- onClick={handleClick}
61
- onMouseMove={(e) => onMouseMove(e, link)}
62
- >
63
- <span className='gm-nav-one-icon'>{iconE}</span>
64
- <span className='gm-nav-one-text'>{name}</span>
65
- </A>
63
+ {footerImage ? (
64
+ <A href={link} onClick={handleClick} onMouseMove={(e) => onMouseMove(e, link)}>
65
+ {footerImage}
66
+ </A>
67
+ ) : (
68
+ <A
69
+ href={link}
70
+ className='gm-nav-one'
71
+ onClick={handleClick}
72
+ onMouseMove={(e) => onMouseMove(e, link)}
73
+ >
74
+ <span className='gm-nav-one-icon'>{iconE}</span>
75
+ <span className='gm-nav-one-text'>{name}</span>
76
+ </A>
77
+ )}
78
+
66
79
  {sub && <div className='gm-nav-one-triangle' />}
67
80
  {sub && (
68
81
  <Portal>
@@ -72,6 +85,7 @@ const NavItem: FC<NavItemProps> = ({
72
85
  data={sub}
73
86
  selected={selected}
74
87
  onSelect={handleSelect}
88
+ onPushCreate={handlePushCreate}
75
89
  />
76
90
  )}
77
91
  </Portal>
@@ -1,10 +1,16 @@
1
- import React, { FC, useLayoutEffect, useRef, useState } from 'react'
1
+ import React, { FC, MouseEventHandler, useLayoutEffect, useRef, useState } from 'react'
2
2
  import { PopupProps } from './types'
3
3
  import classNames from 'classnames'
4
4
  import { Flex } from '../flex'
5
5
  import A from './a'
6
6
 
7
- const Popup: FC<PopupProps> = ({ parentRect, data, selected, onSelect }) => {
7
+ const Popup: FC<PopupProps> = ({
8
+ parentRect,
9
+ data,
10
+ selected,
11
+ onSelect,
12
+ onPushCreate,
13
+ }) => {
8
14
  const refDom = useRef<HTMLDivElement>(null)
9
15
  const [marginTop, setMarginTop] = useState(0)
10
16
 
@@ -16,31 +22,69 @@ const Popup: FC<PopupProps> = ({ parentRect, data, selected, onSelect }) => {
16
22
  }
17
23
  }, [parentRect])
18
24
 
25
+ // 获取不同数量二级菜单的宽度
26
+ const setPopupWidth = (number: number): string => {
27
+ const baseWidth = 212
28
+ const arr: number[] = []
29
+ for (let i = 1; i < 20; i++) {
30
+ arr.push(baseWidth + i * 172)
31
+ }
32
+ const widthArray = [baseWidth].concat(arr).map((i) => i + 'px')
33
+ return widthArray[number - 1]
34
+ }
35
+
36
+ const handleMouseEnter: MouseEventHandler<HTMLDivElement> = (e) => {
37
+ e.currentTarget.classList.add('gm-nav-three-wrap-bg')
38
+ }
39
+
40
+ const handleMouseLeave: MouseEventHandler<HTMLDivElement> = (e) => {
41
+ e.currentTarget.classList.remove('gm-nav-three-wrap-bg')
42
+ }
43
+
19
44
  return (
20
45
  <div
21
46
  ref={refDom}
22
47
  className='gm-nav-popup'
23
- style={{ marginTop: `${marginTop}px`, top: parentRect.top }}
48
+ style={{
49
+ marginTop: `${marginTop}px`,
50
+ top: parentRect.top,
51
+ width: `${setPopupWidth(data.length)}`,
52
+ maxWidth: '900px',
53
+ }}
24
54
  >
25
- <Flex>
55
+ <Flex wrap>
26
56
  {data.map((v, i) => (
27
57
  <div key={i} className='gm-nav-two' style={v.style}>
28
58
  {!!v.name && <div className='gm-nav-two-title'>{v.name}</div>}
29
59
  <div>
30
60
  {v.sub.map((s, si) => (
31
- <A
32
- key={si}
33
- href={s.link}
34
- className={classNames('gm-nav-three', {
61
+ <div
62
+ className={classNames('gm-nav-three-wrap', {
35
63
  active: selected.startsWith(s.link),
36
64
  })}
37
- onClick={(event) => {
38
- event.preventDefault()
39
- onSelect(s)
40
- }}
65
+ key={si}
66
+ onMouseEnter={handleMouseEnter}
67
+ onMouseLeave={handleMouseLeave}
41
68
  >
42
- {s.name}
43
- </A>
69
+ <A
70
+ key={si}
71
+ href={s.link}
72
+ className='gm-nav-three'
73
+ onClick={(event) => {
74
+ event.preventDefault()
75
+ onSelect(s)
76
+ }}
77
+ >
78
+ {s.name}
79
+ </A>
80
+ {s.toCreate && (
81
+ <span
82
+ className='gm-nav-three-create'
83
+ title={s.toCreate.tip}
84
+ onClick={() => onPushCreate(s)}
85
+ />
86
+ )}
87
+ </div>
44
88
  ))}
45
89
  </div>
46
90
  </div>
@@ -1,19 +1,24 @@
1
+ :root {
2
+ --gm-nav-popup-item-color: #454545;
3
+ --gm-nav-popup-item-hover-color: #0363ff;
4
+ --gm-nav-background-color: #282c36;
5
+ }
6
+
1
7
  .gm-nav {
2
8
  width: var(--gm-nav-size-width);
3
9
  height: 100vh;
4
- background: #243351;
10
+ background: var(--gm-nav-background-color);
5
11
 
6
12
  .gm-nav-logo {
7
- text-align: center;
8
- height: 60px;
9
13
  display: flex;
10
14
  align-content: center;
11
15
  justify-content: center;
16
+ height: 64px;
17
+ text-align: center;
12
18
  cursor: pointer;
13
-
14
- &:hover {
15
- background: #17233d;
16
- }
19
+ background-color: #fff;
20
+ padding-bottom: 4px;
21
+ box-shadow: inset -1px 0 0 0 #e8ecf3;
17
22
  }
18
23
 
19
24
  .gm-nav-content {
@@ -25,54 +30,150 @@
25
30
  }
26
31
  }
27
32
 
33
+ .gm-nav-footer-iot {
34
+ width: 100%;
35
+ height: 64px;
36
+ cursor: pointer;
37
+ }
38
+
28
39
  .gm-nav-one {
29
- height: 50px;
30
- padding-left: 20px;
31
- text-decoration: none;
32
- color: rgba(255, 255, 255, 80%);
33
40
  display: flex;
34
41
  align-items: center;
35
- opacity: 0.8;
42
+ position: relative;
43
+ padding: 16px 20px;
44
+ color: #fff;
45
+ text-decoration: none;
36
46
 
37
47
  .gm-nav-one-icon {
48
+ margin-right: 10px;
38
49
  font-size: 18px;
39
50
  line-height: 1;
40
- margin-right: 6px;
41
51
  }
42
52
 
43
53
  .gm-nav-one-text {
44
- font-size: 14px;
54
+ font-size: 16px;
55
+ }
56
+
57
+ &::after {
58
+ content: '';
59
+ position: absolute;
60
+ right: 20px;
61
+ top: 21px;
62
+ height: 7px;
63
+ width: 7px;
64
+ border: 1px solid #fff;
65
+ opacity: 0.36;
66
+ border-top: none;
67
+ border-left: none;
68
+ transform: rotate(-45deg);
45
69
  }
46
70
  }
47
71
 
48
72
  .gm-nav-popup {
49
- color: var(--gm-color-default);
50
- background: white;
51
73
  position: absolute;
52
74
  top: 0;
53
75
  left: var(--gm-nav-size-width);
54
- box-shadow: 1px 1px 6px 1px rgba(36, 51, 81, 0.2);
76
+ padding: 24px 8px 0 32px;
77
+ color: var(--gm-color-default);
78
+ background: #fff;
79
+ box-shadow: 0 0 10px 0 rgba(0, 0, 0, 0.3);
80
+
81
+ .gm-nav-two {
82
+ min-width: 148px;
83
+ margin-right: 24px;
84
+ margin-bottom: 24px;
85
+
86
+ .gm-nav-two-title {
87
+ margin-bottom: 16px;
88
+ font-size: 16px;
89
+ font-weight: 600;
90
+ color: var(--gm-nav-popup-item-color);
91
+ }
92
+ }
93
+
94
+ .gm-nav-three-wrap {
95
+ position: relative;
96
+ margin-bottom: 8px;
97
+ background: #f7f7f7;
98
+
99
+ &.gm-nav-three-wrap-bg {
100
+ background-color: #dae7ff;
101
+ }
102
+
103
+ &.active {
104
+ color: var(--gm-color-primary-active);
105
+ background-color: #dae7ff;
106
+ }
107
+
108
+ .gm-nav-three {
109
+ display: inline-block;
110
+ padding: 8px;
111
+ // width: 100%;
112
+ font-size: 14px;
113
+ color: var(--gm-color-default);
114
+ text-decoration: none;
115
+ white-space: nowrap;
116
+ border-radius: 2px;
117
+
118
+ &:last-child {
119
+ margin-bottom: 0;
120
+ }
121
+
122
+ &:hover {
123
+ color: var(--gm-nav-popup-item-hover-color);
124
+ background-color: #dae7ff;
125
+ }
126
+
127
+ span {
128
+ font-size: 18px;
129
+ color: #99999a;
130
+ cursor: pointer;
131
+
132
+ &:hover {
133
+ color: var(--gm-nav-popup-item-hover-color);
134
+ }
135
+ }
136
+ }
137
+
138
+ .gm-nav-three-create {
139
+ position: absolute;
140
+ top: 7px;
141
+ right: 4px;
142
+ z-index: 10;
143
+ width: 20px;
144
+ height: 20px;
145
+ background-image: url(../../images/add.png);
146
+ background-size: cover;
147
+ cursor: pointer;
148
+
149
+ &:hover {
150
+ background-image: url(../../images/add-hover.png);
151
+ }
152
+ }
153
+ }
55
154
  }
56
155
 
156
+ // 第一级 item
57
157
  .gm-nav-one-box {
58
158
  position: relative;
59
159
 
160
+ // 三角形
60
161
  .gm-nav-one-triangle {
61
- display: none;
62
162
  position: absolute;
163
+ top: 19px;
164
+ right: -1px;
165
+ display: none;
63
166
  width: 0;
64
167
  height: 0;
65
168
  border: 6px solid transparent;
66
169
  border-right: 6px solid white;
67
- top: 18px;
68
- right: -1px;
69
170
  }
70
171
 
71
172
  &.hover {
72
173
  .gm-nav-one {
73
174
  color: white;
175
+ background-color: #1c2129;
74
176
  opacity: 1;
75
- background: rgba(40, 113, 187, 0.4);
76
177
  }
77
178
 
78
179
  .gm-nav-one-triangle {
@@ -82,9 +183,35 @@
82
183
 
83
184
  &.active {
84
185
  .gm-nav-one {
85
- color: white;
186
+ position: relative;
187
+ color: #fff;
188
+ background: #181b23;
86
189
  opacity: 1;
87
- background: rgba(40, 113, 187, 1);
190
+ font-weight: 600;
191
+
192
+ &::before {
193
+ content: '';
194
+ position: absolute;
195
+ left: 0;
196
+ top: 0;
197
+ height: 100%;
198
+ width: 3px;
199
+ background-color: #0363ff;
200
+ }
201
+
202
+ &::after {
203
+ content: '';
204
+ position: absolute;
205
+ right: 20px;
206
+ top: 22px;
207
+ height: 7px;
208
+ width: 7px;
209
+ border: 1px solid #fff;
210
+ opacity: 1;
211
+ border-top: none;
212
+ border-left: none;
213
+ transform: rotate(-45deg);
214
+ }
88
215
  }
89
216
 
90
217
  .gm-nav-one-triangle {
@@ -92,40 +219,4 @@
92
219
  }
93
220
  }
94
221
  }
95
-
96
- .gm-nav-two {
97
- min-width: 110px;
98
- padding: 20px 10px 20px;
99
-
100
- .gm-nav-two-title {
101
- color: var(--gm-color-default);
102
- padding: 0 0 10px;
103
- font-weight: 600;
104
- font-size: 14px;
105
- border-bottom: 1px solid #f0f1f3;
106
- margin: 0 10px 8px;
107
- }
108
- }
109
-
110
- .gm-nav-three {
111
- display: block;
112
- padding: 0 10px;
113
- margin: 2px 0;
114
- font-size: 14px;
115
- line-height: 30px;
116
- text-decoration: none;
117
- color: var(--gm-color-default);
118
- border-radius: 2px;
119
- white-space: nowrap;
120
-
121
- &:hover {
122
- color: var(--gm-color-primary);
123
- background-color: var(--gm-color-bg-back);
124
- }
125
-
126
- &.active {
127
- color: var(--gm-color-primary-active);
128
- background-color: var(--gm-color-bg-back);
129
- }
130
- }
131
222
  }
@@ -1,8 +1,12 @@
1
- import { CSSProperties, ReactNode, MouseEvent } from 'react'
1
+ import React, { CSSProperties, ReactNode, MouseEvent, ReactElement } from 'react'
2
2
 
3
3
  interface NavDataLevel3 {
4
4
  link: string
5
5
  name: string
6
+ toCreate?: {
7
+ tip: string
8
+ href: string
9
+ }
6
10
  }
7
11
 
8
12
  interface NavDataLevel2 {
@@ -28,21 +32,28 @@ interface NavProps {
28
32
  selected: string
29
33
  /** 如果是选中一二级,会直接返回改分级下第三级的 item */
30
34
  onSelect(data: NavDataLevel3): void
35
+ /** 直接到达新建页面 */
36
+ onPushCreate(data: NavDataLevel3): void
31
37
  /** 控制 浮层的线上,如商品库传 merchandise */
32
38
  showActive?: string
33
39
  other?: ReactNode
34
40
  className?: string
35
41
  style?: CSSProperties
42
+ // 底部 iot 图片 & 数据
43
+ footerImage?: ReactNode
44
+ footerConfig?: NavData[]
36
45
  }
37
46
 
38
47
  interface NavItemProps {
39
48
  data: NavData
40
49
  selected: string
41
50
  onSelect(data: NavDataLevel3): void
51
+ onPushCreate(data: NavDataLevel3): void
42
52
  /** onMouseMove 的回调 */
43
53
  onMouseMove(event: MouseEvent, link: string): void
44
54
  /** 控制子导航列表的显示 */
45
55
  showSub?: boolean
56
+ footerImage?: ReactNode
46
57
  }
47
58
 
48
59
  interface PopupProps {
@@ -50,6 +61,7 @@ interface PopupProps {
50
61
  data: NavDataLevel2[]
51
62
  selected: string
52
63
  onSelect(data: NavDataLevel3): void
64
+ onPushCreate(data: NavDataLevel3): void
53
65
  }
54
66
 
55
67
  type NavSingleItemData = Omit<NavData, 'sub'>
@@ -54,11 +54,12 @@ const Right: FC<PaginationProps> = ({ paging, onChange }) => {
54
54
  }
55
55
  }
56
56
 
57
- const all = Math.ceil((paging.count || 0) / paging.limit)
57
+ const all = Math.ceil((paging.count || 1) / paging.limit)
58
58
 
59
59
  return (
60
60
  <Flex className='gm-pagination-right'>
61
61
  <InputNumber
62
+ disabled={all <= 1}
62
63
  precision={0}
63
64
  value={index}
64
65
  onChange={handleInput}
@@ -1,5 +1,4 @@
1
1
  .gm-tabs {
2
-
3
2
  .gm-tabs-head-fix {
4
3
  width: 100%;
5
4
  height: 40px;
@@ -25,17 +24,6 @@
25
24
  border-top-left-radius: 4px;
26
25
  border-top-right-radius: 4px;
27
26
 
28
- &::before {
29
- position: absolute;
30
- width: 100%;
31
- content: ' ';
32
- height: 2px;
33
- right: 0;
34
- bottom: 0 !important;
35
- z-index: 99;
36
- background-color: #fff;
37
- }
38
-
39
27
  &.active {
40
28
  background: white;
41
29
  border-left: 1px solid var(--gm-color-border);
@@ -57,10 +45,9 @@
57
45
  cursor: pointer;
58
46
  line-height: 28px;
59
47
  margin-left: 16px;
60
- transition: all .3s cubic-bezier(.645, .045, .355, 1);
48
+ transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
61
49
  }
62
50
 
63
-
64
51
  .gm-tabs-text-overflow-ellipsis {
65
52
  max-width: 150px;
66
53
  overflow: hidden;
@@ -140,7 +127,6 @@
140
127
 
141
128
  // 可编辑风格样式
142
129
  .gm-tabs-edit {
143
-
144
130
  .gm-tabs-head {
145
131
  background: #fff !important;
146
132
  padding: 0;
@@ -157,8 +143,7 @@
157
143
  &.active {
158
144
  color: #1890ff;
159
145
  box-sizing: border-box;
160
-
161
146
  }
162
147
  }
163
148
  }
164
- }
149
+ }
@@ -96,7 +96,7 @@
96
96
 
97
97
  // 具体业务
98
98
  // nav
99
- --gm-nav-size-width: 92px;
99
+ --gm-nav-size-width: 136px;
100
100
  // modal
101
101
  --gm-modal-size-title-height: 40px;
102
102
  // switch
Binary file
Binary file