@flozy/editor 5.8.7 → 5.8.9
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.
- package/dist/Editor/CommonEditor.js +11 -9
- package/dist/Editor/Elements/SimpleText/index.js +7 -12
- package/dist/Editor/Toolbar/PopupTool/index.js +28 -31
- package/dist/Editor/common/FontLoader/FontLoader.js +13 -22
- package/dist/Editor/common/Section/index.js +60 -89
- package/dist/Editor/hooks/useEditorScroll.js +1 -1
- package/dist/Editor/utils/SlateUtilityFunctions.js +5 -0
- package/package.json +1 -1
@@ -54,13 +54,14 @@ const Item = /*#__PURE__*/forwardRef(({
|
|
54
54
|
});
|
55
55
|
});
|
56
56
|
Item.displayName = "Item";
|
57
|
-
const Element = props => {
|
57
|
+
const Element = /*#__PURE__*/React.memo(props => {
|
58
58
|
return /*#__PURE__*/_jsx(Section, {
|
59
59
|
...props,
|
60
60
|
children: getBlock(props)
|
61
61
|
});
|
62
|
-
};
|
63
|
-
|
62
|
+
});
|
63
|
+
Element.displayName = "Element";
|
64
|
+
const Leaf = /*#__PURE__*/React.memo(({
|
64
65
|
attributes,
|
65
66
|
children,
|
66
67
|
leaf
|
@@ -71,12 +72,13 @@ const Leaf = ({
|
|
71
72
|
...attributes,
|
72
73
|
children: children
|
73
74
|
});
|
74
|
-
};
|
75
|
+
});
|
76
|
+
Leaf.displayName = "Leaf";
|
75
77
|
const updateTopBanner = (content = [], setTopBanner) => {
|
76
|
-
setTopBanner(() => {
|
77
|
-
|
78
|
-
|
79
|
-
});
|
78
|
+
// setTopBanner(() => {
|
79
|
+
// const firstNode = content ? content[0] : {};
|
80
|
+
// return firstNode?.type === "topbanner" ? firstNode : null;
|
81
|
+
// });
|
80
82
|
};
|
81
83
|
const CommonEditor = /*#__PURE__*/forwardRef((props, ref) => {
|
82
84
|
const {
|
@@ -313,7 +315,7 @@ const CommonEditor = /*#__PURE__*/forwardRef((props, ref) => {
|
|
313
315
|
updateTopBanner(newValue, setTopBanner);
|
314
316
|
debounced(newValue);
|
315
317
|
if (!isInteracted) {
|
316
|
-
setIsInteracted(true);
|
318
|
+
// setIsInteracted(true);
|
317
319
|
}
|
318
320
|
}
|
319
321
|
};
|
@@ -1,7 +1,7 @@
|
|
1
1
|
import React from "react";
|
2
2
|
import { useSlateStatic, useSelected, ReactEditor } from "slate-react";
|
3
3
|
import { Box } from "@mui/material";
|
4
|
-
import { getPageSettings } from "../../utils/pageSettings";
|
4
|
+
// import { getPageSettings } from "../../utils/pageSettings";
|
5
5
|
import { isTextSelected } from "../../utils/helper";
|
6
6
|
import { useEditorContext } from "../../hooks/useMouseMove";
|
7
7
|
import SimpleTextStyle from "./style";
|
@@ -12,7 +12,6 @@ import { jsxs as _jsxs } from "react/jsx-runtime";
|
|
12
12
|
import { createElement as _createElement } from "react";
|
13
13
|
const SimpleText = props => {
|
14
14
|
const {
|
15
|
-
theme,
|
16
15
|
openAI
|
17
16
|
} = useEditorContext() || {};
|
18
17
|
const editor = useSlateStatic();
|
@@ -28,19 +27,15 @@ const SimpleText = props => {
|
|
28
27
|
readOnly,
|
29
28
|
editorPlaceholder
|
30
29
|
} = customProps;
|
31
|
-
const {
|
32
|
-
|
33
|
-
} = getPageSettings(editor) || {};
|
34
|
-
const {
|
35
|
-
pageColor
|
36
|
-
} = pageSt?.pageProps || {};
|
30
|
+
// const { element: pageSt } = getPageSettings(editor) || {};
|
31
|
+
// const { pageColor } = pageSt?.pageProps || {};
|
37
32
|
const {
|
38
33
|
activeBreakPoint
|
39
34
|
} = useEditorContext();
|
40
35
|
const lineHeight = element?.children[0]?.lineHeight;
|
41
36
|
const lineH = getBreakpointLineSpacing(lineHeight, activeBreakPoint);
|
42
37
|
const classes = SimpleTextStyle({
|
43
|
-
pageColor:
|
38
|
+
pageColor: "#FFFFFF",
|
44
39
|
lineHeight: lineH
|
45
40
|
});
|
46
41
|
const selected = useSelected();
|
@@ -59,14 +54,14 @@ const SimpleText = props => {
|
|
59
54
|
contentEditable: false,
|
60
55
|
className: "placeholder-simple-text",
|
61
56
|
children: isEmptyEditor ? editorPlaceholder || "Write Something..." : showPlaceHolder ? opacity && selected ? /*#__PURE__*/_jsxs(_Fragment, {
|
62
|
-
children: ["Type ", /*#__PURE__*/_jsx("span", {
|
57
|
+
children: ["Type", " ", /*#__PURE__*/_jsx("span", {
|
63
58
|
style: {
|
64
|
-
backgroundColor:
|
59
|
+
backgroundColor: "#F2F6FA",
|
65
60
|
padding: "0px 2px",
|
66
61
|
borderRadius: "2px"
|
67
62
|
},
|
68
63
|
children: "/"
|
69
|
-
}), " to browse elements"]
|
64
|
+
}), " ", "to browse elements"]
|
70
65
|
}) : "" : ""
|
71
66
|
}));
|
72
67
|
};
|
@@ -1,5 +1,5 @@
|
|
1
|
-
import React, {
|
2
|
-
import { Popper,
|
1
|
+
import React, { useEffect, useState } from "react";
|
2
|
+
import { Popper, Paper, ClickAwayListener } from "@mui/material";
|
3
3
|
import { Editor, Range, Transforms } from "slate";
|
4
4
|
import { ReactEditor, useSlate } from "slate-react";
|
5
5
|
import useDrag from "../../hooks/useDrag";
|
@@ -21,7 +21,8 @@ const PopupTool = props => {
|
|
21
21
|
const classes = usePopupStyles(theme);
|
22
22
|
const {
|
23
23
|
setPopupType,
|
24
|
-
openAI
|
24
|
+
openAI,
|
25
|
+
selectedElement
|
25
26
|
} = useEditorContext();
|
26
27
|
const [anchorEl, setAnchorEl] = useState(null);
|
27
28
|
const [open, setOpen] = useState(false);
|
@@ -32,13 +33,10 @@ const PopupTool = props => {
|
|
32
33
|
const [event] = useDrag(anchorEl);
|
33
34
|
const id = open ? "popup-edit-tool" : "";
|
34
35
|
const [size] = useWindowResize();
|
35
|
-
const {
|
36
|
-
selectedElement
|
37
|
-
} = useEditorContext();
|
38
|
-
const updateAnchorEl = useCallback(() => {
|
36
|
+
const updateAnchorEl = isScroll => {
|
39
37
|
try {
|
40
38
|
const isHavingSelection = selection && !Range.isCollapsed(selection);
|
41
|
-
if (isHavingSelection) {
|
39
|
+
if (isHavingSelection && event === "end") {
|
42
40
|
const domRange = ReactEditor.toDOMRange(editor, editor.selection);
|
43
41
|
const editorContainer = document.querySelector("#slate-wrapper-scroll-container")?.getBoundingClientRect();
|
44
42
|
const rect = domRange.getBoundingClientRect();
|
@@ -47,16 +45,21 @@ const PopupTool = props => {
|
|
47
45
|
rect.y = -500; // hide the popper
|
48
46
|
}
|
49
47
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
}
|
48
|
+
// Create a dummy anchor element to match Popper's requirements
|
49
|
+
const anchor = document.createElement("div");
|
50
|
+
anchor.style.position = "absolute";
|
51
|
+
anchor.style.top = `${rect.top + window.scrollY}px`;
|
52
|
+
anchor.style.left = `${rect.left + window.scrollX}px`;
|
53
|
+
document.body.appendChild(anchor);
|
54
|
+
if (!anchorEl || isScroll === "scroll") {
|
55
|
+
setAnchorEl(anchor);
|
56
|
+
setOpen(true);
|
57
|
+
}
|
55
58
|
}
|
56
59
|
} catch (err) {
|
57
60
|
console.log(err);
|
58
61
|
}
|
59
|
-
}
|
62
|
+
};
|
60
63
|
useEditorScroll(editorWrapper, updateAnchorEl);
|
61
64
|
useEffect(() => {
|
62
65
|
const userStoppedSelection = size?.device === "xs" ? true : event === "end"; // for mobile, when user starts the selection, we are gonna show the popup tool
|
@@ -86,7 +89,7 @@ const PopupTool = props => {
|
|
86
89
|
updateAnchorEl();
|
87
90
|
hideSlateSelection(); // removes slate selection background, when there is no selection
|
88
91
|
}
|
89
|
-
}, [selection]);
|
92
|
+
}, [selection, event]);
|
90
93
|
useEffect(() => {
|
91
94
|
if (selectedElement?.enable === 1) {
|
92
95
|
setAnchorEl(null);
|
@@ -117,24 +120,18 @@ const PopupTool = props => {
|
|
117
120
|
id: id,
|
118
121
|
open: open,
|
119
122
|
anchorEl: anchorEl,
|
120
|
-
transition: true,
|
121
123
|
sx: classes.popupWrapper,
|
122
124
|
placement: "top-start",
|
123
|
-
children: ({
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
editor: editor,
|
134
|
-
classes: classes,
|
135
|
-
closeMainPopup: handleClose,
|
136
|
-
customProps: customProps
|
137
|
-
})
|
125
|
+
children: /*#__PURE__*/_jsx(Paper, {
|
126
|
+
style: {
|
127
|
+
borderRadius: "6px",
|
128
|
+
border: "1px solid #8360FD"
|
129
|
+
},
|
130
|
+
children: /*#__PURE__*/_jsx(MiniTextFormat, {
|
131
|
+
editor: editor,
|
132
|
+
classes: classes,
|
133
|
+
closeMainPopup: handleClose,
|
134
|
+
customProps: customProps
|
138
135
|
})
|
139
136
|
})
|
140
137
|
})
|
@@ -1,11 +1,9 @@
|
|
1
1
|
import { useEffect, useState } from "react";
|
2
2
|
import WebFont from "webfontloader";
|
3
|
+
import { Backdrop, CircularProgress } from "@mui/material";
|
3
4
|
import { useEditorContext } from "../../hooks/useMouseMove";
|
4
5
|
import { googleFontList } from "./FontList";
|
5
|
-
import CircularProgress from '@mui/material/CircularProgress';
|
6
|
-
import Box from "@mui/material/Box";
|
7
6
|
import { jsx as _jsx } from "react/jsx-runtime";
|
8
|
-
import { Fragment as _Fragment } from "react/jsx-runtime";
|
9
7
|
const FontLoader = props => {
|
10
8
|
const {
|
11
9
|
otherProps,
|
@@ -14,7 +12,7 @@ const FontLoader = props => {
|
|
14
12
|
const {
|
15
13
|
setFontFamilies
|
16
14
|
} = useEditorContext();
|
17
|
-
const [
|
15
|
+
const [loader, setLoader] = useState(true);
|
18
16
|
const loadFontsInBatches = (families, batchSize = 5, maxRetries = 3) => {
|
19
17
|
let currentIndex = 0;
|
20
18
|
let retryCount = 0;
|
@@ -22,11 +20,11 @@ const FontLoader = props => {
|
|
22
20
|
function loadNextBatch() {
|
23
21
|
if (currentIndex >= families?.length) {
|
24
22
|
// console.log("All fonts have been loaded");
|
25
|
-
|
23
|
+
setLoader(false);
|
26
24
|
return;
|
27
25
|
}
|
28
26
|
if (currentIndex >= hideLoaderOn) {
|
29
|
-
|
27
|
+
setLoader(false);
|
30
28
|
}
|
31
29
|
const batch = families?.slice(currentIndex, currentIndex + batchSize);
|
32
30
|
const batchWithWeights = batch.map(font => `${font}:300,400,600,700`);
|
@@ -100,25 +98,18 @@ const FontLoader = props => {
|
|
100
98
|
families = families?.map(font => font?.replace(/\"/g, ""));
|
101
99
|
families = families?.map(font => font?.replace(", sans-serif", "")); //This is temporary fix for patch
|
102
100
|
families = families.filter(font => googleFontList.includes(font));
|
103
|
-
// setLoading(true);
|
104
101
|
loadFontsInBatches(families);
|
105
102
|
}
|
106
103
|
}, []);
|
107
|
-
return /*#__PURE__*/_jsx(
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
display: 'flex',
|
117
|
-
justifyContent: 'center',
|
118
|
-
alignItems: 'center'
|
119
|
-
},
|
120
|
-
children: /*#__PURE__*/_jsx(CircularProgress, {})
|
121
|
-
}) : null
|
104
|
+
return /*#__PURE__*/_jsx(Backdrop, {
|
105
|
+
open: loader,
|
106
|
+
sx: {
|
107
|
+
color: "#fff",
|
108
|
+
zIndex: theme => theme.zIndex.drawer + 1 // Ensure it's above other UI elements
|
109
|
+
},
|
110
|
+
children: /*#__PURE__*/_jsx(CircularProgress, {
|
111
|
+
color: "inherit"
|
112
|
+
})
|
122
113
|
});
|
123
114
|
};
|
124
115
|
export default FontLoader;
|
@@ -2,36 +2,34 @@ import React, { useRef, useState } from "react";
|
|
2
2
|
import { useTheme } from "@mui/material";
|
3
3
|
import { Transforms } from "slate";
|
4
4
|
import { ReactEditor, useSlateStatic } from "slate-react";
|
5
|
-
import { Box, IconButton,
|
5
|
+
import { Box, IconButton, Tooltip } from "@mui/material";
|
6
6
|
import SectionPopup from "../../Elements/Grid/SectionPopup";
|
7
7
|
import { getBreakPointsValue, getTRBLBreakPoints, groupByBreakpoint } from "../../helper/theme";
|
8
|
-
import DragHandle from "../DnD/DragHandleButton";
|
9
|
-
import { useEditorSelection } from "../../hooks/useMouseMove";
|
8
|
+
// import DragHandle from "../DnD/DragHandleButton";
|
9
|
+
// import { useEditorSelection } from "../../hooks/useMouseMove";
|
10
10
|
import SectionStyle from "./styles";
|
11
11
|
import useWindowResize from "../../hooks/useWindowResize";
|
12
12
|
import { SectionSettingIcon } from "../iconListV2";
|
13
|
+
|
14
|
+
// const list_types = ["orderedList", "unorderedList"];
|
13
15
|
import { jsx as _jsx } from "react/jsx-runtime";
|
14
16
|
import { jsxs as _jsxs } from "react/jsx-runtime";
|
15
|
-
import { Fragment as _Fragment } from "react/jsx-runtime";
|
16
17
|
const Toolbar = ({
|
17
|
-
fromPopper,
|
18
18
|
readOnly,
|
19
19
|
showTool,
|
20
|
-
onSettings
|
20
|
+
onSettings,
|
21
|
+
isSectionFullWidth
|
21
22
|
}) => {
|
22
23
|
return !readOnly && !showTool ? /*#__PURE__*/_jsx(Box, {
|
23
24
|
component: "div",
|
24
25
|
className: `element-toolbar no-border-button hr section-tw sectionIcon`,
|
25
26
|
contentEditable: false,
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
} : {
|
33
|
-
left: "-28px",
|
34
|
-
top: "1px"
|
27
|
+
sx: {
|
28
|
+
left: isSectionFullWidth ? "0px" : "-28px",
|
29
|
+
top: isSectionFullWidth ? "-28px" : "1px",
|
30
|
+
"&:hover": {
|
31
|
+
backgroundColor: "rgba(0,0,0,0.5)"
|
32
|
+
}
|
35
33
|
},
|
36
34
|
children: /*#__PURE__*/_jsx(Tooltip, {
|
37
35
|
title: "Section Settings",
|
@@ -42,7 +40,6 @@ const Toolbar = ({
|
|
42
40
|
})
|
43
41
|
}) : null;
|
44
42
|
};
|
45
|
-
const list_types = ["orderedList", "unorderedList"];
|
46
43
|
const Section = props => {
|
47
44
|
const themeReact = useTheme();
|
48
45
|
const theme = props?.theme;
|
@@ -56,7 +53,8 @@ const Section = props => {
|
|
56
53
|
readOnly
|
57
54
|
} = customProps;
|
58
55
|
const editor = useSlateStatic();
|
59
|
-
const [
|
56
|
+
// const [isHovering, setIsHovering] = useState(false);
|
57
|
+
const [size] = useWindowResize();
|
60
58
|
const [openSetttings, setOpenSettings] = useState(false);
|
61
59
|
const {
|
62
60
|
sectionBgColor,
|
@@ -73,41 +71,11 @@ const Section = props => {
|
|
73
71
|
} = sectionAlignment || {};
|
74
72
|
const path = ReactEditor.findPath(editor, element);
|
75
73
|
const anchorEl = useRef(null);
|
76
|
-
const popperEl = useRef(null);
|
77
|
-
const [
|
74
|
+
// const popperEl = useRef(null);
|
75
|
+
// const [showTool] = useEditorSelection(editor);
|
78
76
|
const isSectionFullWidth = sectionGridSize && sectionGridSize[size?.device] >= 12;
|
79
|
-
const [
|
80
|
-
const
|
81
|
-
setIsHovering(true);
|
82
|
-
};
|
83
|
-
const onMouseLeave = () => {
|
84
|
-
setIsHovering(false);
|
85
|
-
};
|
86
|
-
const onSettings = () => {
|
87
|
-
setOpenSettings(true);
|
88
|
-
};
|
89
|
-
const onSave = data => {
|
90
|
-
const updateData = {
|
91
|
-
...data
|
92
|
-
};
|
93
|
-
delete updateData.children;
|
94
|
-
Transforms.setNodes(editor, {
|
95
|
-
...updateData
|
96
|
-
}, {
|
97
|
-
at: path
|
98
|
-
});
|
99
|
-
onClose();
|
100
|
-
};
|
101
|
-
const onClose = () => {
|
102
|
-
setOpenSettings(false);
|
103
|
-
};
|
104
|
-
const onDelete = () => {
|
105
|
-
Transforms.removeNodes(editor, {
|
106
|
-
at: path
|
107
|
-
});
|
108
|
-
};
|
109
|
-
const isFreeGrid = element?.children?.find(f => f.type === "freegrid");
|
110
|
-
const needHover = element?.children?.find(f => f.type === "grid" && !list_types.includes(element.type)) ? "" : "";
|
77
|
+
const isFreeGrid = element?.children[0]?.type === "freegrid";
|
78
|
+
const needHover = false;
|
111
79
|
let tempProps = {};
|
112
80
|
if (element?.type === "temp") {
|
113
81
|
tempProps = {
|
@@ -131,6 +99,38 @@ const Section = props => {
|
|
131
99
|
...getBreakPointsValue(sectionGridSize || 8, null, "overrideGridSize", true)
|
132
100
|
}
|
133
101
|
}, themeReact);
|
102
|
+
|
103
|
+
// const onMouseEnter = () => {
|
104
|
+
// setIsHovering(true);
|
105
|
+
// };
|
106
|
+
|
107
|
+
// const onMouseLeave = () => {
|
108
|
+
// setIsHovering(false);
|
109
|
+
// };
|
110
|
+
|
111
|
+
const onSettings = () => {
|
112
|
+
setOpenSettings(true);
|
113
|
+
};
|
114
|
+
const onSave = data => {
|
115
|
+
const updateData = {
|
116
|
+
...data
|
117
|
+
};
|
118
|
+
delete updateData.children;
|
119
|
+
Transforms.setNodes(editor, {
|
120
|
+
...updateData
|
121
|
+
}, {
|
122
|
+
at: path
|
123
|
+
});
|
124
|
+
onClose();
|
125
|
+
};
|
126
|
+
const onClose = () => {
|
127
|
+
setOpenSettings(false);
|
128
|
+
};
|
129
|
+
const onDelete = () => {
|
130
|
+
Transforms.removeNodes(editor, {
|
131
|
+
at: path
|
132
|
+
});
|
133
|
+
};
|
134
134
|
return path.length === 1 && !isFreeGrid ? /*#__PURE__*/_jsxs(Box, {
|
135
135
|
component: "div",
|
136
136
|
className: `ed-section-wrapper ${readOnly ? "" : "hselect"} ${needHover} is-${element?.type}`,
|
@@ -145,9 +145,10 @@ const Section = props => {
|
|
145
145
|
flexDirection: flexDirection || "column",
|
146
146
|
alignItems: horizantal,
|
147
147
|
justifyContent: vertical
|
148
|
-
}
|
149
|
-
|
150
|
-
|
148
|
+
}
|
149
|
+
// onMouseEnter={onMouseEnter}
|
150
|
+
// onMouseLeave={onMouseLeave}
|
151
|
+
,
|
151
152
|
children: [/*#__PURE__*/_jsxs(Box, {
|
152
153
|
className: "ed-section-inner",
|
153
154
|
sx: {
|
@@ -155,41 +156,11 @@ const Section = props => {
|
|
155
156
|
...edInnerSp
|
156
157
|
},
|
157
158
|
ref: anchorEl,
|
158
|
-
children: [
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
zIndex: 9999
|
164
|
-
},
|
165
|
-
disablePortal: true,
|
166
|
-
ref: popperEl,
|
167
|
-
className: "sectionPopper",
|
168
|
-
children: /*#__PURE__*/_jsxs(Box, {
|
169
|
-
sx: {
|
170
|
-
bgcolor: "background.paper",
|
171
|
-
height: "30px",
|
172
|
-
position: "relative",
|
173
|
-
background: theme?.palette?.type === "dark" ? theme?.palette?.editor?.miniToolBarBackground : "#F6F6F6"
|
174
|
-
},
|
175
|
-
children: [!readOnly && !showTool ? /*#__PURE__*/_jsx(DragHandle, {
|
176
|
-
...props,
|
177
|
-
fromPopper: true
|
178
|
-
}) : null, /*#__PURE__*/_jsx(Toolbar, {
|
179
|
-
fromPopper: true,
|
180
|
-
readOnly: readOnly,
|
181
|
-
showTool: showTool,
|
182
|
-
onSettings: onSettings
|
183
|
-
})]
|
184
|
-
})
|
185
|
-
}) : /*#__PURE__*/_jsxs(_Fragment, {
|
186
|
-
children: [!readOnly && !showTool ? /*#__PURE__*/_jsx(DragHandle, {
|
187
|
-
...props
|
188
|
-
}) : null, /*#__PURE__*/_jsx(Toolbar, {
|
189
|
-
readOnly: readOnly,
|
190
|
-
showTool: showTool,
|
191
|
-
onSettings: onSettings
|
192
|
-
})]
|
159
|
+
children: [/*#__PURE__*/_jsx(Toolbar, {
|
160
|
+
isSectionFullWidth: isSectionFullWidth,
|
161
|
+
readOnly: readOnly,
|
162
|
+
showTool: false,
|
163
|
+
onSettings: onSettings
|
193
164
|
}), children]
|
194
165
|
}), openSetttings ? /*#__PURE__*/_jsx(SectionPopup, {
|
195
166
|
element: {
|
@@ -620,6 +620,11 @@ export const getBlock = props => {
|
|
620
620
|
children: children
|
621
621
|
});
|
622
622
|
default:
|
623
|
+
// return (
|
624
|
+
// <span {...attributes} {...element.attr}>
|
625
|
+
// {children}
|
626
|
+
// </span>
|
627
|
+
// );
|
623
628
|
return /*#__PURE__*/_jsx(SimpleText, {
|
624
629
|
...props,
|
625
630
|
isEmpty: isEmpty
|