@openlettermarketing/olc-react-sdk 0.0.8 → 0.0.10

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 (135) hide show
  1. package/.eslintignore +1 -0
  2. package/.eslintrc.cjs +18 -0
  3. package/.eslintrc.yml +47 -0
  4. package/.prettierignore +3 -0
  5. package/.prettierrc.yml +5 -0
  6. package/CHANGELOG.md +4 -0
  7. package/babel.config.json +10 -0
  8. package/build/index.js +2 -2
  9. package/build/index.js.map +1 -1
  10. package/examples/.eslintrc.yml +4 -0
  11. package/index.html +18 -0
  12. package/package.json +6 -6
  13. package/public/vite.svg +1 -0
  14. package/src/App.tsx +76 -0
  15. package/src/assets/Fonts/Lexi-Regular.ttf +0 -0
  16. package/src/assets/images/input/cancel.tsx +20 -0
  17. package/src/assets/images/input/search.tsx +20 -0
  18. package/src/assets/images/modal-icons/cancelIcon.png +0 -0
  19. package/src/assets/images/modal-icons/del.tsx +19 -0
  20. package/src/assets/images/modal-icons/delete.svg +3 -0
  21. package/src/assets/images/modal-icons/modal-cross.tsx +23 -0
  22. package/src/assets/images/modal-icons/save.tsx +23 -0
  23. package/src/assets/images/templates/add-icon.svg +5 -0
  24. package/src/assets/images/templates/back-arrow.tsx +19 -0
  25. package/src/assets/images/templates/back-dialog-icon.png +0 -0
  26. package/src/assets/images/templates/back-dialog-icon.svg +3 -0
  27. package/src/assets/images/templates/barcode.png +0 -0
  28. package/src/assets/images/templates/bi-fold-self-mailers.tsx +28 -0
  29. package/src/assets/images/templates/black-trash-icon.svg +3 -0
  30. package/src/assets/images/templates/cancel.svg +4 -0
  31. package/src/assets/images/templates/cancelIcon.png +0 -0
  32. package/src/assets/images/templates/clipboard.svg +3 -0
  33. package/src/assets/images/templates/contact-search.svg +3 -0
  34. package/src/assets/images/templates/content-copy-icon.tsx +24 -0
  35. package/src/assets/images/templates/cross.svg +3 -0
  36. package/src/assets/images/templates/custom-template-icon-black.svg +3 -0
  37. package/src/assets/images/templates/custom-template-icon.svg +3 -0
  38. package/src/assets/images/templates/custom-template.tsx +23 -0
  39. package/src/assets/images/templates/dummy-template.svg +21 -0
  40. package/src/assets/images/templates/dynamic-field.tsx +119 -0
  41. package/src/assets/images/templates/edit-pencil-icon.tsx +21 -0
  42. package/src/assets/images/templates/filter-2.svg +13 -0
  43. package/src/assets/images/templates/info-icon.svg +12 -0
  44. package/src/assets/images/templates/info-icon.tsx +37 -0
  45. package/src/assets/images/templates/one-barcode.png +0 -0
  46. package/src/assets/images/templates/personal-letter.tsx +53 -0
  47. package/src/assets/images/templates/plus-icon.svg +5 -0
  48. package/src/assets/images/templates/postcard.tsx +32 -0
  49. package/src/assets/images/templates/professional-letter.tsx +53 -0
  50. package/src/assets/images/templates/real-penned-letters.tsx +57 -0
  51. package/src/assets/images/templates/search.svg +3 -0
  52. package/src/assets/images/templates/size-image-lg.tsx +20 -0
  53. package/src/assets/images/templates/size-image-mid.tsx +20 -0
  54. package/src/assets/images/templates/size-image.tsx +20 -0
  55. package/src/assets/images/templates/template-copy.svg +3 -0
  56. package/src/assets/images/templates/template-default-design.tsx +21 -0
  57. package/src/assets/images/templates/template-delete.svg +3 -0
  58. package/src/assets/images/templates/template-edit.svg +4 -0
  59. package/src/assets/images/templates/template-save-icon.svg +3 -0
  60. package/src/assets/images/templates/template-search-2.svg +9 -0
  61. package/src/assets/images/templates/template-search.svg +4 -0
  62. package/src/assets/images/templates/thumbnail.svg +10 -0
  63. package/src/assets/images/templates/trash-icon.svg +13 -0
  64. package/src/assets/images/templates/tri-fold-self-mailers.tsx +93 -0
  65. package/src/components/CreateTemplate/index.tsx +377 -0
  66. package/src/components/CreateTemplate/styles.scss +363 -0
  67. package/src/components/GenericUIBlocks/Button/index.tsx +21 -0
  68. package/src/components/GenericUIBlocks/Button/styles.scss +15 -0
  69. package/src/components/GenericUIBlocks/CircularProgress/index.tsx +18 -0
  70. package/src/components/GenericUIBlocks/CircularProgress/styles.scss +98 -0
  71. package/src/components/GenericUIBlocks/Dialog/index.tsx +127 -0
  72. package/src/components/GenericUIBlocks/Dialog/styles.scss +106 -0
  73. package/src/components/GenericUIBlocks/Divider/index.tsx +12 -0
  74. package/src/components/GenericUIBlocks/Divider/styles.scss +7 -0
  75. package/src/components/GenericUIBlocks/GeneralSelect/index.tsx +86 -0
  76. package/src/components/GenericUIBlocks/GeneralSelect/styles.scss +77 -0
  77. package/src/components/GenericUIBlocks/GeneralTooltip/index.tsx +24 -0
  78. package/src/components/GenericUIBlocks/GeneralTooltip/styles.scss +9 -0
  79. package/src/components/GenericUIBlocks/GenericSnackbar/index.tsx +53 -0
  80. package/src/components/GenericUIBlocks/GenericSnackbar/styles.scss +34 -0
  81. package/src/components/GenericUIBlocks/Grid/index.tsx +82 -0
  82. package/src/components/GenericUIBlocks/Input/index.tsx +89 -0
  83. package/src/components/GenericUIBlocks/Input/styles.scss +80 -0
  84. package/src/components/GenericUIBlocks/Snackbar/index.tsx +66 -0
  85. package/src/components/GenericUIBlocks/Typography/index.tsx +18 -0
  86. package/src/components/GenericUIBlocks/Typography/styles.scss +27 -0
  87. package/src/components/SidePanel/customFields/customFieldSection.tsx +162 -0
  88. package/src/components/SidePanel/customFields/styles.scss +47 -0
  89. package/src/components/SidePanel/index.tsx +30 -0
  90. package/src/components/SidePanel/templates/customTemplateSection.tsx +505 -0
  91. package/src/components/SidePanel/templates/styles.scss +151 -0
  92. package/src/components/TemplateBuilder/index.tsx +295 -0
  93. package/src/components/TemplateBuilder/styles.scss +66 -0
  94. package/src/components/TopNavigation/ConfirmNavigateDialog/index.tsx +58 -0
  95. package/src/components/TopNavigation/ConfirmNavigateDialog/styles.scss +123 -0
  96. package/src/components/TopNavigation/EditTemplateNameModel/index.tsx +98 -0
  97. package/src/components/TopNavigation/EditTemplateNameModel/styles.scss +88 -0
  98. package/src/components/TopNavigation/SaveTemplateModel/index.tsx +60 -0
  99. package/src/components/TopNavigation/SaveTemplateModel/styles.scss +128 -0
  100. package/src/components/TopNavigation/index.tsx +388 -0
  101. package/src/components/TopNavigation/styles.scss +83 -0
  102. package/src/importMeta.d.ts +9 -0
  103. package/src/index.scss +130 -0
  104. package/src/index.tsx +82 -0
  105. package/src/libs/test.ts +7 -0
  106. package/src/redux/actions/action-types.ts +42 -0
  107. package/src/redux/actions/customFieldAction.ts +28 -0
  108. package/src/redux/actions/snackbarActions.ts +16 -0
  109. package/src/redux/actions/templateActions.ts +456 -0
  110. package/src/redux/reducers/customFieldReducer.ts +97 -0
  111. package/src/redux/reducers/index.ts +14 -0
  112. package/src/redux/reducers/snackbarReducer.ts +41 -0
  113. package/src/redux/reducers/templateReducer.ts +353 -0
  114. package/src/redux/store.ts +18 -0
  115. package/src/styles/colors.scss +61 -0
  116. package/src/test/mocks.js +89 -0
  117. package/src/test/setupJest.js +1 -0
  118. package/src/utils/api.ts +36 -0
  119. package/src/utils/constants.ts +40 -0
  120. package/src/utils/customStyles.ts +135 -0
  121. package/src/utils/fetchWrapper.ts +68 -0
  122. package/src/utils/fonts.json +1597 -0
  123. package/src/utils/helper.ts +19 -0
  124. package/src/utils/local-storage.ts +15 -0
  125. package/src/utils/message.ts +71 -0
  126. package/src/utils/template-builder.ts +147 -0
  127. package/src/utils/templateRestrictedArea/biFold.ts +433 -0
  128. package/src/utils/templateRestrictedArea/postCard.ts +439 -0
  129. package/src/utils/templateRestrictedArea/professional.ts +422 -0
  130. package/src/utils/templateRestrictedArea/realPenned.ts +283 -0
  131. package/src/utils/templateRestrictedArea/triFold.ts +434 -0
  132. package/tsconfig.json +29 -0
  133. package/tsconfig.node.json +12 -0
  134. package/vite.config.ts +8 -0
  135. package/webpack.config.js +80 -0
