@flozy/editor 2.1.9 → 3.1.1

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 (29) hide show
  1. package/dist/Editor/CommonEditor.js +14 -5
  2. package/dist/Editor/Editor.css +4 -0
  3. package/dist/Editor/Elements/Button/ButtonNavSettings/NavComponents.js +219 -0
  4. package/dist/Editor/Elements/Button/ButtonNavSettings/index.js +138 -0
  5. package/dist/Editor/Elements/Button/ButtonNavSettings/navOptions.js +32 -0
  6. package/dist/Editor/Elements/Button/ButtonNavSettings/style.js +55 -0
  7. package/dist/Editor/Elements/Button/EditorButton.js +114 -30
  8. package/dist/Editor/Elements/Color Picker/defaultColors.js +4 -1
  9. package/dist/Editor/Elements/Embed/EmbedPopup.js +1 -1
  10. package/dist/Editor/Elements/Form/Form.js +6 -2
  11. package/dist/Editor/Toolbar/Mini/MiniToolbar.js +4 -1
  12. package/dist/Editor/Toolbar/Mini/Options/Options.js +1 -1
  13. package/dist/Editor/Toolbar/PopupTool/PopupToolStyle.js +2 -0
  14. package/dist/Editor/Toolbar/toolbarGroups.js +8 -6
  15. package/dist/Editor/common/ColorPickerButton.js +7 -3
  16. package/dist/Editor/common/Section/index.js +2 -1
  17. package/dist/Editor/common/StyleBuilder/buttonStyle.js +13 -9
  18. package/dist/Editor/common/StyleBuilder/fieldTypes/color.js +25 -2
  19. package/dist/Editor/common/ToolbarIcon.js +2 -2
  20. package/dist/Editor/common/iconslist.js +21 -17
  21. package/dist/Editor/commonStyle.js +16 -1
  22. package/dist/Editor/plugins/withHTML.js +25 -4
  23. package/dist/Editor/plugins/withTable.js +26 -1
  24. package/dist/Editor/service/formSubmit.js +1 -1
  25. package/dist/Editor/utils/embed.js +1 -1
  26. package/dist/Editor/utils/grid.js +2 -4
  27. package/dist/Editor/utils/helper.js +53 -0
  28. package/dist/Editor/utils/table.js +4 -8
  29. package/package.json +1 -1
