@dvrd/dvr-controls 1.0.83 → 1.0.84
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/index.ts
CHANGED
|
@@ -53,7 +53,7 @@ import Link from './src/js/link/link';
|
|
|
53
53
|
import DvrdOptionsList from './src/js/optionsList/dvrdOptionsList';
|
|
54
54
|
import DvrdSelectController from './src/js/select/dvrdSelectController';
|
|
55
55
|
import DVRDGroupedSelect, { GroupedSelectRef } from './src/js/select/dvrdGroupedSelect';
|
|
56
|
-
import
|
|
56
|
+
import DVRDSwitch from './src/js/switch/dvrdSwitch';
|
|
57
57
|
import DvrdHeaderController from './src/js/header/v2/dvrdHeaderController';
|
|
58
58
|
import FileUpload from './src/js/fileUpload/fileUpload';
|
|
59
59
|
import DvrdRadioController from './src/js/radio/dvrdRadioController';
|
|
@@ -104,7 +104,7 @@ export {
|
|
|
104
104
|
DvrdOptionsList,
|
|
105
105
|
DvrdSelectController as DvrdSelect,
|
|
106
106
|
DVRDGroupedSelect,
|
|
107
|
-
|
|
107
|
+
DVRDSwitch,
|
|
108
108
|
DvrdHeaderController as DvrdHeader,
|
|
109
109
|
FileUpload,
|
|
110
110
|
DvrdRadioController as DvrdRadio,
|
package/package.json
CHANGED
|
@@ -5,10 +5,10 @@ import './style/sidebarMenu.scss';
|
|
|
5
5
|
|
|
6
6
|
import React, {MouseEventHandler, ReactNode, useContext, useEffect, useRef, useState} from 'react';
|
|
7
7
|
import {NavLink, useLocation} from 'react-router-dom';
|
|
8
|
-
import {SidebarItem, SideMenuMode} from
|
|
8
|
+
import {SidebarItem, SideMenuMode} from '../util/interfaces';
|
|
9
9
|
import classNames from 'classnames';
|
|
10
|
-
import {AwesomeIcon, generateComponentId, isAbsoluteLink} from
|
|
11
|
-
import {ControlContext} from
|
|
10
|
+
import {AwesomeIcon, generateComponentId, isAbsoluteLink} from '../../../index';
|
|
11
|
+
import {ControlContext} from '../util/controlContext';
|
|
12
12
|
import defer from 'lodash.defer';
|
|
13
13
|
import {IconName} from '@fortawesome/fontawesome-svg-core';
|
|
14
14
|
|
|
@@ -29,7 +29,7 @@ function getTopItems(items: SidebarItem[]): SidebarItem[] {
|
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
function getBottomItems(items: SidebarItem[]): SidebarItem[] {
|
|
32
|
-
return items.filter((item: SidebarItem) => item.onBottom)
|
|
32
|
+
return items.filter((item: SidebarItem) => item.onBottom);
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
function getActiveItem(items: SidebarItem[], pathname: string): SidebarItem | null {
|
|
@@ -52,7 +52,8 @@ function itemIsActive(item: SidebarItem, pathname: string): boolean {
|
|
|
52
52
|
|
|
53
53
|
function itemHasActiveId(item: SidebarItem, activeId: string): boolean {
|
|
54
54
|
if (item.id === activeId) return true;
|
|
55
|
-
else if (Array.isArray(item.children) && item.children.find(
|
|
55
|
+
else if (Array.isArray(item.children) && item.children.find(
|
|
56
|
+
(child: SidebarItem) => itemHasActiveId(child, activeId))) return true;
|
|
56
57
|
return false;
|
|
57
58
|
}
|
|
58
59
|
|
|
@@ -77,7 +78,7 @@ export default function SidebarMenu(props: Props) {
|
|
|
77
78
|
if (_route && !isAbsoluteLink(_route))
|
|
78
79
|
setActiveItem(item.id);
|
|
79
80
|
onClickItem(item)(evt);
|
|
80
|
-
}
|
|
81
|
+
};
|
|
81
82
|
}
|
|
82
83
|
|
|
83
84
|
function renderItem(isChild: boolean = false) {
|
|
@@ -87,11 +88,12 @@ export default function SidebarMenu(props: Props) {
|
|
|
87
88
|
cls = classNames(className, mode === SideMenuMode.COMPACT ? 'side-bar-item' : 'side-bar-item-full',
|
|
88
89
|
isChild && 'child', children !== undefined && 'with-children');
|
|
89
90
|
|
|
90
|
-
const content = (
|
|
91
|
+
const content = (active: boolean) => (
|
|
91
92
|
<>
|
|
92
|
-
{renderIcon(isChild, label, icon)}
|
|
93
|
-
{mode === SideMenuMode.COMPACT &&
|
|
94
|
-
|
|
93
|
+
{renderIcon(isChild, label, active, icon)}
|
|
94
|
+
{mode === SideMenuMode.COMPACT &&
|
|
95
|
+
<div className={classNames('active-indicator', active && 'active')}/>}
|
|
96
|
+
<span className={classNames('item-label', active && 'active')}>{label}</span>
|
|
95
97
|
{children !== undefined && (
|
|
96
98
|
<>
|
|
97
99
|
{isActive && <div className='line'/>}
|
|
@@ -103,15 +105,15 @@ export default function SidebarMenu(props: Props) {
|
|
|
103
105
|
|
|
104
106
|
if (asNavLink) return (
|
|
105
107
|
<NavLink key={id} to={item.route as string} className={cls} id={id}>
|
|
106
|
-
{content}
|
|
108
|
+
{({isActive}) => content(isActive)}
|
|
107
109
|
</NavLink>
|
|
108
110
|
);
|
|
109
111
|
return (
|
|
110
|
-
<div key={id} className={
|
|
111
|
-
{content}
|
|
112
|
+
<div key={id} className={cls} onClick={_onClickItem(item)} id={id}>
|
|
113
|
+
{content(isActive)}
|
|
112
114
|
</div>
|
|
113
|
-
)
|
|
114
|
-
}
|
|
115
|
+
);
|
|
116
|
+
};
|
|
115
117
|
}
|
|
116
118
|
|
|
117
119
|
function renderChildren(isActive: boolean) {
|
|
@@ -121,12 +123,12 @@ export default function SidebarMenu(props: Props) {
|
|
|
121
123
|
<div className='children-container' style={{display}}>
|
|
122
124
|
{children.map(renderItem(true))}
|
|
123
125
|
</div>
|
|
124
|
-
)
|
|
125
|
-
}
|
|
126
|
+
);
|
|
127
|
+
};
|
|
126
128
|
}
|
|
127
129
|
|
|
128
|
-
function renderIcon(isChild: boolean, label: string, icon?: IconName | ReactNode): ReactNode {
|
|
129
|
-
const className = 'item-icon'
|
|
130
|
+
function renderIcon(isChild: boolean, label: string, active: boolean, icon?: IconName | ReactNode): ReactNode {
|
|
131
|
+
const className = classNames('item-icon', active && 'active');
|
|
130
132
|
if (icon) {
|
|
131
133
|
if (typeof icon === 'string') return <AwesomeIcon name={icon as IconName} className={className}/>;
|
|
132
134
|
else if (React.isValidElement(icon))
|
|
@@ -135,7 +137,7 @@ export default function SidebarMenu(props: Props) {
|
|
|
135
137
|
}
|
|
136
138
|
if (label.length) {
|
|
137
139
|
if (isChild) return <span/>;
|
|
138
|
-
return <span className={classNames(className, 'letter')}>{label[0]}</span
|
|
140
|
+
return <span className={classNames(className, 'letter')}>{label[0]}</span>;
|
|
139
141
|
}
|
|
140
142
|
return null;
|
|
141
143
|
}
|
|
@@ -162,7 +164,7 @@ export default function SidebarMenu(props: Props) {
|
|
|
162
164
|
}, []);
|
|
163
165
|
|
|
164
166
|
useEffect(() => {
|
|
165
|
-
_setActiveItem()
|
|
167
|
+
_setActiveItem();
|
|
166
168
|
}, [location]);
|
|
167
169
|
|
|
168
170
|
return (
|
|
@@ -175,5 +177,5 @@ export default function SidebarMenu(props: Props) {
|
|
|
175
177
|
{getBottomItems(items).map(renderItem())}
|
|
176
178
|
</div>
|
|
177
179
|
</div>
|
|
178
|
-
)
|
|
180
|
+
);
|
|
179
181
|
}
|
|
@@ -34,6 +34,10 @@
|
|
|
34
34
|
color: $color-gray-4;
|
|
35
35
|
font-size: 1.5rem;
|
|
36
36
|
transition: color .2s ease-in-out;
|
|
37
|
+
|
|
38
|
+
&.active {
|
|
39
|
+
color: var(--base-color);
|
|
40
|
+
}
|
|
37
41
|
}
|
|
38
42
|
|
|
39
43
|
.item-label {
|
|
@@ -61,24 +65,18 @@
|
|
|
61
65
|
visibility: hidden;
|
|
62
66
|
opacity: 0;
|
|
63
67
|
transition: visibility .2s ease-in-out, opacity .2s ease-in-out;
|
|
64
|
-
}
|
|
65
68
|
|
|
66
|
-
|
|
67
|
-
.item-label {
|
|
69
|
+
&.active {
|
|
68
70
|
visibility: visible;
|
|
69
71
|
opacity: 1;
|
|
70
72
|
}
|
|
71
73
|
}
|
|
72
74
|
|
|
73
|
-
|
|
74
|
-
.
|
|
75
|
+
&:hover {
|
|
76
|
+
.item-label {
|
|
75
77
|
visibility: visible;
|
|
76
78
|
opacity: 1;
|
|
77
79
|
}
|
|
78
|
-
|
|
79
|
-
.item-icon {
|
|
80
|
-
color: var(--base-color);
|
|
81
|
-
}
|
|
82
80
|
}
|
|
83
81
|
}
|
|
84
82
|
|
|
@@ -119,11 +117,11 @@
|
|
|
119
117
|
transition: color .2s ease-in-out;
|
|
120
118
|
white-space: nowrap;
|
|
121
119
|
user-select: none;
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
120
|
+
|
|
121
|
+
&.active {
|
|
122
|
+
font-weight: 600;
|
|
123
|
+
color: black;
|
|
124
|
+
}
|
|
127
125
|
}
|
|
128
126
|
|
|
129
127
|
.line {
|
|
@@ -164,18 +162,6 @@
|
|
|
164
162
|
&.with-children {
|
|
165
163
|
margin-bottom: -.5rem;
|
|
166
164
|
}
|
|
167
|
-
|
|
168
|
-
&.active {
|
|
169
|
-
.item-icon {
|
|
170
|
-
color: var(--base-color);
|
|
171
|
-
opacity: 1;
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
.item-label {
|
|
175
|
-
font-weight: 600;
|
|
176
|
-
color: black;
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
165
|
}
|
|
180
166
|
}
|
|
181
167
|
}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
import './style/dvrdSwitch.scss';
|
|
5
5
|
|
|
6
6
|
import classNames from 'classnames';
|
|
7
|
-
import React, {useContext} from 'react';
|
|
7
|
+
import React, {useContext, useMemo} from 'react';
|
|
8
8
|
import {ControlContext} from "../util/controlContext";
|
|
9
9
|
import {convertColor} from "../util/colorUtil";
|
|
10
10
|
|
|
@@ -12,13 +12,29 @@ interface Props {
|
|
|
12
12
|
onChange: (value: boolean, evt?: React.MouseEvent | React.ChangeEvent) => void;
|
|
13
13
|
value: boolean;
|
|
14
14
|
className?: string;
|
|
15
|
+
labelClassName?: string;
|
|
15
16
|
disabled?: boolean;
|
|
16
17
|
activeColor?: string;
|
|
18
|
+
trackColor?: string;
|
|
19
|
+
baseColor?: string;
|
|
20
|
+
contrastColor?: string;
|
|
21
|
+
labels?: [string, string]; // Labels placed to the left and right of the switch
|
|
22
|
+
label?: string; // Label placed to the right of the switch
|
|
17
23
|
}
|
|
18
24
|
|
|
19
|
-
export default function
|
|
20
|
-
const context = useContext(ControlContext)
|
|
21
|
-
|
|
25
|
+
export default function DVRDSwitch(props: Props) {
|
|
26
|
+
const context = useContext(ControlContext);
|
|
27
|
+
const {
|
|
28
|
+
onChange, disabled, value, activeColor, labels, label, trackColor, baseColor, contrastColor,
|
|
29
|
+
labelClassName
|
|
30
|
+
} = props;
|
|
31
|
+
const className = useMemo(() => {
|
|
32
|
+
const names: Array<string | undefined> = ['dvrd-switch', props.className];
|
|
33
|
+
if (!!labels || !!label) names.push('with-labels');
|
|
34
|
+
if (value) names.push('active');
|
|
35
|
+
if (disabled) names.push('disabled');
|
|
36
|
+
return classNames(names);
|
|
37
|
+
}, [props.className, labels, label, value, disabled]);
|
|
22
38
|
|
|
23
39
|
function onToggle(evt: React.MouseEvent) {
|
|
24
40
|
if (!disabled)
|
|
@@ -27,10 +43,11 @@ export default function DvrdSwitch(props: Props) {
|
|
|
27
43
|
|
|
28
44
|
function getTrackColor(): string {
|
|
29
45
|
let color: string;
|
|
30
|
-
if (
|
|
46
|
+
if (trackColor) color = trackColor;
|
|
47
|
+
else if (disabled) color = 'color-gray-4';
|
|
31
48
|
else if (value) {
|
|
32
49
|
if (activeColor) color = activeColor;
|
|
33
|
-
else color = context.baseColor;
|
|
50
|
+
else color = baseColor ?? context.baseColor;
|
|
34
51
|
} else color = 'color-gray-7';
|
|
35
52
|
return convertColor(color);
|
|
36
53
|
}
|
|
@@ -38,16 +55,26 @@ export default function DvrdSwitch(props: Props) {
|
|
|
38
55
|
function getHandleColor(): string {
|
|
39
56
|
let color: string;
|
|
40
57
|
if (disabled) color = 'color-gray-3';
|
|
41
|
-
else color = context.contrastColor;
|
|
58
|
+
else color = contrastColor ?? context.contrastColor;
|
|
42
59
|
return convertColor(color);
|
|
43
60
|
}
|
|
44
61
|
|
|
62
|
+
function renderLabel(position?: 'left' | 'right') {
|
|
63
|
+
const _label = position === 'left' ? labels?.[0] : position === 'right' ? labels?.[1] : label;
|
|
64
|
+
if(!_label) return null;
|
|
65
|
+
return (
|
|
66
|
+
<label className={classNames('dvrd-switch-label', position, labelClassName)}>{_label}</label>
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
|
|
45
70
|
return (
|
|
46
|
-
<div className={
|
|
47
|
-
|
|
71
|
+
<div className={className} onClick={onToggle}>
|
|
72
|
+
{renderLabel('left')}
|
|
48
73
|
<div className='track' style={{backgroundColor: getTrackColor()}}>
|
|
49
74
|
<div className='handle' style={{backgroundColor: getHandleColor()}}/>
|
|
50
75
|
</div>
|
|
76
|
+
{renderLabel('right')}
|
|
77
|
+
{renderLabel()}
|
|
51
78
|
</div>
|
|
52
79
|
)
|
|
53
80
|
}
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
.dvrd-switch {
|
|
8
8
|
$track-height: 14px;
|
|
9
9
|
$handle-size: 18px;
|
|
10
|
+
cursor: pointer;
|
|
10
11
|
|
|
11
12
|
.track {
|
|
12
13
|
width: $handle-size * 1.3;
|
|
@@ -23,12 +24,21 @@
|
|
|
23
24
|
border-radius: 100%;
|
|
24
25
|
width: $handle-size;
|
|
25
26
|
height: $handle-size;
|
|
26
|
-
cursor: pointer;
|
|
27
27
|
transition: transform .2s ease-in-out, left .2s ease-in-out;
|
|
28
28
|
will-change: left;
|
|
29
29
|
}
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
+
.dvrd-switch-label {
|
|
33
|
+
user-select: none;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
&.with-labels {
|
|
37
|
+
display: flex;
|
|
38
|
+
column-gap: 1rem;
|
|
39
|
+
align-items: center;
|
|
40
|
+
}
|
|
41
|
+
|
|
32
42
|
&.active {
|
|
33
43
|
.track {
|
|
34
44
|
.handle {
|
|
@@ -38,10 +48,6 @@
|
|
|
38
48
|
}
|
|
39
49
|
|
|
40
50
|
&.disabled {
|
|
41
|
-
|
|
42
|
-
.handle {
|
|
43
|
-
cursor: default;
|
|
44
|
-
}
|
|
45
|
-
}
|
|
51
|
+
cursor: default;
|
|
46
52
|
}
|
|
47
53
|
}
|