@dvrd/dvr-controls 1.0.38 → 1.0.40

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
@@ -55,6 +55,7 @@ import DvrdSelectController from './src/js/select/dvrdSelectController';
55
55
  import DvrdSwitch from './src/js/switch/dvrdSwitch';
56
56
  import DvrdHeaderController from './src/js/header/v2/dvrdHeaderController';
57
57
  import FileUpload from './src/js/fileUpload/fileUpload';
58
+ import DvrdRadioController from './src/js/radio/dvrdRadioController';
58
59
 
59
60
  export {
60
61
  // Components
@@ -102,6 +103,7 @@ export {
102
103
  DvrdSwitch,
103
104
  DvrdHeaderController as DvrdHeader,
104
105
  FileUpload,
106
+ DvrdRadioController as DvrdRadio,
105
107
 
106
108
  // Interfaces / Enums
107
109
  DialogActionShape,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dvrd/dvr-controls",
3
- "version": "1.0.38",
3
+ "version": "1.0.40",
4
4
  "description": "Custom web controls",
5
5
  "main": "index.ts",
6
6
  "files": [
@@ -18,34 +18,34 @@
18
18
  "2": "ie >= 11"
19
19
  },
20
20
  "peerDependencies": {
21
- "react-router-dom": "6.8.1"
21
+ "react": "18.2.0",
22
+ "react-dom": "18.2.0"
22
23
  },
23
- "dependencies": {
24
- "@fortawesome/fontawesome-svg-core": "6.3.0",
25
- "@fortawesome/free-brands-svg-icons": "6.3.0",
26
- "@fortawesome/free-regular-svg-icons": "6.3.0",
27
- "@fortawesome/free-solid-svg-icons": "6.3.0",
28
- "@fortawesome/react-fontawesome": "0.2.0",
24
+ "devDependencies": {
29
25
  "@types/dompurify": "2.4.0",
30
26
  "@types/js-cookie": "3.0.3",
31
27
  "@types/lodash": "4.14.191",
32
28
  "@types/node": "18.14.0",
33
- "@types/react": "18.0.28",
29
+ "@types/react": "18.2.19",
34
30
  "@types/react-color": "3.0.6",
35
31
  "@types/react-dom": "18.0.11",
36
- "@types/react-router-dom": "5.3.3",
37
32
  "@types/uuid": "9.0.0",
33
+ "typescript": "4.9.5"
34
+ },
35
+ "dependencies": {
36
+ "@fortawesome/fontawesome-svg-core": "6.3.0",
37
+ "@fortawesome/free-brands-svg-icons": "6.3.0",
38
+ "@fortawesome/free-regular-svg-icons": "6.3.0",
39
+ "@fortawesome/free-solid-svg-icons": "6.3.0",
40
+ "@fortawesome/react-fontawesome": "0.2.0",
38
41
  "classnames": "2.3.2",
39
- "cross-env": "7.0.3",
40
42
  "dompurify": "3.0.0",
41
43
  "js-cookie": "3.0.1",
42
44
  "lodash": "4.17.21",
43
45
  "moment": "2.29.4",
44
- "react": "18.2.0",
45
46
  "react-color": "2.19.3",
46
- "react-dom": "18.2.0",
47
47
  "react-rnd": "10.4.1",
48
- "typescript": "4.9.5",
48
+ "react-router-dom": "6.15.0",
49
49
  "uuid": "9.0.0"
50
50
  }
51
51
  }
@@ -16,6 +16,7 @@ import {Button} from "../../../index";
16
16
 
17
17
  interface Props extends ColorPickerProps<any> {
18
18
  onSubmit: (color: Color) => void;
19
+ onSubmitColorResult?: (colorResult: ColorResult | null) => void;
19
20
  onPreChange?: (color: Color) => void;
20
21
  onClose: MouseEventHandler;
21
22
  pickerType: ColorPickerType;
@@ -27,6 +28,7 @@ interface Props extends ColorPickerProps<any> {
27
28
 
28
29
  interface State {
29
30
  color: Color;
31
+ colorResult: ColorResult | null;
30
32
  }
31
33
 
32
34
  export default class ColorPicker extends PureComponent<Props, State> {
@@ -39,14 +41,17 @@ export default class ColorPicker extends PureComponent<Props, State> {
39
41
 
40
42
  state: State = {
41
43
  color: this.props.color || '#000',
44
+ colorResult: null,
42
45
  };
43
46
 
44
47
  onSubmit = () => {
45
- const {onSubmit} = this.props, {color} = this.state;
48
+ const {onSubmit, onSubmitColorResult} = this.props, {color, colorResult} = this.state;
46
49
  onSubmit(color);
50
+ onSubmitColorResult?.(colorResult);
47
51
  };
48
52
 
49
53
  onChange = (color: ColorResult) => {
54
+ this.setState({colorResult: color});
50
55
  let newColor: Color;
51
56
  switch (this.props.resultType) {
52
57
  case ColorPickerResultType.HEX:
@@ -0,0 +1,72 @@
1
+ /*
2
+ * Copyright (c) Dave van Rijn Development 2023.
3
+ */
4
+ import './style/dvrdRadio.scss';
5
+
6
+ import classNames from 'classnames';
7
+ import React, {MouseEventHandler, useContext, useMemo} from 'react';
8
+ import {ControlContext} from "../util/controlContext";
9
+ import {editColor} from "../util/colorUtil";
10
+
11
+ interface Props {
12
+ onClick: MouseEventHandler;
13
+ onMouseEnter: MouseEventHandler;
14
+ onMouseLeave: MouseEventHandler;
15
+ checked: boolean;
16
+ hasHover: boolean;
17
+ id: string;
18
+ labelPosition: 'left' | 'right';
19
+ disabled?: boolean;
20
+ label?: string;
21
+ baseColor?: string;
22
+ title?: string;
23
+ className?: string;
24
+ }
25
+
26
+ export default function DvrdRadio(props: Props) {
27
+ const context = useContext(ControlContext);
28
+ const {
29
+ checked, label, labelPosition, hasHover, onClick, title, disabled, onMouseLeave, onMouseEnter, className, id
30
+ } = props;
31
+ const baseColor = useMemo(() => {
32
+ return props.baseColor ?? context.baseColor
33
+ }, [props.baseColor, context.baseColor]);
34
+
35
+ function getBulletContainerStyle() {
36
+ let borderColor: string = baseColor;
37
+ if (disabled) borderColor = 'color-gray-4';
38
+ else if (hasHover) borderColor = editColor(-.2, baseColor);
39
+ return {borderColor};
40
+ }
41
+
42
+ function getBulletStyle() {
43
+ let color: string = baseColor;
44
+ if (disabled) color = 'color-gray-4';
45
+ else if (hasHover) color = editColor(-.2, baseColor);
46
+ return {backgroundColor: color};
47
+ }
48
+
49
+ function renderLabel(position: 'left' | 'right') {
50
+ if (!label?.length || position !== labelPosition) return;
51
+ return <label className='dvrd-radio-button-label'>{label}</label>;
52
+ }
53
+
54
+ function renderBullet() {
55
+ return (
56
+ <div className='dvrd-radio-bullet-container' style={getBulletContainerStyle()}>
57
+ <div className='ripple' style={{backgroundColor: baseColor}}/>
58
+ <div className={classNames('dvrd-radio-bullet', checked && 'checked')} style={getBulletStyle()}/>
59
+ </div>
60
+ )
61
+ }
62
+
63
+ return (
64
+ <div
65
+ className={classNames('dvrd-radio-button', disabled && 'disbled', !!context.noAnimations && 'no-animations', className)}
66
+ onClick={onClick} id={id} onMouseEnter={onMouseEnter} onMouseLeave={onMouseLeave} title={title}>
67
+ {renderLabel('left')}
68
+ {renderBullet()}
69
+ {renderLabel('right')}
70
+ </div>
71
+ )
72
+ }
@@ -0,0 +1,79 @@
1
+ /*
2
+ * Copyright (c) Dave van Rijn Development 2023.
3
+ */
4
+
5
+ import React, {useCallback, useContext, useRef, useState} from 'react';
6
+ import {ChangeFunction} from "../util/interfaces";
7
+ import {generateComponentId} from "../util/componentUtil";
8
+ import {ControlContext} from "../util/controlContext";
9
+ import DvrdRadio from "./dvrdRadio";
10
+
11
+ interface Props {
12
+ onChange: ChangeFunction<string | number | bigint>;
13
+ value: string | number | bigint;
14
+ checked: boolean;
15
+ disabled?: boolean;
16
+ label?: string;
17
+ labelPosition?: 'left' | 'right';
18
+ baseColor?: string;
19
+ id?: string;
20
+ title?: string;
21
+ className?: string;
22
+ }
23
+
24
+ export default function DvrdRadioController(props: Props) {
25
+ const context = useContext(ControlContext);
26
+ const {disabled, onChange, value, checked, labelPosition, label, className, baseColor, title} = props;
27
+ const [hasHover, setHasHover] = useState(false);
28
+ const id = useRef(generateComponentId(props.id));
29
+
30
+ const getContainer = useCallback(() => {
31
+ return document.getElementById(id.current);
32
+ }, [id.current]);
33
+
34
+ const getRipple = useCallback(() => {
35
+ const container = getContainer();
36
+ if (container === null) return null;
37
+ return container.querySelector('div.ripple');
38
+ }, [id.current]);
39
+
40
+ function onClick() {
41
+ if (disabled) return;
42
+ onChange(value);
43
+ if (!context.noAnimations)
44
+ addRipple();
45
+ }
46
+
47
+ function onMouseEnter() {
48
+ if (!disabled)
49
+ setHasHover(true);
50
+ }
51
+
52
+ function onMouseLeave() {
53
+ setHasHover(false);
54
+ }
55
+
56
+ function addRipple() {
57
+ const container = getContainer();
58
+ const ripple = this.getRipple();
59
+ if (!container || !ripple) return;
60
+ if (container.classList.contains('rippling'))
61
+ container.classList.remove('rippling');
62
+ ripple.addEventListener('transitionend', removeRipple);
63
+ container.classList.add('rippling');
64
+ }
65
+
66
+ function removeRipple() {
67
+ const ripple = getRipple();
68
+ const container = getContainer();
69
+ if (!container || !ripple) return;
70
+ ripple.removeEventListener('transitionend', this.removeRipple);
71
+ container.classList.remove('rippling');
72
+ }
73
+
74
+ return (
75
+ <DvrdRadio onClick={onClick} onMouseEnter={onMouseEnter} onMouseLeave={onMouseLeave} checked={checked}
76
+ hasHover={hasHover} id={id.current} labelPosition={labelPosition ?? 'right'} label={label}
77
+ baseColor={baseColor} className={className} title={title} disabled={disabled}/>
78
+ );
79
+ }
@@ -0,0 +1,80 @@
1
+ /*!
2
+ * Copyright (c) Dave van Rijn Development 2023.
3
+ */
4
+
5
+ @import '../../../style/variables';
6
+
7
+ .dvrd-radio-button {
8
+ cursor: pointer;
9
+ display: flex;
10
+ column-gap: .5rem;
11
+ align-items: center;
12
+
13
+ .dvrd-radio-button-label {
14
+ font-size: .9rem;
15
+ color: $color-blue-text;
16
+ cursor: inherit;
17
+ user-select: none;
18
+ transition: color .2s ease;
19
+ }
20
+
21
+ .dvrd-radio-bullet-container {
22
+ @include backgroundShadow2;
23
+ width: 22px;
24
+ height: 22px;
25
+ position: relative;
26
+ border-radius: 50%;
27
+ border: 2px solid;
28
+ cursor: inherit;
29
+ background-color: white;
30
+ display: flex;
31
+ justify-content: center;
32
+ align-items: center;
33
+
34
+ .dvrd-radio-bullet {
35
+ width: 10px;
36
+ height: 10px;
37
+ border-radius: 50%;
38
+ visibility: hidden;
39
+ opacity: 0;
40
+ transition: visibility .2s ease-in-out, opacity .2s ease-in-out;
41
+
42
+ &.checked {
43
+ visibility: visible;
44
+ opacity: 1;
45
+ }
46
+ }
47
+
48
+ .ripple {
49
+ @include centerXY;
50
+ @include borderRadius(50%);
51
+ opacity: 1;
52
+ width: 8px;
53
+ height: 8px;
54
+ visibility: hidden;
55
+ pointer-events: none;
56
+ }
57
+ }
58
+
59
+ &.disabled {
60
+ cursor: default;
61
+ }
62
+
63
+ &.no-animations {
64
+ &, * {
65
+ transition: none !important;
66
+ }
67
+ }
68
+
69
+ &.rippling {
70
+ .dvrd-radio-bullet-container {
71
+ .ripple {
72
+ width: 56px;
73
+ height: 56px;
74
+ visibility: visible;
75
+ opacity: 0;
76
+ transition: opacity .5s ease-in-out, opacity .5s ease, width .5s ease-in-out, height .5s ease-in-out;
77
+ }
78
+ }
79
+ }
80
+ }
@@ -10,7 +10,7 @@ import classNames from 'classnames';
10
10
  import {AwesomeIcon, generateComponentId, isAbsoluteLink} from "../../../index";
11
11
  import {ControlContext} from "../util/controlContext";
12
12
  import {defer} from 'lodash';
13
- import { IconName } from '@fortawesome/fontawesome-svg-core';
13
+ import {IconName} from '@fortawesome/fontawesome-svg-core';
14
14
 
15
15
  interface Props {
16
16
  onClickItem: (item: SidebarItem) => MouseEventHandler;
@@ -87,7 +87,7 @@ export default function SidebarMenu(props: Props) {
87
87
  cls = classNames(className, mode === SideMenuMode.COMPACT ? 'side-bar-item' : 'side-bar-item-full',
88
88
  isChild && 'child', children !== undefined && 'with-children');
89
89
  return (
90
- <div key={id} className={cls} onClick={_onClickItem(item)}>
90
+ <div key={id} className={cls} onClick={_onClickItem(item)} id={id}>
91
91
  {renderIcon(isActive, isChild, label, icon)}
92
92
  {mode === SideMenuMode.COMPACT && <div className='active-indicator'/>}
93
93
  <span className={classNames('item-label', isActive && 'active')}>{label}</span>
@@ -8,9 +8,9 @@ import {defer} from 'lodash';
8
8
 
9
9
  // noinspection JSUnusedGlobalSymbols
10
10
  export interface ThemeContextShape {
11
- baseColor: string,
12
- contrastColor: string,
13
- onChange: Function,
11
+ baseColor: string;
12
+ contrastColor: string;
13
+ onChange: Function;
14
14
  }
15
15
 
16
16
  export interface ProviderProps {
@@ -23,6 +23,7 @@ export interface ThemeShape {
23
23
  controlVariant?: ControlVariant;
24
24
  borderColor?: string;
25
25
  onChange?: (theme?: ThemeShape) => void;
26
+ noAnimations?: boolean;
26
27
  }
27
28
 
28
29
  export const ControlContext: Context<ThemeShape> = React.createContext<ThemeShape>(
@@ -165,8 +165,25 @@ export type DefaultPDFElementParams<T extends PDFElementType, O extends IndexedO
165
165
  key: string;
166
166
  linkedID?: string;
167
167
  }>
168
- export type PDFImageParams = { img: File | string | null, persistent: PDFElementPersist; alignment?: ElementPosition; display?: PDFDisplay };
169
- export type PDFTextParams = { bold: boolean; underline: boolean; italic: boolean; fontSize: number; text: string; alignment?: ElementPosition; disabled?: boolean, font: PdfFont, color: string; persistent: PDFElementPersist; display?: PDFDisplay };
168
+ export type PDFImageParams = {
169
+ img: File | string | null,
170
+ persistent: PDFElementPersist;
171
+ alignment?: ElementPosition;
172
+ display?: PDFDisplay
173
+ };
174
+ export type PDFTextParams = {
175
+ bold: boolean;
176
+ underline: boolean;
177
+ italic: boolean;
178
+ fontSize: number;
179
+ text: string;
180
+ alignment?: ElementPosition;
181
+ disabled?: boolean,
182
+ font: PdfFont,
183
+ color: string;
184
+ persistent: PDFElementPersist;
185
+ display?: PDFDisplay
186
+ };
170
187
  export type PDFInvoiceTableParams = {
171
188
  fontSize: number;
172
189
  widths: number[];
@@ -177,7 +194,11 @@ export type PDFInvoiceTableParams = {
177
194
  persistent: PDFElementPersist;
178
195
  };
179
196
  export type PDFInvoiceWidths = { name: number; price: number; quantity: number; subtotal: number }
180
- export type PDFTextVariables = { company: IndexedObject<string>; client: IndexedObject<string>; invoice: IndexedObject<string>; }
197
+ export type PDFTextVariables = {
198
+ company: IndexedObject<string>;
199
+ client: IndexedObject<string>;
200
+ invoice: IndexedObject<string>;
201
+ }
181
202
  export type PDFSubmitHandler = (items: PDFElementParams<any, any>[], callback?: VoidFunction) => void;
182
203
  export type PDFElementDimensions = { left: number; top: number; width: number; height: number };
183
204
 
@@ -5,6 +5,15 @@
5
5
  import moment, {Moment} from "moment";
6
6
 
7
7
  export const MOMENT_FORMATS: string[] = [
8
+ 'MM/DD/YYYY HH:mm:ssZ',
9
+ 'MM-DD-YYYY HH:mm:ssZ',
10
+ 'DD/MM/YYYY HH:mm:ssZ',
11
+ 'DD-MM-YYYY HH:mm:ssZ',
12
+ 'YYYY-MM-DD HH:mm:ssZ',
13
+ 'YYYY/MM/DD HH:mm:ssZ',
14
+ 'DD/MM/YYYYTHH:mm:ssZ',
15
+ 'DD-MM-YYYYTHH:mm:ssZ',
16
+ 'YYYY-MM-DDTHH:mm:ssZ',
8
17
  'MM/DD/YYYY HH:mm:ss',
9
18
  'MM-DD-YYYY HH:mm:ss',
10
19
  'DD/MM/YYYY HH:mm:ss',
@@ -61,6 +61,12 @@ export const cancelAllFetch = () => {
61
61
  }
62
62
  };
63
63
 
64
+ function bigIntParser(_: string, value: any) {
65
+ if (typeof value === 'bigint')
66
+ return value.toString();
67
+ return value;
68
+ }
69
+
64
70
  export function sendFetch(config: FetchOptions, legacySupport: boolean = false): AbortController | null {
65
71
  const baseUrl = config.baseUrl || window.settings.platformUrl;
66
72
  if (!baseUrl) throw new Error('Base url is not set!');
@@ -70,7 +76,7 @@ export function sendFetch(config: FetchOptions, legacySupport: boolean = false):
70
76
  const options: { [index: string]: any } = {
71
77
  headers,
72
78
  method,
73
- body: config.stringifyData === false ? data : JSON.stringify(data),
79
+ body: config.stringifyData === false ? data : JSON.stringify(data, bigIntParser),
74
80
  cache: 'no-store',
75
81
  };
76
82
  const abortController = getAbortController();