@@ -374,6 +374,18 @@ const CommonEditor = /*#__PURE__*/forwardRef((props, ref) => {
374
374
  const handleFooterClick = () => {
375
375
  window.open('https://www.flozy.com', '_blank');
376
376
  };
377
+ const editorWrapperStyle = useMemo(() => {
378
+ const style = {
379
+ color: pageTextColor || ""
380
+ };
381
+ if (pageBgImage && pageBgImage !== "none") {
382
+ style.backgroundImage = `url(${pageBgImage})`;
383
+ style.backgroundSize = `cover`;
384
+ } else {
385
+ style.background = pageColor || "";
386
+ }
387
+ return style;
388
+ }, [pageBgImage, pageColor]);
377
389
  return /*#__PURE__*/_jsx(EditorProvider, {
378
390
  theme: theme,
379
391
  editor: editor,
@@ -396,13 +408,10 @@ const CommonEditor = /*#__PURE__*/forwardRef((props, ref) => {
396
408
  children: [/*#__PURE__*/_jsx(DragAndDrop, {
397
409
  children: /*#__PURE__*/_jsx(Overlay, {
398
410
  children: /*#__PURE__*/_jsx(Box, {
399
- className: `${hasTopBanner() ? "has-topbanner" : ""} ${!pageColor ? "no-color" : ""} ${isScrolling ? "" : "hideScroll"} scrollable-content`,
411
+ className: `${hasTopBanner() ? "has-topbanner" : ""} ${!pageColor ? "no-color" : ""} ${isScrolling ? "" : "hideScroll"} scrollable-content scrollSmooth`,
400
412
  sx: classes.slateWrapper,
401
413
  id: "slate-wrapper-scroll-container",
402
- style: {
403
- background: pageColor || "",
404
- color: pageTextColor || ""
405
- },
414
+ style: editorWrapperStyle,
406
415
  onClick: e => {
407
416
  handleInsertLastElement(e, editor);
408
417
  },
@@ -1109,3 +1109,7 @@ blockquote {
1109
1109
  .doublequote::after {
1110
1110
  content: '\201D';
1111
1111
  }
1112
+
1113
+ .scrollSmooth {
1114
+ scroll-behavior: smooth;
1115
+ }
@@ -0,0 +1,219 @@
1
+ import { Autocomplete, Checkbox, FormControlLabel, MenuItem, Select, TextField, Typography, createFilterOptions } from "@mui/material";
2
+ import { useEffect, useMemo, useState } from "react";
3
+ import { jsx as _jsx } from "react/jsx-runtime";
4
+ import { Fragment as _Fragment } from "react/jsx-runtime";
5
+ import { jsxs as _jsxs } from "react/jsx-runtime";
6
+ const OpenInNewTab = props => {
7
+ const {
8
+ nav,
9
+ openInNewTab,
10
+ onNewTabChange
11
+ } = props;
12
+ return nav?.showOpenInNewTab ? /*#__PURE__*/_jsx(FormControlLabel, {
13
+ className: "ccheckbox-primary",
14
+ control: /*#__PURE__*/_jsx(Checkbox, {
15
+ checked: openInNewTab,
16
+ onChange: onNewTabChange
17
+ }),
18
+ label: /*#__PURE__*/_jsx(Typography, {
19
+ variant: "body2",
20
+ children: "Open in new tab"
21
+ })
22
+ }) : null;
23
+ };
24
+ export const TextInput = props => {
25
+ return /*#__PURE__*/_jsxs(_Fragment, {
26
+ children: [/*#__PURE__*/_jsx(TextField, {
27
+ fullWidth: true,
28
+ size: "small",
29
+ ...props,
30
+ onChange: e => {
31
+ props.onChange(e.target.value);
32
+ }
33
+ }), /*#__PURE__*/_jsx(OpenInNewTab, {
34
+ ...props
35
+ })]
36
+ });
37
+ };
38
+ export const SelectPage = props => {
39
+ const {
40
+ value,
41
+ onChange,
42
+ services
43
+ } = props;
44
+ const [pages, setPages] = useState([]);
45
+ const getPages = async () => {
46
+ const result = await services("getPages", {});
47
+ const refactor = result?.data?.map(r => {
48
+ const {
49
+ title,
50
+ url_name,
51
+ ...rest
52
+ } = r;
53
+ return {
54
+ label: title,
55
+ value: url_name,
56
+ ...rest
57
+ };
58
+ });
59
+ setPages(refactor);
60
+ };
61
+ useEffect(() => {
62
+ getPages();
63
+ }, []);
64
+ const [page, section] = useMemo(() => {
65
+ if (value) {
66
+ const [page, section] = value.split("#");
67
+ const selectedPage = pages.find(p => p.value === page) || {
68
+ label: page,
69
+ value: page
70
+ };
71
+ const selectedSection = pages.find(p => p.value === section) || {
72
+ label: section,
73
+ value: section
74
+ };
75
+ return [selectedPage, selectedSection];
76
+ }
77
+ return [];
78
+ }, [value, pages]);
79
+ return /*#__PURE__*/_jsxs("div", {
80
+ children: [/*#__PURE__*/_jsx(FreeSoloCreateOption, {
81
+ label: page?.label,
82
+ setValue: val => onChange(val?.value),
83
+ placeholder: "Select Page",
84
+ options: pages
85
+ }), /*#__PURE__*/_jsx(FreeSoloCreateOption, {
86
+ label: section?.label,
87
+ setValue: val => {
88
+ let url = page?.value;
89
+ if (val?.value) {
90
+ url += `#${val?.value}`;
91
+ }
92
+ onChange(url);
93
+ },
94
+ placeholder: "Select Section or anchor",
95
+ options: page?.sections?.map(p => ({
96
+ label: p,
97
+ value: p
98
+ }))
99
+ }), /*#__PURE__*/_jsx(OpenInNewTab, {
100
+ ...props
101
+ })]
102
+ });
103
+ };
104
+ export const Trigger = props => {
105
+ return /*#__PURE__*/_jsx(Typography, {
106
+ variant: "h6",
107
+ gutterBottom: true,
108
+ children: "Choosing this will trigger the next step"
109
+ });
110
+ };
111
+ const scrollToOptions = [{
112
+ label: "Top",
113
+ value: "top"
114
+ }, {
115
+ label: "Bottom",
116
+ value: "bottom"
117
+ }];
118
+ export const ScrollTopBottom = props => {
119
+ const {
120
+ value,
121
+ onChange
122
+ } = props;
123
+ return /*#__PURE__*/_jsxs(_Fragment, {
124
+ children: [/*#__PURE__*/_jsx(Typography, {
125
+ variant: "body2",
126
+ sx: {
127
+ paddingBottom: "4px"
128
+ },
129
+ children: "Choose Top/Bottom of page"
130
+ }), /*#__PURE__*/_jsx(Select, {
131
+ size: "small",
132
+ fullWidth: true,
133
+ value: value,
134
+ onChange: e => onChange(e.target.value),
135
+ children: scrollToOptions.map((option, i) => {
136
+ return /*#__PURE__*/_jsx(MenuItem, {
137
+ value: option.value,
138
+ children: /*#__PURE__*/_jsx(Typography, {
139
+ variant: "body2",
140
+ children: option.label
141
+ })
142
+ }, i);
143
+ })
144
+ })]
145
+ });
146
+ };
147
+ const filter = createFilterOptions();
148
+ export function FreeSoloCreateOption({
149
+ label,
150
+ setValue,
151
+ options = [],
152
+ placeholder = ""
153
+ }) {
154
+ return /*#__PURE__*/_jsx(Autocomplete, {
155
+ freeSolo: true,
156
+ options: options,
157
+ value: label || "",
158
+ renderInput: params => /*#__PURE__*/_jsx(TextField, {
159
+ ...params,
160
+ label: placeholder
161
+ }),
162
+ renderOption: (props, option) => /*#__PURE__*/_jsx("li", {
163
+ ...props,
164
+ children: option.label
165
+ }),
166
+ onChange: (event, newValue) => {
167
+ if (typeof newValue === 'string') {
168
+ setValue({
169
+ value: newValue
170
+ });
171
+ } else if (newValue && newValue.inputValue) {
172
+ const {
173
+ inputValue
174
+ } = newValue;
175
+
176
+ // Create a new value from the user input
177
+ setValue({
178
+ label: inputValue,
179
+ value: inputValue
180
+ });
181
+ } else {
182
+ setValue(newValue);
183
+ }
184
+ },
185
+ filterOptions: (options, params) => {
186
+ const filtered = filter(options, params);
187
+ const {
188
+ inputValue
189
+ } = params;
190
+ // Suggest the creation of a new value
191
+ const isExisting = options.some(option => inputValue === option.label);
192
+ if (inputValue !== '' && !isExisting) {
193
+ filtered.push({
194
+ inputValue,
195
+ label: `Add "${inputValue}"`
196
+ });
197
+ }
198
+ return filtered;
199
+ },
200
+ selectOnFocus: true,
201
+ clearOnBlur: true,
202
+ handleHomeEndKeys: true,
203
+ getOptionLabel: option => {
204
+ // Value selected with enter, right from the input
205
+ if (typeof option === 'string') {
206
+ return option;
207
+ }
208
+ // Add "xxx" option created dynamically
209
+ if (option.inputValue) {
210
+ return option.inputValue;
211
+ }
212
+ // Regular option
213
+ return option.value;
214
+ },
215
+ sx: {
216
+ marginTop: "10px"
217
+ }
218
+ });
219
+ }
@@ -0,0 +1,138 @@
1
+ import Button from '@mui/material/Button';
2
+ import Dialog from '@mui/material/Dialog';
3
+ import DialogTitle from '@mui/material/DialogTitle';
4
+ import DialogContent from '@mui/material/DialogContent';
5
+ import DialogActions from '@mui/material/DialogActions';
6
+ import IconButton from '@mui/material/IconButton';
7
+ import CloseIcon from '@mui/icons-material/Close';
8
+ import { FormControl, FormControlLabel, Grid, Radio, RadioGroup } from '@mui/material';
9
+ import { useState } from 'react';
10
+ import ButtonNavSettingsStyles from './style';
11
+ import { getNavOptions } from './navOptions';
12
+ import { ScrollTopBottom, SelectPage, TextInput, Trigger } from './NavComponents';
13
+ import { jsx as _jsx } from "react/jsx-runtime";
14
+ import { jsxs as _jsxs } from "react/jsx-runtime";
15
+ const MAP_COMPONENT = {
16
+ webAddress: TextInput,
17
+ email: TextInput,
18
+ phone: TextInput,
19
+ actionTrigger: Trigger,
20
+ scrollTopOrBottom: ScrollTopBottom,
21
+ page: SelectPage
22
+ };
23
+ export default function ButtonNavSettings(props) {
24
+ const {
25
+ open,
26
+ handleClose,
27
+ onSave,
28
+ customProps,
29
+ element,
30
+ editor
31
+ } = props;
32
+ const navOptions = getNavOptions(customProps.hideTools);
33
+ const prevNavType = element?.buttonLink?.linkType;
34
+ const classes = ButtonNavSettingsStyles();
35
+ const [nav, setNav] = useState(prevNavType ? navOptions.find(n => n.value === prevNavType) : {
36
+ label: "None",
37
+ value: ""
38
+ });
39
+ const [navValue, setNavValue] = useState(element?.url || "");
40
+ const [openInNewTab, setOpenInNewTab] = useState(element.openInNewTab || false);
41
+ const {
42
+ metadata
43
+ } = customProps || {
44
+ metadata: {}
45
+ };
46
+ const {
47
+ buttonLink
48
+ } = metadata || {
49
+ actionTrigger: {}
50
+ };
51
+ const {
52
+ actionTrigger
53
+ } = buttonLink || {};
54
+ const {
55
+ onClick
56
+ } = actionTrigger || {
57
+ options: []
58
+ };
59
+ const NavSettings = MAP_COMPONENT[nav?.value];
60
+ const onChange = value => {
61
+ setNavValue(value);
62
+ };
63
+ return /*#__PURE__*/_jsxs(Dialog, {
64
+ onClose: handleClose,
65
+ open: open,
66
+ sx: classes.dialogContainer,
67
+ fullWidth: true,
68
+ maxWidth: "sm",
69
+ children: [/*#__PURE__*/_jsx(DialogTitle, {
70
+ children: "What do you want to link to?"
71
+ }), /*#__PURE__*/_jsx(IconButton, {
72
+ "aria-label": "close",
73
+ onClick: handleClose,
74
+ sx: classes.closeIcon,
75
+ children: /*#__PURE__*/_jsx(CloseIcon, {})
76
+ }), /*#__PURE__*/_jsx(DialogContent, {
77
+ dividers: true,
78
+ children: /*#__PURE__*/_jsxs(Grid, {
79
+ container: true,
80
+ spacing: 2,
81
+ children: [/*#__PURE__*/_jsx(Grid, {
82
+ item: true,
83
+ xs: 6,
84
+ sx: classes.gridDivider,
85
+ children: /*#__PURE__*/_jsx(FormControl, {
86
+ children: /*#__PURE__*/_jsx(RadioGroup, {
87
+ value: nav?.value,
88
+ children: navOptions?.map((navOption, i) => {
89
+ return /*#__PURE__*/_jsx(FormControlLabel, {
90
+ value: navOption.value,
91
+ control: /*#__PURE__*/_jsx(Radio, {}),
92
+ label: navOption.label,
93
+ onChange: () => {
94
+ setNav(navOption);
95
+ setNavValue("");
96
+ }
97
+ }, i);
98
+ })
99
+ })
100
+ })
101
+ }), /*#__PURE__*/_jsx(Grid, {
102
+ item: true,
103
+ xs: 6,
104
+ children: NavSettings && /*#__PURE__*/_jsx(NavSettings, {
105
+ placeholder: nav?.placeholder,
106
+ nav: nav,
107
+ onChange: onChange,
108
+ value: navValue,
109
+ editor: editor,
110
+ openInNewTab: openInNewTab,
111
+ onNewTabChange: () => setOpenInNewTab(prev => !prev),
112
+ services: customProps.services
113
+ })
114
+ })]
115
+ })
116
+ }), /*#__PURE__*/_jsxs(DialogActions, {
117
+ children: [/*#__PURE__*/_jsx(Button, {
118
+ onClick: handleClose,
119
+ sx: classes.closeBtn,
120
+ children: "Cancel"
121
+ }), /*#__PURE__*/_jsx(Button, {
122
+ onClick: () => {
123
+ onSave({
124
+ buttonLink: {
125
+ linkType: nav?.value,
126
+ onClick
127
+ },
128
+ url: navValue,
129
+ openInNewTab
130
+ });
131
+ handleClose();
132
+ },
133
+ sx: classes.saveBtn,
134
+ children: "Save"
135
+ })]
136
+ })]
137
+ });
138
+ }
@@ -0,0 +1,32 @@
1
+ export const getNavOptions = (hideTools = []) => {
2
+ let navOptions = [{
3
+ label: "None",
4
+ value: ""
5
+ }, {
6
+ label: "Trigger",
7
+ value: "actionTrigger"
8
+ }, {
9
+ label: "Web Address",
10
+ value: "webAddress",
11
+ placeholder: "https://",
12
+ showOpenInNewTab: true
13
+ }, {
14
+ label: "Select Page and Section",
15
+ value: "page",
16
+ placeholder: "Select Page and Section",
17
+ showOpenInNewTab: true
18
+ }, {
19
+ label: "Top/Bottom of page",
20
+ value: "scrollTopOrBottom"
21
+ }, {
22
+ label: "Email",
23
+ value: "email",
24
+ placeholder: "email"
25
+ }, {
26
+ label: "Phone number",
27
+ value: "phone",
28
+ placeholder: "phone"
29
+ }];
30
+ navOptions = navOptions.filter(n => !hideTools.includes(n.value));
31
+ return navOptions;
32
+ };
@@ -0,0 +1,55 @@
1
+ const ButtonNavSettingsStyles = () => ({
2
+ dialogContainer: {
3
+ '& .MuiDialogContent-root': {
4
+ padding: "0px 20px"
5
+ },
6
+ '& .MuiDialogActions-root': {
7
+ padding: "10px"
8
+ },
9
+ '& .MuiTypography-h6': {
10
+ fontWeight: 600,
11
+ fontSize: "16px",
12
+ paddingRight: "20px"
13
+ },
14
+ "& .MuiGrid-container": {
15
+ marginTop: '0px'
16
+ },
17
+ "& .MuiGrid-item": {
18
+ padding: "14px"
19
+ }
20
+ },
21
+ saveBtn: {
22
+ color: '#fff',
23
+ background: "#2563EB",
24
+ fontSize: "14px",
25
+ fontWeight: 500,
26
+ padding: "4px 24px",
27
+ textTransform: "none",
28
+ "&:hover": {
29
+ color: '#fff',
30
+ background: "#2563EB"
31
+ }
32
+ },
33
+ closeBtn: {
34
+ backgroundColor: "#F4F6F9",
35
+ color: "#64748B",
36
+ fontSize: "14px",
37
+ fontWeight: 500,
38
+ padding: "4px 22px",
39
+ textTransform: "none",
40
+ border: "1px solid #D8DDE1",
41
+ "&:hover": {
42
+ border: "1px solid #64748B"
43
+ }
44
+ },
45
+ closeIcon: {
46
+ position: 'absolute',
47
+ right: 8,
48
+ top: 8,
49
+ color: theme => theme.palette.grey[500]
50
+ },
51
+ gridDivider: {
52
+ borderRight: "1px solid rgba(0, 0, 0, 0.12)"
53
+ }
54
+ });
55
+ export default ButtonNavSettingsStyles;