@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,141 @@
1
+ /*
2
+ * Copyright (c) 2021. Dave van Rijn Development
3
+ */
4
+ import './style/pdfInvoiceTableSettings.scss';
5
+
6
+ import React, {PureComponent} from 'react';
7
+ import PdfInvoiceTable from "../../invoiceTable/pdfInvoiceTable";
8
+ import NumberInput from "../../../input/number/numberInput";
9
+ import {debug} from "../../../util/miscUtil";
10
+ import {ElementPosition} from "../../../util/interfaces";
11
+ import {fontItems} from "../../../util/pdfUtil";
12
+ import {ColorPicker, Select} from "../../../../../index";
13
+ import IconButton, {IconButtonType} from "../buttons/iconButton";
14
+
15
+ interface Props {
16
+ element: PdfInvoiceTable;
17
+ }
18
+
19
+ interface State {
20
+ widths: number[];
21
+ color: string;
22
+ colorPickerActive: boolean;
23
+ alignment?: ElementPosition;
24
+ }
25
+
26
+ const TITLES = ['Productnaam', 'Aantal', 'Prijs', 'BTW', 'Subtotaal'];
27
+
28
+ export default class PdfInvoiceTableSettings extends PureComponent<Props, State> {
29
+ constructor(props: Props) {
30
+ super(props);
31
+ const settings = props.element.getSettings();
32
+ this.state = {
33
+ widths: settings.widths,
34
+ color: settings.color,
35
+ colorPickerActive: false,
36
+ alignment: settings.alignment,
37
+ };
38
+ }
39
+
40
+ onCloseColorPicker = () => {
41
+ this.setState({colorPickerActive: false});
42
+ };
43
+
44
+ onOpenColorPicker = () => {
45
+ this.setState({colorPickerActive: true});
46
+ };
47
+
48
+ onPickColor = (close: boolean = true) => (color: string) => {
49
+ const {element} = this.props;
50
+ if (close)
51
+ this.setState({colorPickerActive: false, color}, () => {
52
+ element.setSetting('color', color)
53
+ });
54
+ else this.setState({color}, () => {
55
+ element.setSetting('color', color, undefined, false);
56
+ });
57
+ };
58
+
59
+ onChangeWidth = (index: number) => (value: number) => {
60
+ const {element} = this.props, widths = element.getSettings().widths.slice(),
61
+ remainder = this.getRemainingWidth(index);
62
+ debug('Remainder', {remainder});
63
+ if (value > remainder) value = remainder;
64
+ widths[index] = value;
65
+ element.setSetting('widths', widths);
66
+ this.setState({widths});
67
+ };
68
+
69
+ onToggleAlignment = (type: IconButtonType) => () => {
70
+ const {alignment} = this.state, {element} = this.props;
71
+ let nextAlignment: ElementPosition | undefined;
72
+ if (type === IconButtonType.LEFT)
73
+ nextAlignment = alignment === ElementPosition.LEFT ? undefined : ElementPosition.LEFT;
74
+ else if (type === IconButtonType.CENTER)
75
+ nextAlignment = alignment === ElementPosition.CENTER ? undefined : ElementPosition.CENTER;
76
+ else if (type === IconButtonType.RIGHT)
77
+ nextAlignment = alignment === ElementPosition.RIGHT ? undefined : ElementPosition.RIGHT;
78
+ element.setSetting('alignment', nextAlignment, () => {
79
+ this.setState({alignment: nextAlignment});
80
+ });
81
+ }
82
+
83
+ getRemainingWidth = (excludeIndex: number): number => {
84
+ const {widths} = this.state;
85
+ let remainder: number = 100;
86
+ for (let i = 0; i < widths.length; i++) {
87
+ if (i === excludeIndex) continue;
88
+ remainder -= widths[i];
89
+ }
90
+ return remainder;
91
+ }
92
+
93
+ renderWidth = (value: number, index: number) => {
94
+ const title = TITLES[index];
95
+ return (
96
+ <NumberInput key={index} value={value.toString()} onChange={this.onChangeWidth(index)} label={title}
97
+ ornaments={{
98
+ element: <span style={{cursor: 'text'}}>%</span>,
99
+ placement: ElementPosition.RIGHT,
100
+ allowPropagation: true
101
+ }} asNumber/>
102
+ );
103
+ };
104
+
105
+ render = () => {
106
+ const {widths, colorPickerActive, color, alignment} = this.state, {element} = this.props,
107
+ settings = element.getSettings();
108
+ return (
109
+ <div className='pdf-invoice-table-settings'>
110
+ <label className='settings-label'>Kolom breedtes</label>
111
+ <div className='center-btn'>
112
+ <IconButton onClick={this.onToggleAlignment} active={alignment === ElementPosition.LEFT}
113
+ type={IconButtonType.LEFT} title='Links'/>
114
+ <IconButton onClick={this.onToggleAlignment} active={alignment === ElementPosition.CENTER}
115
+ type={IconButtonType.CENTER} title='Centreren'/>
116
+ <IconButton onClick={this.onToggleAlignment} active={alignment === ElementPosition.RIGHT}
117
+ type={IconButtonType.RIGHT} title='Rechts'/>
118
+ </div>
119
+ {widths.map(this.renderWidth)}
120
+ <div className='divider'/>
121
+ <label className='settings-label'>Tekstgrootte</label>
122
+ <Select items={fontItems} value={settings.font} onSelect={element.changeSetting('font')}
123
+ label='Lettertype' selectOnly unControlled itemsHeight='15rem' fullWidth/>
124
+ <NumberInput value={settings.fontSize.toString()} onChange={element.changeSetting('fontSize')} asNumber
125
+ ornaments={{
126
+ element: <span style={{cursor: 'text'}}>px</span>,
127
+ placement: ElementPosition.RIGHT,
128
+ allowPropagation: true
129
+ }} wholeNumbers unControlled/>
130
+ <div className='settings-color-picker'>
131
+ <label className='picker-label'>Tekstkleur:</label>
132
+ <div className='color-preview' style={{backgroundColor: color}}
133
+ onClick={this.onOpenColorPicker}/>
134
+ <ColorPicker onClose={this.onCloseColorPicker} onSubmit={this.onPickColor()} closeable={false}
135
+ onPreChange={this.onPickColor(false)} color={settings.color}
136
+ visible={colorPickerActive} className='text-color-picker' transparent/>
137
+ </div>
138
+ </div>
139
+ )
140
+ }
141
+ }
@@ -0,0 +1,38 @@
1
+ /*!
2
+ * Copyright (c) 2021. Dave van Rijn Development
3
+ */
4
+
5
+ @import '../../../../../style/variables';
6
+
7
+ .pdf-invoice-table-settings {
8
+ display: grid;
9
+ grid-template-columns: repeat(2, calc(50% - .125rem));
10
+ grid-gap: .5rem;
11
+
12
+ .center-btn {
13
+ grid-column-start: span 2;
14
+ justify-items: start;
15
+ }
16
+
17
+ .settings-label {
18
+ grid-column-start: span 2;
19
+ font-weight: 500;
20
+ }
21
+
22
+ .divider {
23
+ grid-column-start: span 2;
24
+ width: 100%;
25
+ height: 1px;
26
+ background-color: $color-gray-4;
27
+ margin: .5rem 0;
28
+ }
29
+
30
+ @include break-lg-down {
31
+ grid-template-columns: auto;
32
+ grid-column-gap: 0;
33
+
34
+ .center-btn, .settings-label, .divider {
35
+ grid-column-start: unset;
36
+ }
37
+ }
38
+ }
@@ -0,0 +1,86 @@
1
+ /*
2
+ * Copyright (c) 2021. Dave van Rijn Development
3
+ */
4
+ import './style/pdfElementSettings.scss';
5
+
6
+ import React, {MouseEventHandler, PureComponent} from 'react';
7
+ import {PdfElement} from "../element/pdfElement";
8
+ import PdfText from "../text/pdfText";
9
+ import {PDFElementPersist, PdfFont, PDFTextVariables} from "../../util/interfaces";
10
+ import {Button, fontItems, Select, showDialog, stopPropagation} from "../../../../";
11
+ import PdfTextSettings from "./text/pdfTextSettings";
12
+ import PdfImage from "../image/pdfImage";
13
+ import PdfImageSettings from "./image/pdfImageSettings";
14
+ import PdfInvoiceTable from "../invoiceTable/pdfInvoiceTable";
15
+ import PdfInvoiceTableSettings from "./invoiceTable/pdfInvoiceTableSettings";
16
+
17
+ interface Props {
18
+ onReset: MouseEventHandler;
19
+ onChangeFont: (font: PdfFont) => void;
20
+ element: PdfElement | null;
21
+ customVariables?: PDFTextVariables;
22
+ font: PdfFont;
23
+ supportMultiPage: boolean;
24
+ }
25
+
26
+ export default class PdfElementSettings extends PureComponent<Props> {
27
+ onClickDelete = (evt: React.MouseEvent) => {
28
+ const {element} = this.props;
29
+ if (element) {
30
+ const persistence: PDFElementPersist = element.isPersistent();
31
+ if (persistence === PDFElementPersist.PERSISTENT) return;
32
+ else if (persistence === PDFElementPersist.CONFIRM) {
33
+ showDialog('We raden aan om dit element wel te tonen op de factuur. Weet je zeker dat je dit ' +
34
+ 'element wilt verwijderen?', 'Element verwijderen',
35
+ ['Nee', {label: 'Ja', onClick: element.onClickDelete}]);
36
+ } else element.onClickDelete(evt);
37
+ }
38
+ };
39
+
40
+ getTitle = (): string => {
41
+ const {element} = this.props;
42
+ if (element instanceof PdfText) return 'Tekst opties';
43
+ if (element instanceof PdfImage) return 'Afbeelding opties';
44
+ if (element instanceof PdfInvoiceTable) return 'Factuurregel opties';
45
+ return 'Opties'
46
+ };
47
+
48
+ renderSettings = () => {
49
+ const {element, customVariables, supportMultiPage} = this.props;
50
+ if (element === null) return this.renderMainSettings();
51
+ if (element instanceof PdfText) return <PdfTextSettings element={element} customVariables={customVariables}
52
+ supportMultiPage={supportMultiPage}/>;
53
+ if (element instanceof PdfImage) return <PdfImageSettings element={element}
54
+ supportMultiPage={supportMultiPage}/>;
55
+ if (element instanceof PdfInvoiceTable) return <PdfInvoiceTableSettings element={element}/>
56
+ return null;
57
+ };
58
+
59
+ renderMainSettings = () => {
60
+ const {font, onChangeFont} = this.props;
61
+ return (
62
+ <div className='main-settings'>
63
+ <Select items={fontItems} value={font} onSelect={onChangeFont} label='Standaard lettertype'
64
+ selectOnly fullWidth/>
65
+ </div>
66
+ )
67
+ };
68
+
69
+ render = () => {
70
+ const {element, onReset} = this.props, deleteAble = element?.isPersistent() !== PDFElementPersist.PERSISTENT;
71
+ return (
72
+ <div className='pdf-element-settings' onClick={stopPropagation}>
73
+ <h2 className='settings-title'>{this.getTitle()}</h2>
74
+ {!element && <label className='empty-label'>Selecteer een element om opties te weergeven</label>}
75
+ {this.renderSettings()}
76
+ {element !== null && (
77
+ <div className='buttons-container'>
78
+ <Button onClick={onReset} label='Oké' className='reset-btn'/>
79
+ {deleteAble &&
80
+ <Button onClick={this.onClickDelete} label='Verwijderen' primary={false} textColor='red'/>}
81
+ </div>
82
+ )}
83
+ </div>
84
+ );
85
+ }
86
+ };
@@ -0,0 +1,56 @@
1
+ /*!
2
+ * Copyright (c) 2021. Dave van Rijn Development
3
+ */
4
+
5
+ @import '../../../../style/variables';
6
+
7
+ .pdf-element-settings {
8
+ background-color: white;
9
+ padding: 1rem;
10
+ border: 1px solid $color-gray-7;
11
+ border-radius: .5rem;
12
+ max-width: 30rem;
13
+
14
+ .settings-title {
15
+ margin-bottom: .5rem;
16
+ }
17
+
18
+ .empty-label {
19
+ font-size: .9rem;
20
+ }
21
+
22
+ .divider {
23
+ width: 100%;
24
+ height: 1px;
25
+ background-color: $color-gray-4;
26
+ margin: .5rem 0;
27
+ }
28
+
29
+ .buttons-container {
30
+ display: flex;
31
+ justify-content: space-between;
32
+ margin-top: .5rem;
33
+ }
34
+
35
+ .settings-color-picker {
36
+ display: flex;
37
+ align-items: center;
38
+ position: relative;
39
+
40
+ .picker-label {
41
+ margin-right: .5rem;
42
+ }
43
+
44
+ .color-preview {
45
+ width: 2rem;
46
+ height: 1rem;
47
+ cursor: pointer;
48
+ box-shadow: -2px -2px 5px rgba(0,0,0,.25) inset, 2px 2px 5px white inset;
49
+ border-radius: 10px;
50
+ }
51
+
52
+ .text-color-picker {
53
+ position: absolute;
54
+ }
55
+ }
56
+ }
@@ -0,0 +1,202 @@
1
+ /*
2
+ * Copyright (c) 2021. Dave van Rijn Development
3
+ */
4
+ import './style/pdfTextSettings.scss';
5
+
6
+ import React, {PureComponent} from 'react';
7
+ import PdfText from "../../text/pdfText";
8
+ import {
9
+ ElementPosition,
10
+ IndexedObject,
11
+ PDFDisplay,
12
+ PdfFont,
13
+ PDFTextParams,
14
+ PDFTextVariables,
15
+ SelectItemShape
16
+ } from "../../../util/interfaces";
17
+ import {ColorPicker, DvrdSelect, fontItems, getPdfVariables, NumberField, Select} from "../../../../../index";
18
+ import classNames from 'classnames';
19
+ import IconButton, {IconButtonType} from "../buttons/iconButton";
20
+
21
+ interface Props {
22
+ element: PdfText;
23
+ customVariables?: PDFTextVariables;
24
+ supportMultiPage: boolean;
25
+ }
26
+
27
+ interface State extends IndexedObject<any> {
28
+ openVariables: keyof PDFTextVariables;
29
+ bold: boolean;
30
+ underline: boolean;
31
+ italic: boolean;
32
+ alignment?: ElementPosition;
33
+ font: PdfFont;
34
+ color: string;
35
+ colorPickerActive: boolean;
36
+ display: PDFDisplay;
37
+ }
38
+
39
+ const displayItems: SelectItemShape[] = [
40
+ {value: PDFDisplay.ALL_PAGES, label: 'Alle pagina\'s'},
41
+ {value: PDFDisplay.FIRST_PAGE, label: 'Alleen eerste pagina'},
42
+ {value: PDFDisplay.LAST_PAGE, label: 'Alleen laatste pagina'},
43
+ ]
44
+
45
+ export default class PdfTextSettings extends PureComponent<Props, State> {
46
+ constructor(props: Props) {
47
+ super(props);
48
+ const settings = props.element.getSettings();
49
+ this.state = {
50
+ openVariables: 'company',
51
+ bold: settings.bold,
52
+ underline: settings.underline,
53
+ italic: settings.italic,
54
+ alignment: settings.alignment,
55
+ font: settings.font,
56
+ color: settings.color,
57
+ colorPickerActive: false,
58
+ display: settings.display ?? PDFDisplay.ALL_PAGES,
59
+ };
60
+ }
61
+
62
+ onChangeDisplay = (value: PDFDisplay) => {
63
+ const {element} = this.props;
64
+ element.setSetting('display', value, () => {
65
+ this.setState({display: value});
66
+ })
67
+ }
68
+
69
+ onCloseColorPicker = () => {
70
+ this.setState({colorPickerActive: false});
71
+ };
72
+
73
+ onOpenColorPicker = () => {
74
+ this.setState({colorPickerActive: true});
75
+ };
76
+
77
+ onPickColor = (close: boolean = true) => (color: string) => {
78
+ const {element} = this.props;
79
+ if (close)
80
+ this.setState({colorPickerActive: false, color}, () => {
81
+ element.setSetting('color', color)
82
+ });
83
+ else this.setState({color}, () => {
84
+ element.setSetting('color', color, undefined, false);
85
+ });
86
+ };
87
+
88
+ onClickVariablesTitle = (type: keyof PDFTextVariables) => () => {
89
+ this.setState({openVariables: type});
90
+ };
91
+
92
+ onClickTextVariable = (variable: string) => () => {
93
+ const {element} = this.props;
94
+ if (element instanceof PdfText) element.insertText(`{${variable}}`);
95
+ };
96
+
97
+ onToggleSetting = (type: IconButtonType) => () => {
98
+ const {element} = this.props, {bold, underline, italic} = this.state;
99
+ let value: boolean;
100
+ if (type === IconButtonType.BOLD) value = !bold;
101
+ else if (type === IconButtonType.UNDERLINE) value = !underline;
102
+ else value = !italic;
103
+ element.setSetting(type, value, () => {
104
+ this.setState({[type]: value});
105
+ });
106
+ };
107
+
108
+ onToggleAlignment = (type: IconButtonType) => () => {
109
+ const {alignment} = this.state, {element} = this.props;
110
+ let nextAlignment: ElementPosition | undefined;
111
+ if (type === IconButtonType.LEFT)
112
+ nextAlignment = alignment === ElementPosition.LEFT ? undefined : ElementPosition.LEFT;
113
+ else if (type === IconButtonType.CENTER)
114
+ nextAlignment = alignment === ElementPosition.CENTER ? undefined : ElementPosition.CENTER;
115
+ else if (type === IconButtonType.RIGHT)
116
+ nextAlignment = alignment === ElementPosition.RIGHT ? undefined : ElementPosition.RIGHT;
117
+ element.setSetting('alignment', nextAlignment, () => {
118
+ this.setState({alignment: nextAlignment});
119
+ });
120
+ }
121
+
122
+ renderTextVariables = () => {
123
+ const {customVariables} = this.props, variables: PDFTextVariables = getPdfVariables(customVariables),
124
+ {client, company, invoice} = variables;
125
+ return (
126
+ <div className='text-variables-container'>
127
+ <h3 className='variables-container-title'>Tekstvariabelen</h3>
128
+ <div className='variable-containers'>
129
+ {this.renderVariables('company', 'Bedrijf', company)}
130
+ {this.renderVariables('client', 'Klant', client)}
131
+ {this.renderVariables('invoice', 'Factuur', invoice)}
132
+ </div>
133
+ </div>
134
+ )
135
+ };
136
+
137
+ renderVariables = (type: keyof PDFTextVariables, title: string, variables: IndexedObject<string>) => (
138
+ <div className={classNames('variables-container', this.state.openVariables === type && 'open')}>
139
+ <label className='variables-title' onClick={this.onClickVariablesTitle(type)}>{title}</label>
140
+ <div className='variables-main-container'>
141
+ <div className='variables'>
142
+ {Object.keys(variables).map((key: string, index: number) => (
143
+ <label key={index} className='text-variable'
144
+ onClick={this.onClickTextVariable(key)}>{variables[key]}</label>
145
+ ))}
146
+ </div>
147
+ </div>
148
+ </div>
149
+ );
150
+
151
+ render = () => {
152
+ const {element, supportMultiPage} = this.props,
153
+ {bold, underline, italic, alignment, colorPickerActive, color, display} = this.state,
154
+ settings: PDFTextParams = element.getSettings();
155
+ return (
156
+ <div className='pdf-text-settings'>
157
+ {supportMultiPage && <>
158
+ <label className='settings-title'>Weergave</label>
159
+ <DvrdSelect onChange={this.onChangeDisplay} value={display} items={displayItems}/>
160
+ </>}
161
+ <div className='divider'/>
162
+ <div className='text-settings'>
163
+ <IconButton onClick={this.onToggleSetting} active={bold} type={IconButtonType.BOLD}
164
+ title='Vet'/>
165
+ <IconButton onClick={this.onToggleSetting} active={underline} type={IconButtonType.UNDERLINE}
166
+ title='Onderstrepen'/>
167
+ <IconButton onClick={this.onToggleSetting} active={italic} type={IconButtonType.ITALIC}
168
+ title='Cursief'/>
169
+ <IconButton onClick={this.onToggleAlignment} active={alignment === ElementPosition.LEFT}
170
+ type={IconButtonType.LEFT} title='Links'/>
171
+ <IconButton onClick={this.onToggleAlignment} active={alignment === ElementPosition.CENTER}
172
+ type={IconButtonType.CENTER} title='Centreren'/>
173
+ <IconButton onClick={this.onToggleAlignment} active={alignment === ElementPosition.RIGHT}
174
+ type={IconButtonType.RIGHT} title='Rechts'/>
175
+ </div>
176
+ <div className='divider'/>
177
+ <div className='font-settings'>
178
+ <Select items={fontItems} value={settings.font} onSelect={element.changeSetting('font')}
179
+ label='Lettertype' selectOnly unControlled itemsHeight='15rem' fullWidth/>
180
+ <NumberField value={settings.fontSize.toString()} onChange={element.changeSetting('fontSize')}
181
+ label='Tekstgrootte' className='font-size'
182
+ ornaments={{
183
+ element: <span style={{cursor: 'text'}}>px</span>,
184
+ placement: ElementPosition.RIGHT,
185
+ allowPropagation: true
186
+ }} wholeNumbers
187
+ asNumber unControlled/>
188
+ <div className='settings-color-picker'>
189
+ <label className='picker-label'>Tekstkleur:</label>
190
+ <div className='color-preview' style={{backgroundColor: color}}
191
+ onClick={this.onOpenColorPicker}/>
192
+ <ColorPicker onClose={this.onCloseColorPicker} onSubmit={this.onPickColor()} closeable={false}
193
+ onPreChange={this.onPickColor(false)} color={settings.color}
194
+ visible={colorPickerActive} className='text-color-picker' transparent/>
195
+ </div>
196
+ </div>
197
+ <div className='divider'/>
198
+ {!settings.disabled && this.renderTextVariables()}
199
+ </div>
200
+ )
201
+ };
202
+ }
@@ -0,0 +1,94 @@
1
+ /*!
2
+ * Copyright (c) 2021. Dave van Rijn Development
3
+ */
4
+
5
+ @import '../../../../../style/variables';
6
+
7
+ .pdf-text-settings {
8
+ display: grid;
9
+ grid-template-columns: auto;
10
+ grid-row-gap: .5rem;
11
+ justify-items: start;
12
+ align-items: start;
13
+
14
+ .text-settings {
15
+ display: flex;
16
+ align-items: flex-end;
17
+ }
18
+
19
+ .font-settings {
20
+ display: grid;
21
+ grid-template-columns: auto;
22
+ grid-row-gap: .5rem;
23
+ width: 100%;
24
+
25
+ .font-size {
26
+ width: 6rem;
27
+ }
28
+ }
29
+
30
+ .text-variables-container {
31
+ .variables-container-title {
32
+ margin-bottom: .5rem;
33
+ }
34
+
35
+ .variable-containers {
36
+ display: grid;
37
+ grid-template-columns: auto;
38
+ grid-row-gap: .5rem;
39
+ align-items: start;
40
+
41
+ .variables-container {
42
+ display: flex;
43
+ flex-direction: column;
44
+
45
+ .variables-title {
46
+ border-bottom: 2px solid $color-gray-4;
47
+ cursor: pointer;
48
+ padding: .5rem .25rem;
49
+ font-weight: 500;
50
+ font-size: .9rem;
51
+ }
52
+
53
+ .variables-main-container {
54
+ height: 0;
55
+ overflow: hidden;
56
+
57
+ .variables {
58
+ padding: .5rem;
59
+ display: flex;
60
+ flex-wrap: wrap;
61
+ align-items: flex-start;
62
+
63
+ .text-variable {
64
+ @include backgroundShadow;
65
+ padding: .2rem .4rem;
66
+ border-radius: .5rem;
67
+ cursor: pointer;
68
+ margin-right: .5rem;
69
+ margin-bottom: .5rem;
70
+ white-space: nowrap;
71
+ user-select: none;
72
+ transition: background-color .2s ease-in-out;
73
+
74
+ &:last-child {
75
+ margin-right: 0;
76
+ }
77
+
78
+ &:hover {
79
+ background-color: $color-gray-7;
80
+ }
81
+ }
82
+ }
83
+ }
84
+
85
+ &.open {
86
+ .variables-main-container {
87
+ height: fit-content;
88
+ overflow: auto;
89
+ }
90
+ }
91
+ }
92
+ }
93
+ }
94
+ }