@dvrd/dvr-controls 1.0.14 → 1.0.16

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 (180) hide show
  1. package/index.ts +8 -1
  2. package/package.json +29 -23
  3. package/src/js/button/button.tsx +102 -0
  4. package/src/js/button/buttonController.tsx +179 -0
  5. package/src/js/button/closeButton.tsx +29 -0
  6. package/src/js/button/dvrdButton.tsx +128 -0
  7. package/src/js/button/outlinedButton.tsx +105 -0
  8. package/src/js/button/simpleButton.tsx +163 -0
  9. package/src/js/button/style/button.scss +95 -0
  10. package/src/js/button/style/closeButton.scss +15 -0
  11. package/src/js/button/style/dvrdButton.scss +30 -0
  12. package/src/js/button/style/outlinedButton.scss +84 -0
  13. package/src/js/button/style/simpleButton.scss +80 -0
  14. package/src/js/carousel/DVRCarousel.tsx +163 -0
  15. package/src/js/carousel/DVRCarouselController.tsx +95 -0
  16. package/src/js/carousel/style/DVRCarousel.scss +38 -0
  17. package/src/js/checkbox/checkbox.tsx +148 -0
  18. package/src/js/checkbox/checkboxController.tsx +131 -0
  19. package/src/js/checkbox/style/checkbox.scss +109 -0
  20. package/src/js/colorPicker/colorPicker.tsx +118 -0
  21. package/src/js/colorPicker/style/colorPicker.scss +20 -0
  22. package/src/js/date/dvrdDatePicker.tsx +357 -0
  23. package/src/js/date/style/dvrdDatePicker.scss +307 -0
  24. package/src/js/dialog/dialog.tsx +207 -0
  25. package/src/js/dialog/dialogController.tsx +70 -0
  26. package/src/js/dialog/inlineDialog.tsx +127 -0
  27. package/src/js/dialog/style/dialog.scss +61 -0
  28. package/src/js/events/withEvents.tsx +40 -0
  29. package/src/js/head/DVRHead.tsx +49 -0
  30. package/src/js/header/DVRHeader.tsx +417 -0
  31. package/src/js/header/style/header.scss +206 -0
  32. package/src/js/icon/awesomeIcon.tsx +20 -0
  33. package/src/js/image/imageUpload.tsx +69 -0
  34. package/src/js/image/style/imageUpload.scss +11 -0
  35. package/src/js/info/info.tsx +136 -0
  36. package/src/js/info/style/info.scss +39 -0
  37. package/src/js/input/animated/animatedTextField.tsx +159 -0
  38. package/src/js/input/date/dateField.tsx +360 -0
  39. package/src/js/input/date/dateFieldController.tsx +245 -0
  40. package/src/js/input/date/datePicker/datePicker.tsx +186 -0
  41. package/src/js/input/date/datePicker/style/datePicker.scss +102 -0
  42. package/src/js/input/date/input/dateInput.tsx +214 -0
  43. package/src/js/input/date/style/dateField.scss +40 -0
  44. package/src/js/input/date/timePicker/style/timePicker.scss +95 -0
  45. package/src/js/input/date/timePicker/timePicker.tsx +143 -0
  46. package/src/js/input/editor/DVREditor.tsx +21 -0
  47. package/src/js/input/number/numberInput.tsx +157 -0
  48. package/src/js/input/password/passwordInput.tsx +140 -0
  49. package/src/js/input/password/passwordRules.tsx +48 -0
  50. package/src/js/input/password/style/passwordInput.scss +39 -0
  51. package/src/js/input/password/style/passwordRules.scss +41 -0
  52. package/src/js/input/simple/style/simpleInput.scss +98 -0
  53. package/src/js/input/simple/v2/simpleInputV2.tsx +178 -0
  54. package/src/js/input/style/input.scss +138 -0
  55. package/src/js/input/v2/inputController_v2.tsx +250 -0
  56. package/src/js/input/v2/input_v2.tsx +7 -0
  57. package/src/js/label/label.tsx +196 -0
  58. package/src/js/label/style/label.scss +4 -0
  59. package/src/js/link/link.tsx +38 -0
  60. package/src/js/link/style/link.scss +30 -0
  61. package/src/js/loader/loader.tsx +79 -0
  62. package/src/js/loader/loaderController.tsx +61 -0
  63. package/src/js/loader/style/loader.scss +53 -0
  64. package/src/js/media/media.tsx +72 -0
  65. package/src/js/navigator/navigator.tsx +51 -0
  66. package/src/js/optionsList/dvrdOptionsList.tsx +112 -0
  67. package/src/js/optionsList/style/dvrdOptionsList.scss +84 -0
  68. package/src/js/optionsMenu/optionsMenu.tsx +187 -0
  69. package/src/js/optionsMenu/style/optionsMenu.scss +70 -0
  70. package/src/js/pdf/element/pdfElement.tsx +315 -0
  71. package/src/js/pdf/element/style/pdfElement.scss +111 -0
  72. package/src/js/pdf/history/pdfHistory.ts +57 -0
  73. package/src/js/pdf/image/pdfImage.tsx +175 -0
  74. package/src/js/pdf/image/style/pdfImage.scss +34 -0
  75. package/src/js/pdf/invoiceTable/pdfInvoiceTable.tsx +176 -0
  76. package/src/js/pdf/invoiceTable/style/pdfInvoiceTable.scss +32 -0
  77. package/src/js/pdf/pdfTemplateCreator.tsx +279 -0
  78. package/src/js/pdf/settings/buttons/iconButton.tsx +49 -0
  79. package/src/js/pdf/settings/buttons/style/iconButton.scss +50 -0
  80. package/src/js/pdf/settings/image/pdfImageSettings.tsx +82 -0
  81. package/src/js/pdf/settings/image/style/pdfImageSettings.scss +9 -0
  82. package/src/js/pdf/settings/invoiceTable/pdfInvoiceTableSettings.tsx +141 -0
  83. package/src/js/pdf/settings/invoiceTable/style/pdfInvoiceTableSettings.scss +38 -0
  84. package/src/js/pdf/settings/pdfElementSettings.tsx +86 -0
  85. package/src/js/pdf/settings/style/pdfElementSettings.scss +56 -0
  86. package/src/js/pdf/settings/text/pdfTextSettings.tsx +202 -0
  87. package/src/js/pdf/settings/text/style/pdfTextSettings.scss +94 -0
  88. package/src/js/pdf/style/pdfTemplateCreator.scss +118 -0
  89. package/src/js/pdf/text/pdfText.tsx +267 -0
  90. package/src/js/pdf/text/style/pdfText.scss +22 -0
  91. package/src/js/pdf/v2/pdfElement/pdfDraggableElement.tsx +193 -0
  92. package/src/js/pdf/v2/types/pdfTemplateTypes.ts +27 -0
  93. package/src/js/popup/style/withBackground.scss +29 -0
  94. package/src/js/popup/withBackground.tsx +92 -0
  95. package/src/js/select/async/asyncSelect.tsx +46 -0
  96. package/src/js/select/async/style/asyncSelect.scss +23 -0
  97. package/src/js/select/dvrdSelect.tsx +214 -0
  98. package/src/js/select/dvrdSelectController.tsx +81 -0
  99. package/src/js/select/select.tsx +310 -0
  100. package/src/js/select/selectController.tsx +341 -0
  101. package/src/js/select/style/dvrdSelect.scss +140 -0
  102. package/src/js/select/style/select.scss +199 -0
  103. package/src/js/sidebarMenu/sidebarMenu.tsx +167 -0
  104. package/src/js/sidebarMenu/style/sidebarMenu.scss +167 -0
  105. package/src/js/slider/DVRSlider.tsx +107 -0
  106. package/src/js/slider/style/DVRSlider.scss +88 -0
  107. package/src/js/snackbar/snackbar.tsx +72 -0
  108. package/src/js/snackbar/snackbarController.tsx +104 -0
  109. package/src/js/snackbar/style/snackbar.scss +46 -0
  110. package/src/js/switch/dvrdSwitch.tsx +53 -0
  111. package/src/js/switch/style/dvrdSwitch.scss +47 -0
  112. package/src/js/switch/style/switch.scss +84 -0
  113. package/src/js/switch/switch.tsx +115 -0
  114. package/src/js/switch/switchController.tsx +97 -0
  115. package/src/js/textField/dvrdInput.tsx +219 -0
  116. package/src/js/textField/dvrdInputController.tsx +97 -0
  117. package/src/js/textField/dvrdNumberInput.tsx +141 -0
  118. package/src/js/textField/dvrdPasswordInput.tsx +40 -0
  119. package/src/js/textField/style/dvrdInput.scss +114 -0
  120. package/src/js/textField/style/dvrdPassword.scss +15 -0
  121. package/src/js/topButton/style/topButton.scss +54 -0
  122. package/src/js/topButton/topButton.tsx +136 -0
  123. package/src/js/util/analyticsUtil.ts +41 -0
  124. package/src/js/util/colorUtil.ts +230 -0
  125. package/src/js/util/componentUtil.tsx +59 -0
  126. package/src/js/util/constants.ts +12 -0
  127. package/src/js/util/controlContext.tsx +46 -0
  128. package/src/js/util/controlUtil.ts +107 -0
  129. package/src/js/util/cookieUtil.ts +17 -0
  130. package/src/js/util/eventUtil.ts +65 -0
  131. package/src/js/util/googleUtil.ts +88 -0
  132. package/src/js/util/interfaces.ts +180 -0
  133. package/src/js/util/jwtUtil.ts +72 -0
  134. package/src/js/util/miscUtil.ts +170 -0
  135. package/src/js/util/momentUtil.ts +45 -0
  136. package/src/js/util/pdfUtil.ts +124 -0
  137. package/src/js/util/requestUtil.ts +145 -0
  138. package/src/js/util/responsiveUtil.ts +37 -0
  139. package/src/js/util/validationUtil.ts +13 -0
  140. package/src/res/img/lock-handle.png +0 -0
  141. package/src/res/img/lock-handle.webp +0 -0
  142. package/src/res/img/lock.png +0 -0
  143. package/src/res/img/lock.webp +0 -0
  144. package/src/style/common-icons-variables.scss +140 -0
  145. package/src/style/common-icons.scss +714 -0
  146. package/src/style/common-variables.scss +243 -0
  147. package/src/style/display-breakpoints.scss +141 -0
  148. package/src/style/fonts/common-icons.eot +0 -0
  149. package/src/style/fonts/common-icons.svg +150 -0
  150. package/src/style/fonts/common-icons.ttf +0 -0
  151. package/src/style/fonts/common-icons.woff +0 -0
  152. package/src/style/fonts/common-icons.woff2 +0 -0
  153. package/src/style/fonts/fontAwesome/css/all.css +7003 -0
  154. package/src/style/fonts/fontAwesome/css/all.min.css +6 -0
  155. package/src/style/fonts/fontAwesome/css/brands.css +1423 -0
  156. package/src/style/fonts/fontAwesome/css/brands.min.css +6 -0
  157. package/src/style/fonts/fontAwesome/css/fontawesome.css +5519 -0
  158. package/src/style/fonts/fontAwesome/css/fontawesome.min.css +6 -0
  159. package/src/style/fonts/fontAwesome/css/regular.css +19 -0
  160. package/src/style/fonts/fontAwesome/css/regular.min.css +6 -0
  161. package/src/style/fonts/fontAwesome/css/solid.css +19 -0
  162. package/src/style/fonts/fontAwesome/css/solid.min.css +6 -0
  163. package/src/style/fonts/fontAwesome/css/svg-with-js.css +634 -0
  164. package/src/style/fonts/fontAwesome/css/svg-with-js.min.css +6 -0
  165. package/src/style/fonts/fontAwesome/css/v4-font-face.css +26 -0
  166. package/src/style/fonts/fontAwesome/css/v4-font-face.min.css +6 -0
  167. package/src/style/fonts/fontAwesome/css/v4-shims.css +2146 -0
  168. package/src/style/fonts/fontAwesome/css/v4-shims.min.css +6 -0
  169. package/src/style/fonts/fontAwesome/css/v5-font-face.css +22 -0
  170. package/src/style/fonts/fontAwesome/css/v5-font-face.min.css +6 -0
  171. package/src/style/fonts/fontAwesome/webfonts/fa-brands-400.ttf +0 -0
  172. package/src/style/fonts/fontAwesome/webfonts/fa-brands-400.woff2 +0 -0
  173. package/src/style/fonts/fontAwesome/webfonts/fa-regular-400.ttf +0 -0
  174. package/src/style/fonts/fontAwesome/webfonts/fa-regular-400.woff2 +0 -0
  175. package/src/style/fonts/fontAwesome/webfonts/fa-solid-900.ttf +0 -0
  176. package/src/style/fonts/fontAwesome/webfonts/fa-solid-900.woff2 +0 -0
  177. package/src/style/fonts/fontAwesome/webfonts/fa-v4compatibility.ttf +0 -0
  178. package/src/style/fonts/fontAwesome/webfonts/fa-v4compatibility.woff2 +0 -0
  179. package/src/style/variables.scss +11 -0
  180. package/.gitignore +0 -31