@@ -0,0 +1,66 @@
1
+ import React, { useEffect } from 'react';
2
+
3
+ //Hooks
4
+ //@ts-ignore
5
+ import { useSnackbar } from 'react-simple-snackbar';
6
+ import { useDispatch, useSelector } from "react-redux";
7
+ import { AppDispatch, RootState } from '../../../redux/store';
8
+
9
+ // Actions
10
+ import { closeSnackbar } from '../../../redux/actions/snackbarActions';
11
+
12
+ // components
13
+ import Typography from '../Typography';
14
+
15
+ // styles
16
+ import './styles.scss'
17
+
18
+
19
+ const options = {
20
+ position: 'top-right',
21
+ style: {
22
+ backgroundColor: '#EF7820',
23
+ width: '400px',
24
+ color: 'white',
25
+ fontSize: '16px',
26
+ textAlign: 'center',
27
+ },
28
+ closeStyle: {
29
+ color: 'white',
30
+ fontSize: '16px',
31
+ },
32
+ };
33
+
34
+ const Snackbar:React.FC = () => {
35
+ const [openSnackbar] = useSnackbar(options);
36
+
37
+ const open = useSelector((state: RootState) => state.snackbarReducers.snackbar.open);
38
+
39
+ const heading = useSelector(
40
+ (state: RootState) => state.snackbarReducers.snackbar.heading
41
+ );
42
+ const message = useSelector(
43
+ (state: RootState) => state.snackbarReducers.snackbar.message
44
+ );
45
+
46
+ const dispatch: AppDispatch = useDispatch();
47
+
48
+ const Element =
49
+ <div className="snackbar">
50
+ <Typography>{heading || ''}</Typography>
51
+ <Typography>{message || ''}</Typography>
52
+ </div>
53
+
54
+ useEffect(() => {
55
+ if (open) {
56
+ openSnackbar(Element, [5000])
57
+ dispatch(closeSnackbar())
58
+ }
59
+ }, [open]);
60
+
61
+ return (
62
+ Element
63
+ )
64
+ };
65
+
66
+ export default Snackbar;
@@ -0,0 +1,18 @@
1
+ import React, { CSSProperties, ReactNode } from 'react';
2
+
3
+ // styles
4
+ import './styles.scss';
5
+
6
+ interface TypographyProps {
7
+ children?: ReactNode;
8
+ style?: CSSProperties;
9
+ variant?: keyof JSX.IntrinsicElements;
10
+ className?: string;
11
+ }
12
+
13
+ const Typography: React.FC<TypographyProps> = ({ children = '', style = {}, variant = 'p', className = '' }) => {
14
+ const Tag = variant || 'p';
15
+ return <Tag className={className} style={style}>{children}</Tag>;
16
+ };
17
+
18
+ export default Typography;
@@ -0,0 +1,27 @@
1
+ .basic-typo{
2
+ font-weight: 500;
3
+ margin: 0;
4
+ width: 100%;
5
+ margin: 0;
6
+ h1{
7
+ font-size: 50px;
8
+ }
9
+ h2{
10
+ font-size: 45px;
11
+ }
12
+ h3{
13
+ font-size: 40px;
14
+ }
15
+ h4{
16
+ font-size: 35px;
17
+ }
18
+ h5{
19
+ font-size: 30px;
20
+ }
21
+ h6{
22
+ font-size: 25px;
23
+ }
24
+ p{
25
+ font-size: 18px;
26
+ }
27
+ }
@@ -0,0 +1,162 @@
1
+ import React from 'react';
2
+ import { observer } from 'mobx-react-lite';
3
+ import { SectionTab, } from 'polotno/side-panel';
4
+ import { useDispatch, useSelector } from 'react-redux';
5
+ import { useEffect , useState} from 'react';
6
+ import type { StoreType } from 'polotno/model/store';
7
+ import type { TemplatesSection } from 'polotno/side-panel';
8
+ import { AppDispatch, RootState } from '../../../redux/store';
9
+ import { fetchCustomFields } from '../../../redux/actions/customFieldAction';
10
+ import Button from '../../GenericUIBlocks/Button';
11
+ import { copyToClipboard } from '../../../utils/helper';
12
+ import './styles.scss'
13
+ import GeneralTootip from '../../GenericUIBlocks/GeneralTooltip';
14
+ import InfoIcon from '../../../assets/images/templates/info-icon';
15
+ import ContentCopyIcon from '../../..//assets/images/templates/content-copy-icon';
16
+ import DynamicField from '../../../assets/images/templates/dynamic-field';
17
+ import { success } from '../../../redux/actions/snackbarActions';
18
+
19
+ type SideSection = typeof TemplatesSection;
20
+
21
+ const iconButtonStyles= {
22
+ backgroundColor: 'transparent',
23
+ }
24
+
25
+ const customFieldSection: SideSection = {
26
+ name: 'Fields',
27
+ Tab: observer(
28
+ (props: {store: StoreType; active: boolean; onClick: () => void}) => (
29
+ <SectionTab name="Fields" {...props}>
30
+ <DynamicField stroke="var(--sidepanelSVGColor)" />
31
+ </SectionTab>
32
+ )
33
+ ) as SideSection['Tab'],
34
+
35
+ Panel: observer(({store}) => {
36
+ const [isShowDialog, setIsShowDialog] = useState(false);
37
+ const dispatch = useDispatch<AppDispatch>();
38
+ const customFields = useSelector(
39
+ (state: RootState) => state.customFields.customFields
40
+ ) as Record<string, any>;
41
+ const defaultDynamicFields = useSelector(
42
+ (state: RootState) => state.customFields.defaultDynamicFields
43
+ );
44
+ const product = useSelector((state: RootState) => state.templates.product);
45
+ const currentTemplateType = product?.productType;
46
+
47
+ const handleShowDialog = () => {
48
+ setIsShowDialog((prev) => !prev);
49
+ };
50
+
51
+ useEffect(() => {
52
+ dispatch(fetchCustomFields());
53
+ }, [dispatch]);
54
+
55
+ const handleAddElementOnScreen = (event: any, value: any, type: any) => {
56
+ event.preventDefault();
57
+
58
+ if (currentTemplateType === 'Real Penned Letter') {
59
+ copyToClipboard(value);
60
+ dispatch(success(`${value} Copied`));
61
+ return;
62
+ }
63
+
64
+ let x, y;
65
+
66
+ if (type === 'drag') {
67
+ const rect = event.currentTarget.getBoundingClientRect();
68
+ x = event.clientX - rect.left;
69
+ y = event.clientY - rect.top;
70
+ } else {
71
+ // For click events, use nativeEvent.offsetX and nativeEvent.offsetY
72
+ x = store.width / 2 - 200;
73
+ y = 300;
74
+ }
75
+ x /= store.activePage.scale;
76
+ y /= store.activePage.scale;
77
+
78
+ store.activePage.addElement({
79
+ type: 'text',
80
+ x,
81
+ y,
82
+ text: value,
83
+ width: value.length > 15 ? 10 * value.length : 150,
84
+ contentEditable: false,
85
+ });
86
+ };
87
+
88
+ return (
89
+ <div className="dynamic-content">
90
+ <div className="dynamic-content__top">
91
+ <div>
92
+ <span className="title">Contact Fields</span>
93
+ <InfoIcon fill="var(--primaryColor)" className="infoIcon" />
94
+ <GeneralTootip
95
+ anchorSelect=".infoIcon"
96
+ place="bottom"
97
+ title="Merge fields allow you to personalize your mailer with contact information."
98
+ />
99
+ </div>
100
+ </div>
101
+ {defaultDynamicFields.map(
102
+ ({key, value}: {key: string; value: string}, i: number) => (
103
+ <div style={{display: 'flex', alignItems: 'center'}} key={i}>
104
+ <span
105
+ className="contact-element"
106
+ onClick={(event) =>
107
+ handleAddElementOnScreen(event, key, 'click')
108
+ }
109
+ >
110
+ {value}
111
+ </span>
112
+ <Button
113
+ style={iconButtonStyles}
114
+ onClick={() => copyToClipboard(key)}
115
+ >
116
+ <ContentCopyIcon className="copy" />
117
+ </Button>
118
+ </div>
119
+ )
120
+ )}
121
+ <GeneralTootip anchorSelect=".copy" place="bottom" title="Copy" />
122
+ <hr className="divider" />
123
+ <div className="dynamic-content__top">
124
+ <div>
125
+ <span className="title">Custom Fields</span>
126
+ <InfoIcon fill="var(--primaryColor)" className="custom" />
127
+ <GeneralTootip
128
+ anchorSelect=".custom"
129
+ place="bottom"
130
+ title="You can add custom fields to your template."
131
+ />
132
+ </div>
133
+ <Button onClick={handleShowDialog}></Button>
134
+ </div>
135
+ {customFields.data?.map(
136
+ ({key, value}: {key: string; value: string}, i: number) => (
137
+ <div style={{display: 'flex', alignItems: 'center'}} key={i}>
138
+ <span
139
+ className="contact-element"
140
+ onClick={(event) =>
141
+ handleAddElementOnScreen(event, key, 'click')
142
+ }
143
+ >
144
+ {value}
145
+ </span>
146
+ <Button
147
+ style={iconButtonStyles}
148
+ onClick={() => copyToClipboard(key)}
149
+ >
150
+ <ContentCopyIcon
151
+ className="copy"
152
+ />
153
+ </Button>
154
+ </div>
155
+ )
156
+ )}
157
+ </div>
158
+ );
159
+ }) as SideSection['Panel'],
160
+ };
161
+
162
+ export default customFieldSection;
@@ -0,0 +1,47 @@
1
+ .dynamic-icon{
2
+ width:20px;
3
+ height: 20px;
4
+ }
5
+ .dynamic-content{
6
+ & .dynamic-content__top {
7
+ display: flex;
8
+ flex-direction: row;
9
+ justify-content: space-between;
10
+ align-items: center;
11
+ margin: 8px auto;
12
+ & .title{
13
+ font-weight: 600;
14
+ font-size: 16px;
15
+ line-height: 19.36px;
16
+ color: var(--primaryColor);
17
+ margin-right: 5px;
18
+ }
19
+ & .icon{
20
+ width: 12px;
21
+ height: 12px;
22
+ cursor: pointer;
23
+ }
24
+ & .plus-icon{
25
+ // margin-right: 6px;
26
+ }
27
+ }
28
+
29
+ & .divider{
30
+ margin-top: 10px;
31
+ color: #44424145;
32
+ }
33
+
34
+ & .contact-element{
35
+ width: 100%;
36
+ border-radius: 3px;
37
+ border: 0.5px solid var(--customFieldBorderColor);
38
+ text-align: center;
39
+ height: 35px;
40
+ line-height: 35px;
41
+ margin: 5px auto;
42
+ color: var(--customFieldTextColor);
43
+ }
44
+ .copy{
45
+ fill: var(--customFieldCopySVGColor) !important;
46
+ }
47
+ }
@@ -0,0 +1,30 @@
1
+ import React from 'react';
2
+
3
+ // Polotno Imports
4
+ import { SidePanelWrap } from 'polotno';
5
+ import type { StoreType } from 'polotno/model/store';
6
+ import {SidePanel as PolotnoSidePanel, DEFAULT_SECTIONS} from 'polotno/side-panel';
7
+
8
+ // Custom Sections
9
+ import customTemplateSection from './templates/customTemplateSection';
10
+ import customFieldSection from './customFields/customFieldSection';
11
+
12
+
13
+ interface Props {
14
+ store: StoreType;
15
+ }
16
+
17
+ const SidePanel: React.FC<Props> = (props) => {
18
+ const sections = DEFAULT_SECTIONS.filter(
19
+ (section) => !['photos', 'size', 'templates'].includes(section.name)
20
+ );
21
+
22
+ return (
23
+ <SidePanelWrap>
24
+ <PolotnoSidePanel store={props.store} sections={[customTemplateSection, ...sections, customFieldSection]} defaultSection="text" />
25
+ </SidePanelWrap>
26
+ );
27
+ };
28
+
29
+
30
+ export default SidePanel;