@dvrd/dvr-controls 1.0.83 → 1.0.85

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 DvrdSwitch from './src/js/switch/dvrdSwitch';
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
- DvrdSwitch,
107
+ DVRDSwitch,
108
108
  DvrdHeaderController as DvrdHeader,
109
109
  FileUpload,
110
110
  DvrdRadioController as DvrdRadio,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dvrd/dvr-controls",
3
- "version": "1.0.83",
3
+ "version": "1.0.85",
4
4
  "description": "Custom web controls",
5
5
  "main": "index.ts",
6
6
  "files": [
@@ -47,7 +47,6 @@
47
47
  "@types/react": "^18.2.28",
48
48
  "@types/react-color": "2.13.5",
49
49
  "@types/react-dom": "^18.0.11",
50
- "@types/swiper": "^6.0.0",
51
50
  "@types/uuid": "9.0.0",
52
51
  "classnames": "2.5.1",
53
52
  "dompurify": "3.0.0",
@@ -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 "../util/interfaces";
8
+ import {SidebarItem, SideMenuMode} from '../util/interfaces';
9
9
  import classNames from 'classnames';
10
- import {AwesomeIcon, generateComponentId, isAbsoluteLink} from "../../../index";
11
- import {ControlContext} from "../util/controlContext";
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((child: SidebarItem) => itemHasActiveId(child, activeId))) return true;
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 && <div className='active-indicator'/>}
94
- <span className='item-label'>{label}</span>
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={classNames(cls, isActive && 'active')} onClick={_onClickItem(item)} id={id}>
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
- &:hover {
67
- .item-label {
69
+ &.active {
68
70
  visibility: visible;
69
71
  opacity: 1;
70
72
  }
71
73
  }
72
74
 
73
- &.active {
74
- .active-indicator {
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
- //&.active {
124
- // font-weight: 600;
125
- // color: black;
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 DvrdSwitch(props: Props) {
20
- const context = useContext(ControlContext),
21
- {className, onChange, disabled, value, activeColor} = props;
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 (disabled) color = 'color-gray-4';
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={classNames('dvrd-switch', value && 'active', disabled && 'disabled', className)}
47
- onClick={onToggle}>
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
- .track {
42
- .handle {
43
- cursor: default;
44
- }
45
- }
51
+ cursor: default;
46
52
  }
47
53
  }
@@ -158,7 +158,7 @@ export type OptionsMenuItem = {
158
158
  label: string;
159
159
  icon?: React.ReactNode;
160
160
  iconPlacement?: ElementPosition;
161
- onClick?: Function;
161
+ onClick?: MouseEventHandler;
162
162
  disabled?: boolean;
163
163
  };
164
164