@flozy/editor 3.2.8 → 3.2.9

Sign up to get free protection for your applications and to get access to all the features.
@@ -99,6 +99,7 @@ const EditorButton = props => {
99
99
  };
100
100
  const Toolbar = () => {
101
101
  const btnProps = handleLinkType(refURl, linkType, true, true, handleTrigger);
102
+ const hideOpenLink = linkType === "page" || !linkType;
102
103
  return !readOnly ? /*#__PURE__*/_jsxs("div", {
103
104
  className: "element-toolbar hr",
104
105
  style: {
@@ -121,7 +122,7 @@ const EditorButton = props => {
121
122
  onClick: onMenuClick("nav"),
122
123
  children: /*#__PURE__*/_jsx(LinkIcon, {})
123
124
  })
124
- }), linkType === "page" ? null : /*#__PURE__*/_jsx(Tooltip, {
125
+ }), hideOpenLink ? null : /*#__PURE__*/_jsx(Tooltip, {
125
126
  title: "Open Link",
126
127
  arrow: true,
127
128
  children: /*#__PURE__*/_jsx(Box, {
@@ -1,4 +1,6 @@
1
1
  import React, { useEffect, useRef } from "react";
2
+ import sanitizeHtml from "sanitize-html";
3
+ import { allowedDomains } from "../../utils/helper";
2
4
 
3
5
  // const sanitize = (input) => {
4
6
  // const doc = new DOMParser().parseFromString(input, "text/html");
@@ -25,7 +27,14 @@ const Code = props => {
25
27
  } = element;
26
28
  useEffect(() => {
27
29
  if (codeRef?.current) {
28
- const slotHtml = document.createRange().createContextualFragment(embedData); // Create a 'tiny' document and parse the html string
30
+ const clean = sanitizeHtml(embedData, {
31
+ allowedTags: false,
32
+ // Allow all tags
33
+ allowedAttributes: false,
34
+ // Allow all attributes
35
+ allowedScriptDomains: allowedDomains
36
+ });
37
+ const slotHtml = document.createRange().createContextualFragment(clean); // Create a 'tiny' document and parse the html string
29
38
  codeRef.current.innerHTML = ""; // Clear the container
30
39
  codeRef.current.appendChild(slotHtml);
31
40
  }
@@ -165,15 +165,13 @@ export const toolbarGroups = [[{
165
165
  format: "video",
166
166
  type: "embed",
167
167
  group: "elements"
168
- },
169
- // {
170
- // id: 49,
171
- // lbT: "embedScript",
172
- // format: "embedScript",
173
- // type: "embedScript",
174
- // group: "elements",
175
- // },
176
- {
168
+ }, {
169
+ id: 49,
170
+ lbT: "embedScript",
171
+ format: "embedScript",
172
+ type: "embedScript",
173
+ group: "elements"
174
+ }, {
177
175
  id: 45,
178
176
  format: "topbanner",
179
177
  type: "topbanner",
@@ -103,7 +103,7 @@ export const SelectPage = props => {
103
103
  };
104
104
  export const Trigger = props => {
105
105
  return /*#__PURE__*/_jsx(Typography, {
106
- variant: "h6",
106
+ variant: "subtitle1",
107
107
  gutterBottom: true,
108
108
  children: "Choosing this will trigger the next step"
109
109
  });
@@ -1,17 +1,20 @@
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 LinkSettingsStyles from './style';
11
- import { getNavOptions } from './navOptions';
12
- import { ScrollTopBottom, SelectPage, TextInput, Trigger } from './NavComponents';
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 { Box, FormControl, FormControlLabel, Grid, MenuItem, Radio, RadioGroup, Select, Typography } from "@mui/material";
9
+ import { useState } from "react";
10
+ import LinkSettingsStyles from "./style";
11
+ import { getNavOptions } from "./navOptions";
12
+ import { ScrollTopBottom, SelectPage, TextInput, Trigger } from "./NavComponents";
13
+ import SwipeableDrawer from "../SwipeableDrawer";
14
+ import { useEditorContext } from "../../hooks/useMouseMove";
13
15
  import { jsx as _jsx } from "react/jsx-runtime";
14
16
  import { jsxs as _jsxs } from "react/jsx-runtime";
17
+ import { Fragment as _Fragment } from "react/jsx-runtime";
15
18
  const MAP_COMPONENT = {
16
19
  webAddress: TextInput,
17
20
  email: TextInput,
@@ -20,6 +23,12 @@ const MAP_COMPONENT = {
20
23
  scrollTopOrBottom: ScrollTopBottom,
21
24
  page: SelectPage
22
25
  };
26
+ function getNav(navType, navOptions) {
27
+ return navType ? navOptions.find(n => n.value === navType) : {
28
+ label: "None",
29
+ value: ""
30
+ };
31
+ }
23
32
  export default function LinkSettings(props) {
24
33
  const {
25
34
  handleClose,
@@ -27,86 +36,157 @@ export default function LinkSettings(props) {
27
36
  customProps,
28
37
  navType
29
38
  } = props;
39
+ const {
40
+ isMobile
41
+ } = customProps;
30
42
  const navOptions = getNavOptions(customProps.hideTools);
31
43
  const classes = LinkSettingsStyles();
32
- const [nav, setNav] = useState(navType ? navOptions.find(n => n.value === navType) : {
33
- label: "None",
34
- value: ""
35
- });
44
+ const [nav, setNav] = useState(getNav(navType, navOptions));
36
45
  const [navValue, setNavValue] = useState(props?.navValue || "");
37
46
  const [openInNewTab, setOpenInNewTab] = useState(props.openInNewTab || false);
38
47
  const NavSettings = MAP_COMPONENT[nav?.value];
39
48
  const onChange = value => {
40
49
  setNavValue(value);
41
50
  };
42
- return /*#__PURE__*/_jsxs(Dialog, {
43
- onClose: handleClose,
44
- open: true,
45
- sx: classes.dialogContainer,
46
- fullWidth: true,
47
- maxWidth: "sm",
48
- children: [/*#__PURE__*/_jsx(DialogTitle, {
49
- children: "What do you want to link to?"
50
- }), /*#__PURE__*/_jsx(IconButton, {
51
- "aria-label": "close",
52
- onClick: handleClose,
53
- sx: classes.closeIcon,
54
- children: /*#__PURE__*/_jsx(CloseIcon, {})
55
- }), /*#__PURE__*/_jsx(DialogContent, {
56
- dividers: true,
57
- children: /*#__PURE__*/_jsxs(Grid, {
58
- container: true,
59
- spacing: 2,
60
- children: [/*#__PURE__*/_jsx(Grid, {
61
- item: true,
62
- xs: 6,
63
- sx: classes.gridDivider,
64
- children: /*#__PURE__*/_jsx(FormControl, {
65
- children: /*#__PURE__*/_jsx(RadioGroup, {
66
- value: nav?.value,
67
- children: navOptions?.map((navOption, i) => {
68
- return /*#__PURE__*/_jsx(FormControlLabel, {
69
- value: navOption.value,
70
- control: /*#__PURE__*/_jsx(Radio, {}),
71
- label: navOption.label,
72
- onChange: () => {
73
- setNav(navOption);
74
- setNavValue("");
75
- }
76
- }, i);
77
- })
51
+ const onSubmit = () => {
52
+ onSave({
53
+ linkType: nav?.value,
54
+ navValue,
55
+ openInNewTab
56
+ });
57
+ };
58
+ if (isMobile) {
59
+ return /*#__PURE__*/_jsxs(SwipeableDrawer, {
60
+ onClose: handleClose,
61
+ children: [/*#__PURE__*/_jsx(Typography, {
62
+ variant: "subtitle1",
63
+ gutterBottom: true,
64
+ sx: {
65
+ fontWeight: 600
66
+ },
67
+ children: "What do you want to link to?"
68
+ }), /*#__PURE__*/_jsx(Select, {
69
+ size: "small",
70
+ fullWidth: true,
71
+ value: nav?.value,
72
+ onChange: e => {
73
+ const {
74
+ value
75
+ } = e.target;
76
+ const selected = getNav(value, navOptions);
77
+ setNav(selected);
78
+ setNavValue("");
79
+ },
80
+ displayEmpty: true,
81
+ children: navOptions.map((navOption, i) => {
82
+ return /*#__PURE__*/_jsx(MenuItem, {
83
+ value: navOption.value,
84
+ children: /*#__PURE__*/_jsx(Typography, {
85
+ variant: "body2",
86
+ children: navOption.label
78
87
  })
79
- })
80
- }), /*#__PURE__*/_jsx(Grid, {
81
- item: true,
82
- xs: 6,
83
- children: NavSettings && /*#__PURE__*/_jsx(NavSettings, {
84
- placeholder: nav?.placeholder,
85
- nav: nav,
86
- onChange: onChange,
87
- value: navValue,
88
- openInNewTab: openInNewTab,
89
- onNewTabChange: () => setOpenInNewTab(prev => !prev),
90
- services: customProps.services
91
- })
92
- })]
93
- })
94
- }), /*#__PURE__*/_jsxs(DialogActions, {
95
- children: [/*#__PURE__*/_jsx(Button, {
96
- onClick: handleClose,
97
- sx: classes.closeBtn,
98
- children: "Cancel"
99
- }), /*#__PURE__*/_jsx(Button, {
100
- onClick: () => {
101
- onSave({
102
- linkType: nav?.value,
103
- navValue,
104
- openInNewTab
105
- });
88
+ }, i);
89
+ })
90
+ }), /*#__PURE__*/_jsx(Box, {
91
+ sx: {
92
+ paddingTop: "14px"
106
93
  },
107
- sx: classes.saveBtn,
108
- children: "Save"
94
+ children: NavSettings && /*#__PURE__*/_jsx(NavSettings, {
95
+ placeholder: nav?.placeholder,
96
+ nav: nav,
97
+ onChange: onChange,
98
+ value: navValue,
99
+ openInNewTab: openInNewTab,
100
+ onNewTabChange: () => setOpenInNewTab(prev => !prev),
101
+ services: customProps.services
102
+ })
103
+ }), /*#__PURE__*/_jsx(Box, {
104
+ component: "div",
105
+ sx: classes.mobileActionBtns,
106
+ children: /*#__PURE__*/_jsx(ActionsButtons, {
107
+ classes: classes,
108
+ onCancel: handleClose,
109
+ onSave: onSubmit
110
+ })
111
+ })]
112
+ });
113
+ } else {
114
+ return /*#__PURE__*/_jsxs(Dialog, {
115
+ onClose: handleClose,
116
+ open: true,
117
+ sx: classes.dialogContainer,
118
+ fullWidth: true,
119
+ maxWidth: "sm",
120
+ children: [/*#__PURE__*/_jsx(DialogTitle, {
121
+ children: "What do you want to link to?"
122
+ }), /*#__PURE__*/_jsx(IconButton, {
123
+ "aria-label": "close",
124
+ onClick: handleClose,
125
+ sx: classes.closeIcon,
126
+ children: /*#__PURE__*/_jsx(CloseIcon, {})
127
+ }), /*#__PURE__*/_jsx(DialogContent, {
128
+ dividers: true,
129
+ children: /*#__PURE__*/_jsxs(Grid, {
130
+ container: true,
131
+ spacing: 2,
132
+ children: [/*#__PURE__*/_jsx(Grid, {
133
+ item: true,
134
+ xs: 6,
135
+ sx: classes.gridDivider,
136
+ children: /*#__PURE__*/_jsx(FormControl, {
137
+ children: /*#__PURE__*/_jsx(RadioGroup, {
138
+ value: nav?.value,
139
+ children: navOptions?.map((navOption, i) => {
140
+ return /*#__PURE__*/_jsx(FormControlLabel, {
141
+ value: navOption.value,
142
+ control: /*#__PURE__*/_jsx(Radio, {}),
143
+ label: navOption.label,
144
+ onChange: () => {
145
+ setNav(navOption);
146
+ setNavValue("");
147
+ }
148
+ }, i);
149
+ })
150
+ })
151
+ })
152
+ }), /*#__PURE__*/_jsx(Grid, {
153
+ item: true,
154
+ xs: 6,
155
+ children: NavSettings && /*#__PURE__*/_jsx(NavSettings, {
156
+ placeholder: nav?.placeholder,
157
+ nav: nav,
158
+ onChange: onChange,
159
+ value: navValue,
160
+ openInNewTab: openInNewTab,
161
+ onNewTabChange: () => setOpenInNewTab(prev => !prev),
162
+ services: customProps.services
163
+ })
164
+ })]
165
+ })
166
+ }), /*#__PURE__*/_jsx(DialogActions, {
167
+ children: /*#__PURE__*/_jsx(ActionsButtons, {
168
+ classes: classes,
169
+ onCancel: handleClose,
170
+ onSave: onSubmit
171
+ })
109
172
  })]
173
+ });
174
+ }
175
+ }
176
+ function ActionsButtons({
177
+ classes,
178
+ onCancel,
179
+ onSave
180
+ }) {
181
+ return /*#__PURE__*/_jsxs(_Fragment, {
182
+ children: [/*#__PURE__*/_jsx(Button, {
183
+ onClick: onCancel,
184
+ sx: classes.closeBtn,
185
+ children: "Cancel"
186
+ }), /*#__PURE__*/_jsx(Button, {
187
+ onClick: onSave,
188
+ sx: classes.saveBtn,
189
+ children: "Save"
110
190
  })]
111
191
  });
112
192
  }
@@ -50,6 +50,14 @@ const ButtonNavSettingsStyles = () => ({
50
50
  },
51
51
  gridDivider: {
52
52
  borderRight: "1px solid rgba(0, 0, 0, 0.12)"
53
+ },
54
+ mobileActionBtns: {
55
+ display: "flex",
56
+ justifyContent: "flex-end",
57
+ gap: "8px",
58
+ paddingTop: "14px",
59
+ marginTop: "14px",
60
+ borderTop: theme => `1px solid ${theme.palette.grey[300]}`
53
61
  }
54
62
  });
55
63
  export default ButtonNavSettingsStyles;
@@ -0,0 +1,34 @@
1
+ import { Box, SwipeableDrawer, Typography } from "@mui/material";
2
+ import DrawerStyles from "./style";
3
+ import { grey } from "@mui/material/colors";
4
+ import { styled } from "@mui/material/styles";
5
+ import { jsx as _jsx } from "react/jsx-runtime";
6
+ import { jsxs as _jsxs } from "react/jsx-runtime";
7
+ const Puller = styled("div")(({
8
+ theme
9
+ }) => ({
10
+ width: 30,
11
+ height: 6,
12
+ backgroundColor: theme?.palette?.mode === "light" ? grey[300] : grey[900],
13
+ borderRadius: 3,
14
+ margin: "auto",
15
+ marginTop: "14px"
16
+ }));
17
+ function SwipeableDrawerComponent({
18
+ open,
19
+ onClose,
20
+ children
21
+ }) {
22
+ const classes = DrawerStyles();
23
+ return /*#__PURE__*/_jsxs(SwipeableDrawer, {
24
+ anchor: "bottom",
25
+ open: true,
26
+ onClose: onClose,
27
+ sx: classes.drawerContainer,
28
+ children: [/*#__PURE__*/_jsx(Puller, {}), /*#__PURE__*/_jsx(Box, {
29
+ sx: classes.childContainer,
30
+ children: children
31
+ })]
32
+ });
33
+ }
34
+ export default SwipeableDrawerComponent;
@@ -0,0 +1,12 @@
1
+ const Styles = () => ({
2
+ drawerContainer: {
3
+ "& .MuiDrawer-paper": {
4
+ borderTopLeftRadius: 8,
5
+ borderTopRightRadius: 8
6
+ }
7
+ },
8
+ childContainer: {
9
+ padding: "20px"
10
+ }
11
+ });
12
+ export default Styles;
@@ -296,4 +296,5 @@ export const handleLinkType = (url, linkType, readOnly, openInNewTab, onClick =
296
296
  };
297
297
  }
298
298
  return props;
299
- };
299
+ };
300
+ export const allowedDomains = ["youtube.com", "lemcal.com", "facebook.com", "calendly.com"];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flozy/editor",
3
- "version": "3.2.8",
3
+ "version": "3.2.9",
4
4
  "description": "An Editor for flozy app brain",
5
5
  "files": [
6
6
  "dist"
@@ -39,6 +39,7 @@
39
39
  "react-scripts": "5.0.1",
40
40
  "react-signature-canvas": "^1.0.6",
41
41
  "react-slick": "^0.29.0",
42
+ "sanitize-html": "^2.13.0",
42
43
  "slate": "^0.94.1",
43
44
  "slate-history": "^0.93.0",
44
45
  "slate-hyperscript": "^0.100.0",
@@ -63,7 +64,7 @@
63
64
  "storybook": "storybook dev -p 6006",
64
65
  "build-storybook": "storybook build",
65
66
  "publish:npm": "rm -rf dist && mkdir dist && babel src/components -d dist --copy-files",
66
- "publish:local": "rm -rf /Users/agmac23/Desktop/surya/sweetpsocial-2.0/client/node_modules/@flozy/editor/dist && babel src/components -d /Users/agmac23/Desktop/surya/sweetpsocial-2.0/client/node_modules/@flozy/editor/dist --copy-files"
67
+ "publish:local": "rm -rf /Users/agmac03/flozy/client/node_modules/@flozy/editor/dist && babel src/components -d /Users/agmac03/flozy/client/node_modules/@flozy/editor/dist --copy-files"
67
68
  },
68
69
  "eslintConfig": {
69
70
  "extends": [