@@ -0,0 +1,163 @@
1
+ /*
2
+ * Copyright (c) 2021. Dave van Rijn Development
3
+ */
4
+
5
+ import './style/simpleButton.scss';
6
+
7
+ import React, {CSSProperties, PureComponent, ReactNode} from 'react';
8
+ import {ControlContext} from "../util/controlContext";
9
+ import {colorIsWhite, convertColor, editColor} from "../util/colorUtil";
10
+ import {ControlPadding, ElementPosition, OrnamentShape} from "../util/interfaces";
11
+ import classNames from "classnames";
12
+ import {voidFunction} from "../util/controlUtil";
13
+
14
+ interface Props {
15
+ onClick: any;
16
+ onMouseEnter: any;
17
+ onMouseLeave: any;
18
+ onMouseDown: any;
19
+ label: string;
20
+ containerClass: string;
21
+ labelClass: string;
22
+ id: string;
23
+ padding: ControlPadding;
24
+ disabled: boolean;
25
+ isHovered: boolean;
26
+ baseColor?: string;
27
+ textColor?: string;
28
+ title?: string;
29
+ withRipple: boolean;
30
+ primary: boolean;
31
+ tabIndex?: number;
32
+ children?: ReactNode | ReactNode[] | OrnamentShape | OrnamentShape[];
33
+ }
34
+
35
+ export default class SimpleButton extends PureComponent<Props> {
36
+ declare context: React.ContextType<typeof ControlContext>;
37
+ static contextType = ControlContext;
38
+
39
+ getBaseColor = (trueBase: boolean = false): string => {
40
+ const {baseColor, textColor, primary} = this.props;
41
+ let color: string;
42
+ if (baseColor && baseColor.length) return convertColor(baseColor);
43
+ else color = this.context.baseColor;
44
+ color = convertColor(color);
45
+ if (colorIsWhite(color) && !trueBase && primary) {
46
+ if (textColor && textColor.length) color = textColor;
47
+ else color = this.context.contrastColor;
48
+ color = convertColor(color);
49
+ }
50
+ return color;
51
+ };
52
+
53
+ getContrastColor = (allowWhite: boolean = true) => {
54
+ const {textColor, primary, isHovered} = this.props, {baseColor, contrastColor} = this.context;
55
+ if (textColor && textColor.length) return convertColor(textColor);
56
+ const trueBase = this.getBaseColor(true);
57
+ if (colorIsWhite(trueBase) && primary) return trueBase;
58
+
59
+ let color: string;
60
+ if (textColor && textColor.length) color = textColor;
61
+ else {
62
+ color = convertColor(contrastColor);
63
+ if (!primary && !isHovered) {
64
+ color = convertColor(baseColor);
65
+ if (colorIsWhite(color) && !allowWhite)
66
+ color = convertColor(contrastColor);
67
+ }
68
+ }
69
+ return color;
70
+ };
71
+
72
+ getContainerClass = (): string => {
73
+ const {containerClass, padding, disabled, withRipple, primary} = this.props;
74
+ return classNames('dvr-simple-button', padding, disabled && 'disabled', withRipple && 'ripple',
75
+ primary && 'primary', containerClass);
76
+ };
77
+
78
+ getContainerStyle = (): CSSProperties => {
79
+ const {disabled, isHovered, primary} = this.props, baseColor = this.getBaseColor();
80
+ let backgroundColor: string;
81
+ if (disabled) backgroundColor = 'color-gray-6';
82
+ else if (isHovered) {
83
+ if (primary) backgroundColor = editColor(-.2, baseColor);
84
+ else backgroundColor = editColor(-.2, baseColor);
85
+ } else if (!primary) backgroundColor = 'transparent';
86
+ else backgroundColor = baseColor;
87
+ return {backgroundColor: convertColor(backgroundColor)};
88
+ };
89
+
90
+ getLabelStyle = (): CSSProperties => {
91
+ const {disabled} = this.props, textColor = this.getContrastColor(false),
92
+ style: CSSProperties = {};
93
+ let color: string;
94
+ if (disabled) color = 'gray';
95
+ else color = textColor;
96
+ style.color = convertColor(color);
97
+
98
+ const childCount = this.getLabelChildCount();
99
+ style.gridTemplateColumns = `repeat(${childCount}, auto)`;
100
+ return style;
101
+ };
102
+
103
+ getLabelChildCount = () => {
104
+ const {label, children} = this.props;
105
+ let childCount = 0;
106
+ if (label && label.length) childCount++;
107
+ if (Array.isArray(children)) {
108
+ for (const child of children) {
109
+ if (this.isOrnament(child)) childCount++;
110
+ }
111
+ } else if (this.isOrnament(children)) childCount++;
112
+ return Math.min(3, childCount);
113
+ };
114
+
115
+ isOrnament = (obj: any) => obj && obj.hasOwnProperty('element');
116
+
117
+ placementIsMatch = (ornament: OrnamentShape, placement: ElementPosition) => ornament.placement === placement;
118
+
119
+ renderOrnament = (placement: ElementPosition) => {
120
+ const {children, onClick} = this.props;
121
+ let ornament: OrnamentShape | null = null;
122
+ if (Array.isArray(children)) {
123
+ for (const child of children) {
124
+ if (this.isOrnament(child) && this.placementIsMatch(child as OrnamentShape, placement)) {
125
+ ornament = child as OrnamentShape;
126
+ break;
127
+ }
128
+ }
129
+ } else if (this.isOrnament(children) && this.placementIsMatch(children as OrnamentShape, placement)) {
130
+ ornament = children as OrnamentShape;
131
+ }
132
+ if (ornament !== null) return (
133
+ <div className={classNames('dvr-simple-button-ornament', placement)}
134
+ onClick={ornament.allowPropagation ? onClick : voidFunction}>
135
+ {ornament.element}
136
+ </div>
137
+ );
138
+ return null;
139
+ };
140
+
141
+ renderLabel = () => {
142
+ const {label, labelClass} = this.props;
143
+ return <label className={classNames('dvr-simple-button-label', labelClass)}>{label}</label>;
144
+ };
145
+
146
+ render = () => {
147
+ const {onClick, onMouseEnter, onMouseLeave, id, onMouseDown, withRipple, title, disabled, tabIndex} = this.props,
148
+ titleProp = title !== undefined ? {title} : {};
149
+ return (
150
+ <div className={this.getContainerClass()} style={this.getContainerStyle()}
151
+ onClick={disabled ? voidFunction : onClick}
152
+ onMouseEnter={onMouseEnter} onMouseLeave={onMouseLeave} onMouseDown={onMouseDown}
153
+ id={id} tabIndex={tabIndex} {...titleProp}>
154
+ <div className='dvr-simple-button-label-container' style={this.getLabelStyle()}>
155
+ {this.renderOrnament(ElementPosition.LEFT)}
156
+ {this.renderLabel()}
157
+ {this.renderOrnament(ElementPosition.RIGHT)}
158
+ </div>
159
+ {withRipple && <div className='ripple' style={{backgroundColor: this.getContrastColor()}}/>}
160
+ </div>
161
+ )
162
+ };
163
+ }
@@ -0,0 +1,95 @@
1
+ /*!
2
+ * Copyright (c) 2021. Dave van Rijn Development
3
+ */
4
+
5
+ @import '../../../style/variables';
6
+
7
+ .buttonController {
8
+ overflow: hidden;
9
+ display: inline-block;
10
+
11
+ &:not(.disabled) {
12
+ @include backgroundShadow;
13
+ }
14
+
15
+ border-radius: .3rem;
16
+ position: relative;
17
+ padding: .5rem 1rem;
18
+ cursor: pointer;
19
+ box-sizing: border-box;
20
+ transition: background-color .2s ease-in-out;
21
+
22
+ .buttonLabel {
23
+ position: relative;
24
+ display: flex;
25
+ align-items: center;
26
+ justify-content: space-between;
27
+ cursor: inherit;
28
+ pointer-events: none;
29
+ font-size: .9rem;
30
+ font-weight: 500;
31
+ text-transform: uppercase;
32
+ font-family: 'Roboto', sans-serif;
33
+
34
+ &.singleChild {
35
+ justify-content: center;
36
+ }
37
+
38
+ .buttonLabel {
39
+ text-align: center;
40
+ }
41
+
42
+ * {
43
+ user-select: none;
44
+ margin-right: .5rem;
45
+
46
+ &:last-child {
47
+ margin-right: 0;
48
+ }
49
+ }
50
+ }
51
+
52
+ .ripple {
53
+ border-radius: 50%;
54
+ position: absolute;
55
+ opacity: .5;
56
+ width: 10%;
57
+ padding-top: 10%;
58
+ visibility: hidden;
59
+ pointer-events: none;
60
+ }
61
+
62
+ &.rippling {
63
+ .ripple {
64
+ visibility: visible;
65
+ opacity: 0;
66
+ transform: scale(15);
67
+ transition: opacity .5s ease-in-out, transform .5s ease-in-out, opacity .5s ease;
68
+ }
69
+ }
70
+
71
+ &.sp {
72
+ padding: .4rem .5rem;
73
+
74
+ .buttonLabel {
75
+ font-size: .8rem;
76
+ }
77
+ }
78
+
79
+ &.lp {
80
+ padding: .8rem 1.5rem;
81
+ }
82
+
83
+ &.disabled {
84
+ background-color: $color-gray-6 !important;
85
+ cursor: not-allowed;
86
+
87
+ .buttonLabel {
88
+ color: $color-gray-2 !important;
89
+ }
90
+ }
91
+
92
+ &:active {
93
+ box-shadow: none;
94
+ }
95
+ }
@@ -0,0 +1,15 @@
1
+ /*!
2
+ * Copyright (c) 2021. Dave van Rijn Development
3
+ */
4
+
5
+ @import '../../../style/variables';
6
+
7
+ .close-button {
8
+ cursor: pointer;
9
+ transition: color .2s ease-in-out;
10
+ font-size: .8rem;
11
+
12
+ &:hover {
13
+ color: red !important;
14
+ }
15
+ }
@@ -0,0 +1,30 @@
1
+ /*!
2
+ * Copyright (c) 2021. Dave van Rijn Development
3
+ */
4
+
5
+ @import '../../../style/variables';
6
+
7
+ .dvrd-button {
8
+ @include backgroundShadow2;
9
+ padding: .7rem 1rem;
10
+ cursor: pointer;
11
+ transition: background-color .2s ease-in-out;
12
+ display: inline-grid;
13
+ align-items: center;
14
+ grid-column-gap: .5rem;
15
+ justify-content: center;
16
+ justify-items: center;
17
+
18
+ &, * {
19
+ user-select: none;
20
+ }
21
+
22
+ .dvrd-button-label {
23
+ transition: color .2s ease-in-out;
24
+ }
25
+
26
+ &.disabled {
27
+ cursor: not-allowed;
28
+ box-shadow: none;
29
+ }
30
+ }
@@ -0,0 +1,84 @@
1
+ /*!
2
+ * Copyright (c) 2021. Dave van Rijn Development
3
+ */
4
+
5
+ @import '../../../style/variables';
6
+
7
+ .outlinedButtonContainer {
8
+ @include borderRadius(.3rem);
9
+ position: relative;
10
+ padding: .37rem 1rem;
11
+ cursor: pointer;
12
+ box-sizing: border-box;
13
+ border: 2px solid transparent;
14
+ transition: border-color .2s ease-in-out;
15
+ overflow: hidden;
16
+ display: inline-block;
17
+
18
+ .outlinedButtonLabel {
19
+ position: relative;
20
+ display: flex;
21
+ align-items: center;
22
+ justify-content: space-between;
23
+ cursor: inherit;
24
+ pointer-events: none;
25
+ font-size: .9rem;
26
+ font-weight: 500;
27
+ text-transform: uppercase;
28
+ font-family: 'Roboto', sans-serif;
29
+ transition: color .2s ease-in-out;
30
+
31
+ &.singleChild {
32
+ justify-content: center;
33
+ }
34
+
35
+ .buttonLabel {
36
+ text-align: center;
37
+ }
38
+
39
+ * {
40
+ user-select: none;
41
+ margin-right: .5rem;
42
+
43
+ &:last-child {
44
+ margin-right: 0;
45
+ }
46
+ }
47
+ }
48
+
49
+ .ripple {
50
+ @include borderRadius(50%);
51
+ position: absolute;
52
+ opacity: .7;
53
+ width: 10%;
54
+ padding-top: 10%;
55
+ visibility: hidden;
56
+ pointer-events: none;
57
+ }
58
+
59
+ &.rippling {
60
+ .ripple {
61
+ visibility: visible;
62
+ opacity: 0;
63
+ transform: scale(15);
64
+ transition: opacity .5s ease-in-out, transform .5s ease-in-out, opacity .5s ease;
65
+ }
66
+ }
67
+
68
+ &.sp {
69
+ padding: .2rem .5rem;
70
+ }
71
+
72
+ &.lp {
73
+ padding: .8rem 1.5rem;
74
+ }
75
+
76
+ &.disabled {
77
+ border-color: $color-gray-6 !important;
78
+ cursor: not-allowed;
79
+
80
+ .outlinedButtonLabel {
81
+ color: $color-gray-2 !important;
82
+ }
83
+ }
84
+ }
@@ -0,0 +1,80 @@
1
+ /*!
2
+ * Copyright (c) 2021. Dave van Rijn Development
3
+ */
4
+
5
+ @import '../../../style/variables';
6
+
7
+ @import '../../../style/variables';
8
+
9
+ .dvr-simple-button {
10
+ position: relative;
11
+ overflow: hidden;
12
+ border-radius: 1rem;
13
+ cursor: pointer;
14
+ padding: .5rem 1rem;
15
+ transition: background-color .2s ease-in-out;
16
+ display: inline-block;
17
+
18
+ &, * {
19
+ user-select: none;
20
+ }
21
+
22
+ .dvr-simple-button-label-container {
23
+ display: inline-grid;
24
+ grid-column-gap: .25rem;
25
+
26
+ .dvr-simple-button-ornament {
27
+ font-size: .9rem;
28
+ }
29
+
30
+ .dvr-simple-button-label {
31
+ font-size: .9rem;
32
+ cursor: inherit;
33
+ font-weight: 500;
34
+ text-align: center;
35
+ transition: color .2s ease-in-out;
36
+ white-space: nowrap;
37
+
38
+ &:only-child {
39
+ grid-column-start: 1;
40
+ grid-column-end: 4;
41
+ }
42
+ }
43
+ }
44
+
45
+ .ripple {
46
+ @include borderRadius(50%);
47
+ position: absolute;
48
+ opacity: .5;
49
+ width: 10%;
50
+ padding-top: 10%;
51
+ visibility: hidden;
52
+ pointer-events: none;
53
+ }
54
+
55
+ &.rippling {
56
+ .ripple {
57
+ visibility: visible;
58
+ opacity: 0;
59
+ transform: scale(15);
60
+ transition: opacity .5s ease-in-out, transform .5s ease-in-out, opacity .5s ease;
61
+ }
62
+ }
63
+
64
+ &, * {
65
+ box-sizing: border-box;
66
+ }
67
+
68
+ &.primary {
69
+ @include backgroundShadow;
70
+ }
71
+
72
+ &.disabled {
73
+ box-shadow: none !important;
74
+ cursor: not-allowed !important;
75
+ }
76
+
77
+ &.sp {
78
+ padding: .25rem .5rem;
79
+ }
80
+ }
@@ -0,0 +1,163 @@
1
+ /*
2
+ * Copyright (c) 2021. Dave van Rijn Development
3
+ */
4
+ import './style/DVRCarousel.scss';
5
+
6
+ import React, {MouseEventHandler} from 'react';
7
+ import {PureComponent, ReactElement} from "react";
8
+ import AwesomeIcon from "../icon/awesomeIcon";
9
+ import classNames from "classnames";
10
+ import {voidFunction} from "../util/controlUtil";
11
+ import isEqual from 'lodash/isEqual';
12
+ import {debug} from "../../..";
13
+
14
+ interface Props {
15
+ onClickNext: MouseEventHandler;
16
+ onClickPrev: MouseEventHandler;
17
+ children: ReactElement[];
18
+ currentIndex: number;
19
+ visibleItems: number;
20
+ lazy: boolean;
21
+ className: string;
22
+ showControls: boolean;
23
+ infinite: boolean;
24
+ variableWidth: boolean;
25
+ }
26
+
27
+ interface State {
28
+ initialRendered: boolean;
29
+ }
30
+
31
+ export default class DVRCarousel extends PureComponent<Props, State> {
32
+ state: State = {
33
+ initialRendered: false,
34
+ }
35
+ carousel: HTMLDivElement;
36
+
37
+ getMaxWidth = (): number => {
38
+ const {children, visibleItems} = this.props;
39
+ let width = 0;
40
+ for (let i = 0; i < children.length; i++) {
41
+ let combinedWidth = 0;
42
+ for (let j = i; j < i + visibleItems && j < children.length; j++) {
43
+ const container = this.getItemContainer(j);
44
+ if (container) combinedWidth += container.offsetWidth;
45
+ }
46
+ if (combinedWidth > width) width = combinedWidth;
47
+ }
48
+ return width;
49
+ };
50
+
51
+ getVisibleIndexes = (): { firstIndex: number, lastIndex: number } => {
52
+ const {currentIndex, visibleItems, infinite, children} = this.props,
53
+ itemsBefore = Math.floor((visibleItems - 1) / 2), itemsAfter = Math.ceil((visibleItems - 1) / 2)
54
+ let firstIndex = currentIndex - itemsBefore, lastIndex = currentIndex + itemsAfter;
55
+ if (firstIndex < 0) {
56
+ lastIndex = visibleItems - 1;
57
+ firstIndex = 0;
58
+ }
59
+ if (lastIndex > children.length - 1) {
60
+ if (infinite) lastIndex -= (children.length - 1)
61
+ else {
62
+ lastIndex = children.length - -1;
63
+ firstIndex = Math.max(0, lastIndex - visibleItems);
64
+ }
65
+ }
66
+ return {firstIndex, lastIndex};
67
+ };
68
+
69
+ getItemContainer = (index: number): HTMLDivElement | null => {
70
+ return document.querySelector(`div[data-name=dvr-carousel-${index}]`);
71
+ }
72
+
73
+ getVisibleWidth = (): number => {
74
+ const {firstIndex, lastIndex} = this.getVisibleIndexes();
75
+ let width: number = 0;
76
+ for (let i = firstIndex; i <= lastIndex; i++) {
77
+ const container: HTMLDivElement | null = this.getItemContainer(i);
78
+ if (container) width += container.offsetWidth;
79
+ }
80
+ return width;
81
+ };
82
+
83
+ setStyle = () => {
84
+ if (this.carousel) {
85
+ const {variableWidth} = this.props, {firstIndex} = this.getVisibleIndexes();
86
+ let left: number = 0;
87
+ if (firstIndex > 0) {
88
+ for (let i = 0; i < firstIndex; i++) {
89
+ const container: HTMLDivElement | null = this.getItemContainer(i);
90
+ if (container) left -= container.offsetWidth;
91
+ }
92
+ }
93
+ const itemsContainer: HTMLDivElement | null = this.carousel.querySelector('div.items-container');
94
+ if (variableWidth)
95
+ this.carousel.style.width = this.getVisibleWidth() + 'px';
96
+ else this.carousel.style.width = this.getMaxWidth() + 'px';
97
+
98
+ if (itemsContainer)
99
+ itemsContainer.style.transform = `translateX(${left}px)`;
100
+
101
+ }
102
+ if (!this.state.initialRendered) this.setState({initialRendered: true});
103
+ }
104
+
105
+ renderPrevControl = () => {
106
+ const {showControls, onClickPrev, currentIndex, infinite} = this.props;
107
+ if (!showControls) return null;
108
+ const disabled = currentIndex === 0 && !infinite;
109
+ return <AwesomeIcon name='chevron-left'
110
+ className={classNames('carousel-control', 'prev', disabled && 'disabled')}
111
+ onClick={disabled ? voidFunction : onClickPrev}/>;
112
+ };
113
+
114
+ renderNextControl = () => {
115
+ const {showControls, onClickNext, currentIndex, infinite, children, visibleItems} = this.props;
116
+ if (!showControls) return null;
117
+ const disabled = currentIndex === (children.length - 1) - visibleItems && !infinite;
118
+ return <AwesomeIcon name='chevron-right'
119
+ className={classNames('carousel-control', 'next', disabled && 'disabled')}
120
+ onClick={disabled ? voidFunction : onClickNext}/>;
121
+ };
122
+
123
+ renderItems = () => {
124
+ const {lazy, children} = this.props, {initialRendered} = this.state, {firstIndex, lastIndex} = this.getVisibleIndexes();
125
+ return (
126
+ <div className='carousel-items-container' ref={(ref: HTMLDivElement) => {
127
+ this.carousel = ref;
128
+ }}>
129
+ <div className='items-container'>
130
+ {children.map((child: ReactElement, index: number) => {
131
+ const hidden = !initialRendered || index < firstIndex || index > lastIndex;
132
+ return (
133
+ <div key={index} className={classNames('carousel-item', hidden && 'hidden')}
134
+ data-name={`dvr-carousel-${index}`}>
135
+ {(!hidden || !lazy) && child}
136
+ </div>
137
+ )
138
+ })}
139
+ </div>
140
+ </div>
141
+ )
142
+ };
143
+
144
+ componentDidMount = () => {
145
+ window.setTimeout(this.setStyle, 0);
146
+ };
147
+
148
+ componentDidUpdate = (prevProps: Props, prevState: State) => {
149
+ const {currentIndex, visibleItems, children} = this.props, {initialRendered} = this.state;
150
+ if (currentIndex !== prevProps.currentIndex || visibleItems !== prevProps.visibleItems || !isEqual(children, prevProps.children) || initialRendered !== prevState.initialRendered)
151
+ window.setTimeout(this.setStyle, 0);
152
+ };
153
+
154
+ render = () => {
155
+ return (
156
+ <div className='dvr-carousel'>
157
+ {this.renderPrevControl()}
158
+ {this.renderItems()}
159
+ {this.renderNextControl()}
160
+ </div>
161
+ )
162
+ };
163
+ }