@dvrd/dvr-controls 1.0.15 → 1.0.17

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.
Files changed (179) hide show
  1. package/package.json +2 -1
  2. package/src/js/button/button.tsx +102 -0
  3. package/src/js/button/buttonController.tsx +179 -0
  4. package/src/js/button/closeButton.tsx +29 -0
  5. package/src/js/button/dvrdButton.tsx +128 -0
  6. package/src/js/button/outlinedButton.tsx +105 -0
  7. package/src/js/button/simpleButton.tsx +163 -0
  8. package/src/js/button/style/button.scss +95 -0
  9. package/src/js/button/style/closeButton.scss +15 -0
  10. package/src/js/button/style/dvrdButton.scss +30 -0
  11. package/src/js/button/style/outlinedButton.scss +84 -0
  12. package/src/js/button/style/simpleButton.scss +80 -0
  13. package/src/js/carousel/DVRCarousel.tsx +163 -0
  14. package/src/js/carousel/DVRCarouselController.tsx +95 -0
  15. package/src/js/carousel/style/DVRCarousel.scss +38 -0
  16. package/src/js/checkbox/checkbox.tsx +148 -0
  17. package/src/js/checkbox/checkboxController.tsx +131 -0
  18. package/src/js/checkbox/style/checkbox.scss +109 -0
  19. package/src/js/colorPicker/colorPicker.tsx +118 -0
  20. package/src/js/colorPicker/style/colorPicker.scss +20 -0
  21. package/src/js/date/dvrdDatePicker.tsx +357 -0
  22. package/src/js/date/style/dvrdDatePicker.scss +318 -0
  23. package/src/js/dialog/dialog.tsx +207 -0
  24. package/src/js/dialog/dialogController.tsx +70 -0
  25. package/src/js/dialog/inlineDialog.tsx +127 -0
  26. package/src/js/dialog/style/dialog.scss +61 -0
  27. package/src/js/events/withEvents.tsx +40 -0
  28. package/src/js/head/DVRHead.tsx +49 -0
  29. package/src/js/header/DVRHeader.tsx +417 -0
  30. package/src/js/header/style/header.scss +206 -0
  31. package/src/js/icon/awesomeIcon.tsx +20 -0
  32. package/src/js/image/imageUpload.tsx +69 -0
  33. package/src/js/image/style/imageUpload.scss +11 -0
  34. package/src/js/info/info.tsx +136 -0
  35. package/src/js/info/style/info.scss +39 -0
  36. package/src/js/input/animated/animatedTextField.tsx +159 -0
  37. package/src/js/input/date/dateField.tsx +360 -0
  38. package/src/js/input/date/dateFieldController.tsx +245 -0
  39. package/src/js/input/date/datePicker/datePicker.tsx +186 -0
  40. package/src/js/input/date/datePicker/style/datePicker.scss +102 -0
  41. package/src/js/input/date/input/dateInput.tsx +214 -0
  42. package/src/js/input/date/style/dateField.scss +40 -0
  43. package/src/js/input/date/timePicker/style/timePicker.scss +95 -0
  44. package/src/js/input/date/timePicker/timePicker.tsx +143 -0
  45. package/src/js/input/editor/DVREditor.tsx +21 -0
  46. package/src/js/input/number/numberInput.tsx +157 -0
  47. package/src/js/input/password/passwordInput.tsx +140 -0
  48. package/src/js/input/password/passwordRules.tsx +48 -0
  49. package/src/js/input/password/style/passwordInput.scss +39 -0
  50. package/src/js/input/password/style/passwordRules.scss +41 -0
  51. package/src/js/input/simple/style/simpleInput.scss +98 -0
  52. package/src/js/input/simple/v2/simpleInputV2.tsx +178 -0
  53. package/src/js/input/style/input.scss +138 -0
  54. package/src/js/input/v2/inputController_v2.tsx +250 -0
  55. package/src/js/input/v2/input_v2.tsx +7 -0
  56. package/src/js/label/label.tsx +196 -0
  57. package/src/js/label/style/label.scss +4 -0
  58. package/src/js/link/link.tsx +38 -0
  59. package/src/js/link/style/link.scss +30 -0
  60. package/src/js/loader/loader.tsx +79 -0
  61. package/src/js/loader/loaderController.tsx +61 -0
  62. package/src/js/loader/style/loader.scss +53 -0
  63. package/src/js/media/media.tsx +72 -0
  64. package/src/js/navigator/navigator.tsx +51 -0
  65. package/src/js/optionsList/dvrdOptionsList.tsx +112 -0
  66. package/src/js/optionsList/style/dvrdOptionsList.scss +84 -0
  67. package/src/js/optionsMenu/optionsMenu.tsx +187 -0
  68. package/src/js/optionsMenu/style/optionsMenu.scss +70 -0
  69. package/src/js/pdf/element/pdfElement.tsx +315 -0
  70. package/src/js/pdf/element/style/pdfElement.scss +111 -0
  71. package/src/js/pdf/history/pdfHistory.ts +57 -0
  72. package/src/js/pdf/image/pdfImage.tsx +175 -0
  73. package/src/js/pdf/image/style/pdfImage.scss +34 -0
  74. package/src/js/pdf/invoiceTable/pdfInvoiceTable.tsx +176 -0
  75. package/src/js/pdf/invoiceTable/style/pdfInvoiceTable.scss +32 -0
  76. package/src/js/pdf/pdfTemplateCreator.tsx +279 -0
  77. package/src/js/pdf/settings/buttons/iconButton.tsx +49 -0
  78. package/src/js/pdf/settings/buttons/style/iconButton.scss +50 -0
  79. package/src/js/pdf/settings/image/pdfImageSettings.tsx +82 -0
  80. package/src/js/pdf/settings/image/style/pdfImageSettings.scss +9 -0
  81. package/src/js/pdf/settings/invoiceTable/pdfInvoiceTableSettings.tsx +141 -0
  82. package/src/js/pdf/settings/invoiceTable/style/pdfInvoiceTableSettings.scss +38 -0
  83. package/src/js/pdf/settings/pdfElementSettings.tsx +86 -0
  84. package/src/js/pdf/settings/style/pdfElementSettings.scss +56 -0
  85. package/src/js/pdf/settings/text/pdfTextSettings.tsx +202 -0
  86. package/src/js/pdf/settings/text/style/pdfTextSettings.scss +94 -0
  87. package/src/js/pdf/style/pdfTemplateCreator.scss +118 -0
  88. package/src/js/pdf/text/pdfText.tsx +267 -0
  89. package/src/js/pdf/text/style/pdfText.scss +22 -0
  90. package/src/js/pdf/v2/pdfElement/pdfDraggableElement.tsx +193 -0
  91. package/src/js/pdf/v2/types/pdfTemplateTypes.ts +27 -0
  92. package/src/js/popup/style/withBackground.scss +29 -0
  93. package/src/js/popup/withBackground.tsx +92 -0
  94. package/src/js/select/async/asyncSelect.tsx +46 -0
  95. package/src/js/select/async/style/asyncSelect.scss +23 -0
  96. package/src/js/select/dvrdSelect.tsx +214 -0
  97. package/src/js/select/dvrdSelectController.tsx +81 -0
  98. package/src/js/select/select.tsx +310 -0
  99. package/src/js/select/selectController.tsx +341 -0
  100. package/src/js/select/style/dvrdSelect.scss +140 -0
  101. package/src/js/select/style/select.scss +199 -0
  102. package/src/js/sidebarMenu/sidebarMenu.tsx +167 -0
  103. package/src/js/sidebarMenu/style/sidebarMenu.scss +167 -0
  104. package/src/js/slider/DVRSlider.tsx +107 -0
  105. package/src/js/slider/style/DVRSlider.scss +88 -0
  106. package/src/js/snackbar/snackbar.tsx +72 -0
  107. package/src/js/snackbar/snackbarController.tsx +104 -0
  108. package/src/js/snackbar/style/snackbar.scss +46 -0
  109. package/src/js/switch/dvrdSwitch.tsx +53 -0
  110. package/src/js/switch/style/dvrdSwitch.scss +47 -0
  111. package/src/js/switch/style/switch.scss +84 -0
  112. package/src/js/switch/switch.tsx +115 -0
  113. package/src/js/switch/switchController.tsx +97 -0
  114. package/src/js/textField/dvrdInput.tsx +219 -0
  115. package/src/js/textField/dvrdInputController.tsx +97 -0
  116. package/src/js/textField/dvrdNumberInput.tsx +141 -0
  117. package/src/js/textField/dvrdPasswordInput.tsx +40 -0
  118. package/src/js/textField/style/dvrdInput.scss +115 -0
  119. package/src/js/textField/style/dvrdPassword.scss +15 -0
  120. package/src/js/topButton/style/topButton.scss +54 -0
  121. package/src/js/topButton/topButton.tsx +136 -0
  122. package/src/js/util/analyticsUtil.ts +41 -0
  123. package/src/js/util/colorUtil.ts +230 -0
  124. package/src/js/util/componentUtil.tsx +59 -0
  125. package/src/js/util/constants.ts +12 -0
  126. package/src/js/util/controlContext.tsx +46 -0
  127. package/src/js/util/controlUtil.ts +107 -0
  128. package/src/js/util/cookieUtil.ts +17 -0
  129. package/src/js/util/eventUtil.ts +65 -0
  130. package/src/js/util/googleUtil.ts +88 -0
  131. package/src/js/util/interfaces.ts +180 -0
  132. package/src/js/util/jwtUtil.ts +72 -0
  133. package/src/js/util/miscUtil.ts +170 -0
  134. package/src/js/util/momentUtil.ts +45 -0
  135. package/src/js/util/pdfUtil.ts +124 -0
  136. package/src/js/util/requestUtil.ts +146 -0
  137. package/src/js/util/responsiveUtil.ts +37 -0
  138. package/src/js/util/validationUtil.ts +13 -0
  139. package/src/res/img/lock-handle.png +0 -0
  140. package/src/res/img/lock-handle.webp +0 -0
  141. package/src/res/img/lock.png +0 -0
  142. package/src/res/img/lock.webp +0 -0
  143. package/src/style/common-icons-variables.scss +140 -0
  144. package/src/style/common-icons.scss +714 -0
  145. package/src/style/common-variables.scss +243 -0
  146. package/src/style/display-breakpoints.scss +141 -0
  147. package/src/style/fonts/common-icons.eot +0 -0
  148. package/src/style/fonts/common-icons.svg +150 -0
  149. package/src/style/fonts/common-icons.ttf +0 -0
  150. package/src/style/fonts/common-icons.woff +0 -0
  151. package/src/style/fonts/common-icons.woff2 +0 -0
  152. package/src/style/fonts/fontAwesome/css/all.css +7003 -0
  153. package/src/style/fonts/fontAwesome/css/all.min.css +6 -0
  154. package/src/style/fonts/fontAwesome/css/brands.css +1423 -0
  155. package/src/style/fonts/fontAwesome/css/brands.min.css +6 -0
  156. package/src/style/fonts/fontAwesome/css/fontawesome.css +5519 -0
  157. package/src/style/fonts/fontAwesome/css/fontawesome.min.css +6 -0
  158. package/src/style/fonts/fontAwesome/css/regular.css +19 -0
  159. package/src/style/fonts/fontAwesome/css/regular.min.css +6 -0
  160. package/src/style/fonts/fontAwesome/css/solid.css +19 -0
  161. package/src/style/fonts/fontAwesome/css/solid.min.css +6 -0
  162. package/src/style/fonts/fontAwesome/css/svg-with-js.css +634 -0
  163. package/src/style/fonts/fontAwesome/css/svg-with-js.min.css +6 -0
  164. package/src/style/fonts/fontAwesome/css/v4-font-face.css +26 -0
  165. package/src/style/fonts/fontAwesome/css/v4-font-face.min.css +6 -0
  166. package/src/style/fonts/fontAwesome/css/v4-shims.css +2146 -0
  167. package/src/style/fonts/fontAwesome/css/v4-shims.min.css +6 -0
  168. package/src/style/fonts/fontAwesome/css/v5-font-face.css +22 -0
  169. package/src/style/fonts/fontAwesome/css/v5-font-face.min.css +6 -0
  170. package/src/style/fonts/fontAwesome/webfonts/fa-brands-400.ttf +0 -0
  171. package/src/style/fonts/fontAwesome/webfonts/fa-brands-400.woff2 +0 -0
  172. package/src/style/fonts/fontAwesome/webfonts/fa-regular-400.ttf +0 -0
  173. package/src/style/fonts/fontAwesome/webfonts/fa-regular-400.woff2 +0 -0
  174. package/src/style/fonts/fontAwesome/webfonts/fa-solid-900.ttf +0 -0
  175. package/src/style/fonts/fontAwesome/webfonts/fa-solid-900.woff2 +0 -0
  176. package/src/style/fonts/fontAwesome/webfonts/fa-v4compatibility.ttf +0 -0
  177. package/src/style/fonts/fontAwesome/webfonts/fa-v4compatibility.woff2 +0 -0
  178. package/src/style/variables.scss +11 -0
  179. package/.gitignore +0 -31
package/package.json CHANGED
@@ -1,8 +1,9 @@
1
1
  {
2
2
  "name": "@dvrd/dvr-controls",
3
- "version": "1.0.15",
3
+ "version": "1.0.17",
4
4
  "description": "Custom web controls",
5
5
  "main": "index.ts",
6
+ "files": ["src/**/*"],
6
7
  "scripts": {},
7
8
  "repository": {
8
9
  "type": "git",
@@ -0,0 +1,102 @@
1
+ /*
2
+ * Copyright (c) 2021. Dave van Rijn Development
3
+ */
4
+
5
+ import './style/button.scss';
6
+
7
+ import React, { PropsWithChildren } from 'react';
8
+ import classNames from 'classnames';
9
+ import {convertColor, editColor, ThemeShape} from "../../..";
10
+ import {isNotNull, isNull} from "../util/controlUtil";
11
+
12
+ interface Props {
13
+ onClick: any;
14
+ onMouseEnter: any;
15
+ onMouseLeave: any;
16
+ onMouseDown: any;
17
+ label: string;
18
+ containerClass: string;
19
+ labelClass: string;
20
+ id: string;
21
+ padding: 'small' | 'normal' | 'large';
22
+ disabled: boolean;
23
+ withRipple: boolean;
24
+ isHovered: boolean;
25
+ baseColor: string;
26
+ textColor: string;
27
+ contextStyle: ThemeShape;
28
+ title?: string;
29
+ tabIndex?: number;
30
+ }
31
+
32
+ export class Button extends React.Component<PropsWithChildren<Props>> {
33
+ getContainerClass = (): string => {
34
+ const {disabled, withRipple, padding, containerClass} = this.props,
35
+ classes = ['buttonController'];
36
+ if (disabled) classes.push('disabled');
37
+ else if (withRipple) classes.push('ripple');
38
+
39
+ if (padding === 'small') classes.push('sp');
40
+ else if (padding === 'large') classes.push('lp');
41
+
42
+ classes.push(containerClass);
43
+ return classNames(classes);
44
+ };
45
+
46
+ getContainerStyle = (): object => {
47
+ const {isHovered, baseColor} = this.props;
48
+ let hexColor = convertColor(baseColor);
49
+ if (isHovered) hexColor = editColor(-.2, hexColor);
50
+ return {backgroundColor: hexColor};
51
+ };
52
+
53
+ getLabelStyle = (): object => {
54
+ const {textColor} = this.props;
55
+ return {color: convertColor(textColor)};
56
+ };
57
+
58
+ getRippleColor = (): string => {
59
+ const {contextStyle, textColor} = this.props;
60
+ if(textColor) return convertColor(textColor);
61
+ return convertColor(contextStyle.contrastColor);
62
+ };
63
+
64
+ renderLabel = (): React.ReactNode => {
65
+ const {children, labelClass, label} = this.props, leftElements = [], rightElements = [];
66
+ if (Array.isArray(children)) {
67
+ for (let child of children) {
68
+ if (child !== undefined && child !== null) {
69
+ //@ts-ignore
70
+ const {placement, element} = child;
71
+ if (placement === 'left') leftElements.push(element);
72
+ else rightElements.push(element);
73
+ }
74
+ }
75
+ } else if (isNotNull(children)) {
76
+ //@ts-ignore
77
+ const {placement, element} = children;
78
+ if (placement === 'left') leftElements.push(element);
79
+ else rightElements.push(element);
80
+ }
81
+ return (
82
+ <span className={classNames('buttonLabel', isNull(children) && 'singleChild', labelClass)}
83
+ style={this.getLabelStyle()}>
84
+ {leftElements.map((element, key) => ({...element, key}))}
85
+ {isNotNull(label) && <span className='buttonLabel'>{label}</span>}
86
+ {rightElements.map((element, key) => ({...element, key}))}
87
+ </span>)
88
+ };
89
+
90
+ render = () => {
91
+ const {onClick, onMouseEnter, onMouseLeave, id, onMouseDown, withRipple, title, tabIndex} = this.props,
92
+ titleProps = isNotNull(title) ? {title} : {};
93
+ return (
94
+ <div className={this.getContainerClass()} style={this.getContainerStyle()} onClick={onClick}
95
+ onMouseEnter={onMouseEnter} onMouseLeave={onMouseLeave} onMouseDown={onMouseDown}
96
+ id={id} tabIndex={tabIndex} {...titleProps}>
97
+ {this.renderLabel()}
98
+ {withRipple && <div className='ripple' style={{backgroundColor: this.getRippleColor()}}/>}
99
+ </div>
100
+ )
101
+ };
102
+ }
@@ -0,0 +1,179 @@
1
+ /*
2
+ * Copyright (c) 2021. Dave van Rijn Development
3
+ */
4
+
5
+ import React, {MouseEventHandler, ReactNode} from 'react';
6
+ import {Button} from "./button";
7
+ import {OutlinedButton} from "./outlinedButton";
8
+ import {ControlContext, ThemeShape} from "../util/controlContext";
9
+ import {ControlPadding, ControlVariant} from "../util/interfaces";
10
+ import SimpleButton from "./simpleButton";
11
+ import {generateComponentId} from '../util/componentUtil';
12
+
13
+ interface Props extends Readonly<{ children?: ReactNode }> {
14
+ onClick: MouseEventHandler;
15
+ label: string;
16
+ containerClass: string;
17
+ className: string;
18
+ labelClass: string;
19
+ id?: string;
20
+ padding: 'small' | 'normal' | 'large';
21
+ type: ControlVariant | string;
22
+ disabled: boolean;
23
+ withRipple: boolean;
24
+ baseColor?: string;
25
+ textColor?: string;
26
+ contextStyle?: ThemeShape;
27
+ title?: string;
28
+ primary: boolean;
29
+ tabIndex?: number;
30
+ }
31
+
32
+ interface State {
33
+ isHovered: boolean;
34
+ }
35
+
36
+ export default class ButtonController extends React.Component<Props, State> {
37
+ declare context: React.ContextType<typeof ControlContext>;
38
+ static contextType = ControlContext;
39
+
40
+ static defaultProps = {
41
+ containerClass: '',
42
+ className: '',
43
+ labelClass: '',
44
+ padding: 'normal',
45
+ disabled: false,
46
+ withRipple: true,
47
+ type: ControlVariant.STANDARD,
48
+ primary: true,
49
+ };
50
+
51
+ state = {
52
+ isHovered: false,
53
+ };
54
+
55
+ private getProps = (): Props => {
56
+ const origProps = this.props;
57
+ return {
58
+ ...origProps,
59
+ type: this.context.controlVariant || this.props.type,
60
+ };
61
+ };
62
+
63
+ private id: string = generateComponentId(this.props.id);
64
+
65
+ private getContainer = (): HTMLElement | null => {
66
+ return document.getElementById(this.id);
67
+ };
68
+
69
+ private getRipple = (): HTMLElement | null => {
70
+ const container = this.getContainer();
71
+ if (container === null) return null;
72
+ return container.querySelector('div.ripple');
73
+ };
74
+
75
+ onClick = (evt: any) => {
76
+ if (!this.props.disabled)
77
+ this.props.onClick(evt);
78
+ };
79
+
80
+ onMouseEnter = () => {
81
+ this.setState({isHovered: true});
82
+ };
83
+
84
+ onMouseLeave = () => {
85
+ this.setState({isHovered: false});
86
+ };
87
+
88
+ onMouseDown = (evt: any) => {
89
+ if (this.props.withRipple && !this.props.disabled)
90
+ this.addRipple(evt);
91
+ };
92
+
93
+ addRipple = (evt: any) => {
94
+ const container = this.getContainer();
95
+ if (container !== null) {
96
+ const ripple = this.getRipple();
97
+ if (ripple !== null) {
98
+ if (container.classList.contains('rippling'))
99
+ container.classList.remove('rippling');
100
+ const rect = evt.target.getBoundingClientRect();
101
+ ripple.style.setProperty('left', evt.clientX - rect.left + 'px');
102
+ ripple.style.setProperty('top', evt.clientY - rect.top + 'px');
103
+ ripple.addEventListener('transitionend', this.removeRipple);
104
+ container.classList.add('rippling');
105
+ }
106
+ }
107
+ };
108
+
109
+ removeRipple = () => {
110
+ const ripple = this.getRipple();
111
+ const container = this.getContainer();
112
+ if (ripple !== null && container !== null) {
113
+ ripple.removeEventListener('transitionend', this.removeRipple);
114
+ container.classList.remove('rippling');
115
+ }
116
+ };
117
+
118
+ getBaseColor = (): string => {
119
+ const {baseColor} = this.props;
120
+ if (baseColor !== undefined && baseColor !== null) return baseColor;
121
+ return this.getContextStyle().baseColor;
122
+ };
123
+
124
+ getTextColor = (): string => {
125
+ const {textColor} = this.props;
126
+ if (textColor !== null && textColor !== undefined) return textColor;
127
+ return this.getContextStyle().contrastColor;
128
+ };
129
+
130
+ getContextStyle = (): ThemeShape => {
131
+ const {contextStyle} = this.props;
132
+ if (contextStyle !== null && contextStyle !== undefined) return contextStyle;
133
+ // noinspection JSDeprecatedSymbols
134
+ return this.context;
135
+ };
136
+
137
+ componentWillUnmount = () => {
138
+ this.removeRipple();
139
+ };
140
+
141
+ render = () => {
142
+ const {
143
+ labelClass, containerClass, disabled, padding, withRipple, label, type, title, baseColor, textColor,
144
+ primary, children, tabIndex, className
145
+ } = this.getProps(),
146
+ {isHovered} = this.state, controlType = type === 'standard' ? ControlVariant.STANDARD :
147
+ type === 'outlined' ? ControlVariant.OUTLINED : ControlVariant.SIMPLE;
148
+ const controlPadding = padding === 'small' ? ControlPadding.SMALL :
149
+ padding === 'normal' ? ControlPadding.NORMAL : ControlPadding.LARGE;
150
+ if (controlType === ControlVariant.STANDARD)
151
+ return (
152
+ <Button labelClass={labelClass} containerClass={containerClass + className} disabled={disabled}
153
+ id={this.id} onClick={this.onClick} padding={padding} withRipple={withRipple}
154
+ baseColor={this.getBaseColor()} textColor={this.getTextColor()} label={label}
155
+ onMouseEnter={this.onMouseEnter} contextStyle={this.getContextStyle()} title={title}
156
+ isHovered={isHovered} onMouseLeave={this.onMouseLeave} onMouseDown={this.onMouseDown}
157
+ tabIndex={tabIndex}>
158
+ {children}
159
+ </Button>
160
+ );
161
+ else if (controlType === ControlVariant.OUTLINED) return (
162
+ <OutlinedButton onClick={this.onClick} onMouseEnter={this.onMouseEnter}
163
+ onMouseLeave={this.onMouseLeave} onMouseDown={this.onMouseDown} label={label}
164
+ containerClass={containerClass + className} labelClass={labelClass} id={this.id}
165
+ title={title} padding={padding} disabled={disabled} withRipple={withRipple}
166
+ isHovered={isHovered} baseColor={this.getBaseColor()} contextStyle={this.getContextStyle()}
167
+ tabIndex={tabIndex}>
168
+ {children}
169
+ </OutlinedButton>
170
+ );
171
+ else return (
172
+ <SimpleButton onClick={this.onClick} onMouseEnter={this.onMouseEnter} onMouseLeave={this.onMouseLeave}
173
+ onMouseDown={this.onMouseDown} label={label} containerClass={containerClass + className}
174
+ labelClass={labelClass} id={this.id} padding={controlPadding} disabled={disabled}
175
+ isHovered={isHovered} baseColor={baseColor} textColor={textColor} withRipple={withRipple}
176
+ primary={primary} title={title} tabIndex={tabIndex}>{children}</SimpleButton>
177
+ );
178
+ };
179
+ }
@@ -0,0 +1,29 @@
1
+ /*
2
+ * Copyright (c) 2021. Dave van Rijn Development
3
+ */
4
+
5
+ import './style/closeButton.scss';
6
+
7
+ import React, {CSSProperties, PureComponent} from 'react';
8
+ import {MouseEventHandler} from "react";
9
+ import classNames from "classnames";
10
+ import {voidFunction} from "../util/controlUtil";
11
+ import AwesomeIcon from "../icon/awesomeIcon";
12
+
13
+ interface Props {
14
+ onClick: MouseEventHandler;
15
+ className?: string;
16
+ disabled?: boolean;
17
+ style?: CSSProperties;
18
+ title?: string;
19
+ }
20
+
21
+ export default class CloseButton extends PureComponent<Props> {
22
+ render = () => {
23
+ const {className, title, disabled, onClick, style} = this.props;
24
+ return (
25
+ <AwesomeIcon name='times' className={classNames('close-button', className)} title={title} style={style}
26
+ onClick={disabled ? voidFunction : onClick}/>
27
+ )
28
+ }
29
+ }
@@ -0,0 +1,128 @@
1
+ /*
2
+ * Copyright (c) 2021. Dave van Rijn Development
3
+ */
4
+ import './style/dvrdButton.scss';
5
+
6
+ import React, {CSSProperties, MouseEventHandler, useContext, useState} from "react";
7
+ import classNames from "classnames";
8
+ import {ElementPosition, OrnamentShape} from "../util/interfaces";
9
+ import {ControlContext} from "../util/controlContext";
10
+ import {convertColor, editColor} from "../util/colorUtil";
11
+
12
+ export interface DvrdButtonProps {
13
+ onClick: MouseEventHandler;
14
+ label: string;
15
+ ornaments?: OrnamentShape | OrnamentShape[];
16
+ disabled?: boolean;
17
+ className?: string;
18
+ labelClassName?: string;
19
+ ornamentClassName?: string;
20
+ secondary?: boolean;
21
+ red?: boolean;
22
+ customBaseColor?: string;
23
+ customContrastColor?: string;
24
+ }
25
+
26
+ export default function DvrdButton(props: DvrdButtonProps) {
27
+ const context = useContext(ControlContext),
28
+ {
29
+ className, disabled, label, labelClassName, onClick, ornamentClassName, ornaments, red, secondary,
30
+ customBaseColor, customContrastColor
31
+ } = props,
32
+ [hover, setHover] = useState(false);
33
+
34
+ function onMouseEnter() {
35
+ setHover(true);
36
+ }
37
+
38
+ function onMouseLeave() {
39
+ setHover(false);
40
+ }
41
+
42
+ function getContainerStyle(): CSSProperties {
43
+ const style: CSSProperties = {
44
+ gridTemplateColumns: '1fr', backgroundColor: getBackgroundColor(), color: getColor()
45
+ };
46
+ let hasLeft: boolean = false, hasRight: boolean = false;
47
+ if (Array.isArray(ornaments))
48
+ for (const ornament of ornaments) {
49
+ if (!ornament.placement || ornament.placement === ElementPosition.LEFT) hasLeft = true;
50
+ else if (ornament.placement === ElementPosition.RIGHT) hasRight = true;
51
+ if (hasLeft && hasRight) break;
52
+ }
53
+ else if (ornaments) {
54
+ hasLeft = !ornaments.placement || ornaments.placement === ElementPosition.LEFT;
55
+ hasRight = ornaments.placement === ElementPosition.RIGHT;
56
+ }
57
+ let columns: string = '1fr';
58
+ if (hasRight) columns = `${columns} fit-content(100%)`
59
+ if (hasLeft) columns = `fit-content(100%) ${columns}`;
60
+ style.gridTemplateColumns = columns;
61
+ return style;
62
+ }
63
+
64
+ function getBackgroundColor(): string {
65
+ let color: string;
66
+ if (disabled) color = 'color-gray-4';
67
+ else if (customBaseColor) color = customBaseColor;
68
+ else if (red) {
69
+ if (secondary) color = 'color-red-secondary';
70
+ else color = 'rgb(255,0,0)';
71
+ } else if (secondary) color = context.contrastColor;
72
+ else color = context.baseColor;
73
+ color = convertColor(color);
74
+ if (hover) color = editColor(-.2, color);
75
+ return color;
76
+ }
77
+
78
+ function getColor(): string {
79
+ let color: string;
80
+ if (disabled) color = 'color-gray-3';
81
+ else if (customContrastColor) color = customContrastColor;
82
+ else if (red) {
83
+ if (secondary) color = 'red';
84
+ else color = 'white';
85
+ } else if (secondary) color = context.baseColor;
86
+ else color = context.contrastColor;
87
+ return convertColor(color);
88
+ }
89
+
90
+ return (
91
+ <div
92
+ className={classNames('dvrd-button', disabled && 'disabled', secondary && 'secondary', red && 'red', className)}
93
+ style={getContainerStyle()} onClick={disabled ? undefined : onClick} onMouseEnter={onMouseEnter}
94
+ onMouseLeave={onMouseLeave}>
95
+ <Ornament position={ElementPosition.LEFT} ornamentClassName={ornamentClassName} ornaments={ornaments}/>
96
+ <label className={classNames('dvrd-button-label', labelClassName)}>{label}</label>
97
+ <Ornament position={ElementPosition.RIGHT} ornamentClassName={ornamentClassName} ornaments={ornaments}/>
98
+ </div>
99
+ )
100
+ }
101
+
102
+ interface OrnamentProps {
103
+ position: ElementPosition;
104
+ ornaments?: OrnamentShape | OrnamentShape[];
105
+ ornamentClassName?: string;
106
+ }
107
+
108
+ function Ornament(props: OrnamentProps) {
109
+ const {ornaments, position, ornamentClassName} = props;
110
+ if (!ornaments || (Array.isArray(ornaments) && !ornaments.length)) return null;
111
+ let ornament: OrnamentShape | null = null;
112
+ if (Array.isArray(ornaments)) {
113
+ for (const orn of ornaments) {
114
+ if (!orn.placement || orn.placement === position) {
115
+ ornament = orn;
116
+ break;
117
+ }
118
+ }
119
+ } else if ((!ornaments.placement && position === ElementPosition.LEFT) || ornaments.placement === position)
120
+ ornament = ornaments;
121
+ if (!ornament) return null;
122
+
123
+ if (typeof ornament.element === 'string')
124
+ return <span className={classNames('dvrd-button-ornament', ornamentClassName)}>{ornament.element}</span>;
125
+ else return React.cloneElement(ornament.element, {
126
+ className: classNames('dvrd-button-ornament', ornament.element.props.className, ornamentClassName)
127
+ });
128
+ }
@@ -0,0 +1,105 @@
1
+ /*
2
+ * Copyright (c) 2021. Dave van Rijn Development
3
+ */
4
+
5
+ import './style/outlinedButton.scss';
6
+
7
+ import React, { PropsWithChildren } from 'react';
8
+ import classNames from 'classnames';
9
+ import {colorIsWhite, convertColor, editColor} from "../util/colorUtil";
10
+ import {isNotNull, isNull} from "../util/controlUtil";
11
+ import {ThemeShape} from "../util/controlContext";
12
+
13
+ interface ButtonProps {
14
+ onClick: any,
15
+ onMouseEnter: any,
16
+ onMouseLeave: any,
17
+ onMouseDown: any,
18
+ label: string,
19
+ containerClass: string,
20
+ labelClass: string,
21
+ id: string,
22
+ padding: 'small' | 'normal' | 'large',
23
+ disabled: boolean,
24
+ withRipple: boolean,
25
+ isHovered: boolean,
26
+ baseColor: string,
27
+ contextStyle: ThemeShape,
28
+ title?: string,
29
+ tabIndex?: number;
30
+ }
31
+
32
+ export class OutlinedButton extends React.Component<PropsWithChildren<ButtonProps>> {
33
+ getContainerClass = (): string => {
34
+ const {containerClass, disabled, padding} = this.props, classes: string[] = ['outlinedButtonContainer'];
35
+ if (disabled) classes.push('disabled');
36
+
37
+ if (padding === 'small') classes.push('sp');
38
+ else if (padding === 'large') classes.push('lp');
39
+
40
+ classes.push(containerClass);
41
+ return classNames(classes);
42
+ };
43
+
44
+ getContainerStyle = (): object => {
45
+ const {baseColor, isHovered, contextStyle} = this.props;
46
+ let color = convertColor(baseColor);
47
+ if (colorIsWhite(color)) color = convertColor(contextStyle.contrastColor);
48
+ if (isHovered) color = editColor(-.2, color);
49
+ return {borderColor: color};
50
+ };
51
+
52
+ getLabelStyle = () => {
53
+ const {baseColor, isHovered, contextStyle} = this.props;
54
+ let color = convertColor(baseColor);
55
+ if (colorIsWhite(color)) color = convertColor(contextStyle.contrastColor);
56
+ if (isHovered) color = editColor(-.2, color);
57
+ return {color};
58
+ };
59
+
60
+ getRippleColor = (): string => {
61
+ const {baseColor, contextStyle} = this.props;
62
+ let color = baseColor;
63
+ if (colorIsWhite(baseColor)) color = contextStyle.contrastColor;
64
+ return convertColor(color);
65
+ };
66
+
67
+ renderLabel = (): React.ReactNode => {
68
+ const {children, labelClass, label} = this.props, leftElements = [], rightElements = [];
69
+ if (Array.isArray(children)) {
70
+ for (let child of children) {
71
+ if (child !== undefined && child !== null) {
72
+ //@ts-ignore
73
+ const {placement, element} = child;
74
+ if (placement === 'left') leftElements.push(element);
75
+ else rightElements.push(element);
76
+ }
77
+ }
78
+ } else if (isNotNull(children)) {
79
+ //@ts-ignore
80
+ const {placement, element} = children;
81
+ if (placement === 'left') leftElements.push(element);
82
+ else rightElements.push(element);
83
+ }
84
+ return (
85
+ <span className={classNames('outlinedButtonLabel', isNull(children) && 'singleChild', labelClass)}
86
+ style={this.getLabelStyle()}>
87
+ {leftElements.map((element, key) => ({...element, key}))}
88
+ {isNotNull(label) && <span className='buttonLabel'>{label}</span>}
89
+ {rightElements.map((element, key) => ({...element, key}))}
90
+ </span>)
91
+ };
92
+
93
+ render = () => {
94
+ const {id, onClick, onMouseEnter, onMouseLeave, onMouseDown, withRipple, title, tabIndex} = this.props,
95
+ titleProps = isNotNull(title) ? {title} : {};
96
+ return (
97
+ <div className={this.getContainerClass()} id={id} style={this.getContainerStyle()} onClick={onClick}
98
+ onMouseEnter={onMouseEnter} onMouseLeave={onMouseLeave} onMouseDown={onMouseDown}
99
+ tabIndex={tabIndex} {...titleProps}>
100
+ {this.renderLabel()}
101
+ {withRipple && <div className='ripple' style={{backgroundColor: this.getRippleColor()}}/>}
102
+ </div>
103
+ )
104
+ };
105
+ }