@selfcommunity/react-ui 0.7.0-alpha.314 → 0.7.0-alpha.316
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/lib/cjs/components/Editor/Editor.js +0 -2
- package/lib/cjs/components/Editor/nodes/ImageNode.d.ts +8 -11
- package/lib/cjs/components/Editor/nodes/ImageNode.js +47 -313
- package/lib/cjs/components/Editor/plugins/ImagePlugin.js +1 -1
- package/lib/cjs/components/Feed/Feed.js +3 -2
- package/lib/esm/components/Editor/Editor.js +0 -2
- package/lib/esm/components/Editor/nodes/ImageNode.d.ts +8 -11
- package/lib/esm/components/Editor/nodes/ImageNode.js +49 -315
- package/lib/esm/components/Editor/plugins/ImagePlugin.js +1 -1
- package/lib/esm/components/Feed/Feed.js +4 -3
- package/lib/umd/react-ui.js +1 -1
- package/package.json +2 -2
|
@@ -19,7 +19,6 @@ const LexicalLinkPlugin_1 = require("@lexical/react/LexicalLinkPlugin");
|
|
|
19
19
|
const ApiPlugin_1 = tslib_1.__importDefault(require("./plugins/ApiPlugin"));
|
|
20
20
|
const ToolbarPlugin_1 = tslib_1.__importDefault(require("./plugins/ToolbarPlugin"));
|
|
21
21
|
const LexicalListPlugin_1 = require("@lexical/react/LexicalListPlugin");
|
|
22
|
-
const useMediaQuery_1 = tslib_1.__importDefault(require("@mui/material/useMediaQuery"));
|
|
23
22
|
const FloatingLinkPlugin_1 = tslib_1.__importDefault(require("./plugins/FloatingLinkPlugin"));
|
|
24
23
|
const OnBlurPlugin_1 = tslib_1.__importDefault(require("./plugins/OnBlurPlugin"));
|
|
25
24
|
const OnFocusPlugin_1 = tslib_1.__importDefault(require("./plugins/OnFocusPlugin"));
|
|
@@ -110,7 +109,6 @@ const Editor = (inProps, ref) => {
|
|
|
110
109
|
const apiRef = (0, react_1.useRef)();
|
|
111
110
|
// MEMO
|
|
112
111
|
const theme = (0, material_1.useTheme)();
|
|
113
|
-
const isMobile = (0, useMediaQuery_1.default)(theme.breakpoints.down('md'));
|
|
114
112
|
// HANDLERS
|
|
115
113
|
const handleChange = (value) => {
|
|
116
114
|
onChange && onChange(value);
|
|
@@ -3,33 +3,30 @@ import { DecoratorNode, DOMExportOutput, EditorConfig, LexicalNode, NodeKey, Ser
|
|
|
3
3
|
export interface ImagePayload {
|
|
4
4
|
altText: string;
|
|
5
5
|
className?: string;
|
|
6
|
-
height
|
|
6
|
+
height: number;
|
|
7
7
|
imageRef?: LegacyRef<HTMLImageElement>;
|
|
8
|
-
maxWidth: number | string;
|
|
9
8
|
src: string;
|
|
10
|
-
width
|
|
9
|
+
width: number;
|
|
11
10
|
}
|
|
12
11
|
declare function convertImageElement(domNode: any): {
|
|
13
12
|
node: ImageNode;
|
|
14
13
|
};
|
|
15
14
|
export declare type SerializedImageNode = Spread<{
|
|
16
15
|
altText: string;
|
|
17
|
-
height
|
|
18
|
-
maxWidth: number | string;
|
|
16
|
+
height: number;
|
|
19
17
|
src: string;
|
|
20
|
-
width
|
|
18
|
+
width: number;
|
|
21
19
|
type: 'image';
|
|
22
20
|
version: 1;
|
|
23
21
|
}, SerializedLexicalNode>;
|
|
24
22
|
export declare class ImageNode extends DecoratorNode<JSX.Element> {
|
|
25
23
|
__src: string;
|
|
26
24
|
__altText: string;
|
|
27
|
-
__width:
|
|
28
|
-
__height:
|
|
29
|
-
__maxWidth: number | string;
|
|
25
|
+
__width: number;
|
|
26
|
+
__height: number;
|
|
30
27
|
static getType(): string;
|
|
31
28
|
static clone(node: ImageNode): ImageNode;
|
|
32
|
-
constructor(src: string, altText: string,
|
|
29
|
+
constructor(src: string, altText: string, width: number, height: number, key?: NodeKey);
|
|
33
30
|
setWidthAndHeight(width: 'inherit' | number, height: 'inherit' | number): void;
|
|
34
31
|
createDOM(config: EditorConfig): HTMLElement;
|
|
35
32
|
updateDOM(): false;
|
|
@@ -44,6 +41,6 @@ export declare class ImageNode extends DecoratorNode<JSX.Element> {
|
|
|
44
41
|
static importJSON(serializedNode: SerializedImageNode): ImageNode;
|
|
45
42
|
exportJSON(): SerializedImageNode;
|
|
46
43
|
}
|
|
47
|
-
export declare function $createImageNode({ src, altText,
|
|
44
|
+
export declare function $createImageNode({ src, altText, width, height }: ImagePayload): ImageNode;
|
|
48
45
|
export declare function $isImageNode(node?: LexicalNode): boolean;
|
|
49
46
|
export {};
|
|
@@ -7,248 +7,18 @@ const lexical_1 = require("lexical");
|
|
|
7
7
|
const LexicalComposerContext_1 = require("@lexical/react/LexicalComposerContext");
|
|
8
8
|
const useLexicalNodeSelection_1 = require("@lexical/react/useLexicalNodeSelection");
|
|
9
9
|
const utils_1 = require("@lexical/utils");
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
position: 'absolute',
|
|
23
|
-
top: 0,
|
|
24
|
-
left: 0,
|
|
25
|
-
zIndex: 2000,
|
|
26
|
-
outline: `2px solid ${theme.palette.primary.main}`,
|
|
27
|
-
userSelect: 'none',
|
|
28
|
-
display: 'flex',
|
|
29
|
-
justifyContent: 'center',
|
|
30
|
-
alignItems: 'center',
|
|
31
|
-
'& .MuiPaper-root': {
|
|
32
|
-
padding: theme.spacing(1),
|
|
33
|
-
display: 'flex',
|
|
34
|
-
flexDirection: 'column',
|
|
35
|
-
justifyContent: 'center',
|
|
36
|
-
alignItems: 'center',
|
|
37
|
-
width: '50%',
|
|
38
|
-
backgroundColor: theme.palette.background.paper,
|
|
39
|
-
'& > *': {
|
|
40
|
-
margin: theme.spacing(1)
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
}));
|
|
44
|
-
const ImageEdit = ({ onResize, onDelete, imageRef }) => {
|
|
45
|
-
// STATE
|
|
46
|
-
const [width, setWidth] = (0, react_1.useState)(imageRef.current.width);
|
|
47
|
-
const [height, setHeight] = (0, react_1.useState)(imageRef.current.height);
|
|
48
|
-
const [openResizePanel, setOpenResizePanel] = (0, react_1.useState)(false);
|
|
49
|
-
// HANDLERS
|
|
50
|
-
const handleStopPropagation = (event) => {
|
|
51
|
-
event.preventDefault();
|
|
52
|
-
event.stopPropagation();
|
|
53
|
-
return false;
|
|
54
|
-
};
|
|
55
|
-
const handleOpenResizePanel = (event) => {
|
|
56
|
-
event.preventDefault();
|
|
57
|
-
event.stopPropagation();
|
|
58
|
-
setOpenResizePanel(true);
|
|
59
|
-
return false;
|
|
60
|
-
};
|
|
61
|
-
const handleChangeWidth = (event) => {
|
|
62
|
-
setWidth(event.target.value);
|
|
63
|
-
};
|
|
64
|
-
const handleChangeHeight = (event) => {
|
|
65
|
-
setHeight(event.target.value);
|
|
66
|
-
};
|
|
67
|
-
const handleResize = (event) => {
|
|
68
|
-
onResize(width, height);
|
|
69
|
-
setOpenResizePanel(false);
|
|
70
|
-
};
|
|
71
|
-
// RENDER
|
|
72
|
-
return (react_1.default.createElement(Root, { className: classes.root, style: { width: imageRef.current.width, height: imageRef.current.height }, contentEditable: false, onClick: handleStopPropagation },
|
|
73
|
-
react_1.default.createElement(material_1.Paper, null, openResizePanel ? (react_1.default.createElement(react_1.default.Fragment, null,
|
|
74
|
-
react_1.default.createElement(material_1.TextField, { value: width, type: "number", onChange: handleChangeWidth, label: react_1.default.createElement(react_intl_1.FormattedMessage, { id: "ui.editor.imagePluginEdit.width", defaultMessage: "ui.editor.imagePluginEdit.width" }), InputProps: {
|
|
75
|
-
endAdornment: react_1.default.createElement(material_1.InputAdornment, { position: "start" }, "px")
|
|
76
|
-
} }),
|
|
77
|
-
react_1.default.createElement(material_1.TextField, { value: height, type: "number", onChange: handleChangeHeight, label: react_1.default.createElement(react_intl_1.FormattedMessage, { id: "ui.editor.imagePluginEdit.height", defaultMessage: "ui.editor.imagePluginEdit.height" }), InputProps: {
|
|
78
|
-
endAdornment: react_1.default.createElement(material_1.InputAdornment, { position: "start" }, "px")
|
|
79
|
-
} }),
|
|
80
|
-
react_1.default.createElement(material_1.Button, { variant: "contained", color: "primary", disabled: width === imageRef.current.width && height === imageRef.current.height, onClick: handleResize },
|
|
81
|
-
react_1.default.createElement(react_intl_1.FormattedMessage, { id: "ui.editor.imagePluginEdit.resize", defaultMessage: "ui.editor.imagePluginEdit.resize" })))) : (react_1.default.createElement(react_1.default.Fragment, null,
|
|
82
|
-
react_1.default.createElement(material_1.Button, { variant: "contained", color: "primary", onClick: handleOpenResizePanel },
|
|
83
|
-
react_1.default.createElement(react_intl_1.FormattedMessage, { id: "ui.editor.imagePluginEdit.resize", defaultMessage: "ui.editor.imagePluginEdit.resize" })),
|
|
84
|
-
react_1.default.createElement(material_1.Button, { variant: "contained", color: "secondary", onClick: onDelete },
|
|
85
|
-
react_1.default.createElement(react_intl_1.FormattedMessage, { id: "ui.editor.imagePluginEdit.delete", defaultMessage: "ui.editor.imagePluginEdit.delete" })))))));
|
|
86
|
-
};
|
|
87
|
-
function clamp(value, min, max) {
|
|
88
|
-
return Math.min(Math.max(value, min), Number(max));
|
|
89
|
-
}
|
|
90
|
-
const Direction = {
|
|
91
|
-
east: 1 << 0,
|
|
92
|
-
north: 1 << 3,
|
|
93
|
-
south: 1 << 1,
|
|
94
|
-
west: 1 << 2
|
|
95
|
-
};
|
|
96
|
-
function ImageResizer({ onResizeStart, onResizeEnd, imageRef, maxWidth, editor }) {
|
|
97
|
-
const controlWrapperRef = (0, react_1.useRef)(null);
|
|
98
|
-
const userSelect = (0, react_1.useRef)({
|
|
99
|
-
priority: '',
|
|
100
|
-
value: 'default'
|
|
101
|
-
});
|
|
102
|
-
const positioningRef = (0, react_1.useRef)({
|
|
103
|
-
currentHeight: 0,
|
|
104
|
-
currentWidth: 0,
|
|
105
|
-
direction: 0,
|
|
106
|
-
isResizing: false,
|
|
107
|
-
ratio: 0,
|
|
108
|
-
startHeight: 0,
|
|
109
|
-
startWidth: 0,
|
|
110
|
-
startX: 0,
|
|
111
|
-
startY: 0
|
|
112
|
-
});
|
|
113
|
-
const editorRootElement = editor.getRootElement();
|
|
114
|
-
// Find max width, accounting for editor padding.
|
|
115
|
-
const maxWidthContainer = maxWidth ? maxWidth : editorRootElement !== null ? editorRootElement.getBoundingClientRect().width - 20 : 100;
|
|
116
|
-
const maxHeightContainer = editorRootElement !== null ? editorRootElement.getBoundingClientRect().height - 20 : 100;
|
|
117
|
-
const minWidth = 100;
|
|
118
|
-
const minHeight = 100;
|
|
119
|
-
const setStartCursor = (direction) => {
|
|
120
|
-
const ew = direction === Direction.east || direction === Direction.west;
|
|
121
|
-
const ns = direction === Direction.north || direction === Direction.south;
|
|
122
|
-
const nwse = (direction & Direction.north && direction & Direction.west) || (direction & Direction.south && direction & Direction.east);
|
|
123
|
-
const cursorDir = ew ? 'ew' : ns ? 'ns' : nwse ? 'nwse' : 'nesw';
|
|
124
|
-
if (editorRootElement !== null) {
|
|
125
|
-
editorRootElement.style.setProperty('cursor', `${cursorDir}-resize`, 'important');
|
|
126
|
-
}
|
|
127
|
-
if (document.body !== null) {
|
|
128
|
-
document.body.style.setProperty('cursor', `${cursorDir}-resize`, 'important');
|
|
129
|
-
userSelect.current.value = document.body.style.getPropertyValue('-webkit-user-select');
|
|
130
|
-
userSelect.current.priority = document.body.style.getPropertyPriority('-webkit-user-select');
|
|
131
|
-
document.body.style.setProperty('-webkit-user-select', `none`, 'important');
|
|
132
|
-
}
|
|
133
|
-
};
|
|
134
|
-
const setEndCursor = () => {
|
|
135
|
-
if (editorRootElement !== null) {
|
|
136
|
-
editorRootElement.style.setProperty('cursor', 'text');
|
|
137
|
-
}
|
|
138
|
-
if (document.body !== null) {
|
|
139
|
-
document.body.style.setProperty('cursor', 'default');
|
|
140
|
-
document.body.style.setProperty('-webkit-user-select', userSelect.current.value, userSelect.current.priority);
|
|
141
|
-
}
|
|
142
|
-
};
|
|
143
|
-
const handlePointerDown = (event, direction) => {
|
|
144
|
-
if (!editor.isEditable()) {
|
|
145
|
-
return;
|
|
146
|
-
}
|
|
147
|
-
const image = imageRef.current;
|
|
148
|
-
const controlWrapper = controlWrapperRef.current;
|
|
149
|
-
if (image !== null && controlWrapper !== null) {
|
|
150
|
-
const { width, height } = image.getBoundingClientRect();
|
|
151
|
-
const positioning = positioningRef.current;
|
|
152
|
-
positioning.startWidth = width;
|
|
153
|
-
positioning.startHeight = height;
|
|
154
|
-
positioning.ratio = width / height;
|
|
155
|
-
positioning.currentWidth = width;
|
|
156
|
-
positioning.currentHeight = height;
|
|
157
|
-
positioning.startX = event.clientX;
|
|
158
|
-
positioning.startY = event.clientY;
|
|
159
|
-
positioning.isResizing = true;
|
|
160
|
-
positioning.direction = direction;
|
|
161
|
-
setStartCursor(direction);
|
|
162
|
-
onResizeStart();
|
|
163
|
-
controlWrapper.classList.add('image-control-wrapper--resizing');
|
|
164
|
-
image.style.height = `${height}px`;
|
|
165
|
-
image.style.width = `${width}px`;
|
|
166
|
-
document.addEventListener('pointermove', handlePointerMove);
|
|
167
|
-
document.addEventListener('pointerup', handlePointerUp);
|
|
168
|
-
}
|
|
169
|
-
};
|
|
170
|
-
const handlePointerMove = (event) => {
|
|
171
|
-
const image = imageRef.current;
|
|
172
|
-
const positioning = positioningRef.current;
|
|
173
|
-
const isHorizontal = positioning.direction & (Direction.east | Direction.west);
|
|
174
|
-
const isVertical = positioning.direction & (Direction.south | Direction.north);
|
|
175
|
-
if (image !== null && positioning.isResizing) {
|
|
176
|
-
// Corner cursor
|
|
177
|
-
if (isHorizontal && isVertical) {
|
|
178
|
-
let diff = Math.floor(positioning.startX - event.clientX);
|
|
179
|
-
diff = positioning.direction & Direction.east ? -diff : diff;
|
|
180
|
-
const width = clamp(positioning.startWidth + diff, minWidth, maxWidthContainer);
|
|
181
|
-
const height = width / positioning.ratio;
|
|
182
|
-
image.style.width = `${width}px`;
|
|
183
|
-
image.style.height = `${height}px`;
|
|
184
|
-
positioning.currentHeight = height;
|
|
185
|
-
positioning.currentWidth = width;
|
|
186
|
-
}
|
|
187
|
-
else if (isVertical) {
|
|
188
|
-
let diff = Math.floor(positioning.startY - event.clientY);
|
|
189
|
-
diff = positioning.direction & Direction.south ? -diff : diff;
|
|
190
|
-
const height = clamp(positioning.startHeight + diff, minHeight, maxHeightContainer);
|
|
191
|
-
image.style.height = `${height}px`;
|
|
192
|
-
positioning.currentHeight = height;
|
|
193
|
-
}
|
|
194
|
-
else {
|
|
195
|
-
let diff = Math.floor(positioning.startX - event.clientX);
|
|
196
|
-
diff = positioning.direction & Direction.east ? -diff : diff;
|
|
197
|
-
const width = clamp(positioning.startWidth + diff, minWidth, maxWidthContainer);
|
|
198
|
-
image.style.width = `${width}px`;
|
|
199
|
-
positioning.currentWidth = width;
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
};
|
|
203
|
-
const handlePointerUp = () => {
|
|
204
|
-
const image = imageRef.current;
|
|
205
|
-
const positioning = positioningRef.current;
|
|
206
|
-
const controlWrapper = controlWrapperRef.current;
|
|
207
|
-
if (image !== null && controlWrapper !== null && positioning.isResizing) {
|
|
208
|
-
const width = positioning.currentWidth;
|
|
209
|
-
const height = positioning.currentHeight;
|
|
210
|
-
positioning.startWidth = 0;
|
|
211
|
-
positioning.startHeight = 0;
|
|
212
|
-
positioning.ratio = 0;
|
|
213
|
-
positioning.startX = 0;
|
|
214
|
-
positioning.startY = 0;
|
|
215
|
-
positioning.currentWidth = 0;
|
|
216
|
-
positioning.currentHeight = 0;
|
|
217
|
-
positioning.isResizing = false;
|
|
218
|
-
controlWrapper.classList.remove('image-control-wrapper--resizing');
|
|
219
|
-
setEndCursor();
|
|
220
|
-
console.log(width);
|
|
221
|
-
console.log(height);
|
|
222
|
-
onResizeEnd(width, height);
|
|
223
|
-
document.removeEventListener('pointermove', handlePointerMove);
|
|
224
|
-
document.removeEventListener('pointerup', handlePointerUp);
|
|
225
|
-
}
|
|
226
|
-
};
|
|
227
|
-
return (react_1.default.createElement("div", { ref: controlWrapperRef },
|
|
228
|
-
react_1.default.createElement("div", { className: "image-resizer image-resizer-n", onPointerDown: (event) => {
|
|
229
|
-
handlePointerDown(event, Direction.north);
|
|
230
|
-
} }),
|
|
231
|
-
react_1.default.createElement("div", { className: "image-resizer image-resizer-ne", onPointerDown: (event) => {
|
|
232
|
-
handlePointerDown(event, Direction.north | Direction.east);
|
|
233
|
-
} }),
|
|
234
|
-
react_1.default.createElement("div", { className: "image-resizer image-resizer-e", onPointerDown: (event) => {
|
|
235
|
-
handlePointerDown(event, Direction.east);
|
|
236
|
-
} }),
|
|
237
|
-
react_1.default.createElement("div", { className: "image-resizer image-resizer-se", onPointerDown: (event) => {
|
|
238
|
-
handlePointerDown(event, Direction.south | Direction.east);
|
|
239
|
-
} }),
|
|
240
|
-
react_1.default.createElement("div", { className: "image-resizer image-resizer-s", onPointerDown: (event) => {
|
|
241
|
-
handlePointerDown(event, Direction.south);
|
|
242
|
-
} }),
|
|
243
|
-
react_1.default.createElement("div", { className: "image-resizer image-resizer-sw", onPointerDown: (event) => {
|
|
244
|
-
handlePointerDown(event, Direction.south | Direction.west);
|
|
245
|
-
} }),
|
|
246
|
-
react_1.default.createElement("div", { className: "image-resizer image-resizer-w", onPointerDown: (event) => {
|
|
247
|
-
handlePointerDown(event, Direction.west);
|
|
248
|
-
} }),
|
|
249
|
-
react_1.default.createElement("div", { className: "image-resizer image-resizer-nw", onPointerDown: (event) => {
|
|
250
|
-
handlePointerDown(event, Direction.north | Direction.west);
|
|
251
|
-
} })));
|
|
10
|
+
/**
|
|
11
|
+
* Limit the width of an image
|
|
12
|
+
* Used to compute the padding-bottom of the div that wrap the img
|
|
13
|
+
*/
|
|
14
|
+
const IMAGE_WIDTH_THRESHOLD = 500;
|
|
15
|
+
/**
|
|
16
|
+
* Calc aspect-ratio of image
|
|
17
|
+
* @param width
|
|
18
|
+
* @param height
|
|
19
|
+
*/
|
|
20
|
+
function getAspectRatio(width, height) {
|
|
21
|
+
return width / height;
|
|
252
22
|
}
|
|
253
23
|
const imageCache = new Set();
|
|
254
24
|
function useSuspenseImage(src) {
|
|
@@ -263,21 +33,21 @@ function useSuspenseImage(src) {
|
|
|
263
33
|
});
|
|
264
34
|
}
|
|
265
35
|
}
|
|
266
|
-
function LazyImage({ altText, className, imageRef, src, width, height
|
|
36
|
+
function LazyImage({ altText, className, imageRef, src, width, height }) {
|
|
267
37
|
useSuspenseImage(src);
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
38
|
+
const aspectRatio = getAspectRatio(IMAGE_WIDTH_THRESHOLD, height);
|
|
39
|
+
return (react_1.default.createElement("div", { draggable: false, className: className, style: { position: 'relative', paddingBottom: `${100 / aspectRatio}%` } },
|
|
40
|
+
react_1.default.createElement("img", { src: src, alt: altText, ref: imageRef, style: {
|
|
41
|
+
position: 'absolute',
|
|
42
|
+
height: `100%`,
|
|
43
|
+
width: `100%`
|
|
44
|
+
} })));
|
|
273
45
|
}
|
|
274
|
-
function ImageComponent({ src, altText, nodeKey, width, height
|
|
46
|
+
function ImageComponent({ src, altText, nodeKey, width, height }) {
|
|
275
47
|
const imageRef = (0, react_1.useRef)(null);
|
|
276
48
|
const buttonRef = (0, react_1.useRef)(null);
|
|
277
49
|
const [isSelected, setSelected, clearSelection] = (0, useLexicalNodeSelection_1.useLexicalNodeSelection)(nodeKey);
|
|
278
|
-
const [isResizing, setIsResizing] = (0, react_1.useState)(false);
|
|
279
50
|
const [editor] = (0, LexicalComposerContext_1.useLexicalComposerContext)();
|
|
280
|
-
const [selection, setSelection] = (0, react_1.useState)(null);
|
|
281
51
|
const activeEditorRef = (0, react_1.useRef)(null);
|
|
282
52
|
const onDelete = (0, react_1.useCallback)((payload) => {
|
|
283
53
|
if (isSelected && (0, lexical_1.$isNodeSelection)((0, lexical_1.$getSelection)())) {
|
|
@@ -318,19 +88,11 @@ function ImageComponent({ src, altText, nodeKey, width, height, maxWidth, resiza
|
|
|
318
88
|
return false;
|
|
319
89
|
}, [editor, setSelected]);
|
|
320
90
|
(0, react_1.useEffect)(() => {
|
|
321
|
-
|
|
322
|
-
const unregister = (0, utils_1.mergeRegister)(editor.registerUpdateListener(({ editorState }) => {
|
|
323
|
-
if (isMounted) {
|
|
324
|
-
setSelection(editorState.read(() => (0, lexical_1.$getSelection)()));
|
|
325
|
-
}
|
|
326
|
-
}), editor.registerCommand(lexical_1.SELECTION_CHANGE_COMMAND, (_, activeEditor) => {
|
|
91
|
+
const unregister = (0, utils_1.mergeRegister)(editor.registerCommand(lexical_1.SELECTION_CHANGE_COMMAND, (_, activeEditor) => {
|
|
327
92
|
activeEditorRef.current = activeEditor;
|
|
328
93
|
return false;
|
|
329
94
|
}, lexical_1.COMMAND_PRIORITY_LOW), editor.registerCommand(lexical_1.CLICK_COMMAND, (payload) => {
|
|
330
95
|
const event = payload;
|
|
331
|
-
if (isResizing) {
|
|
332
|
-
return true;
|
|
333
|
-
}
|
|
334
96
|
if (event.target === imageRef.current) {
|
|
335
97
|
if (event.shiftKey) {
|
|
336
98
|
setSelected(!isSelected);
|
|
@@ -342,65 +104,36 @@ function ImageComponent({ src, altText, nodeKey, width, height, maxWidth, resiza
|
|
|
342
104
|
return true;
|
|
343
105
|
}
|
|
344
106
|
return false;
|
|
345
|
-
}, lexical_1.COMMAND_PRIORITY_LOW), editor.registerCommand(lexical_1.DRAGSTART_COMMAND, (event) => {
|
|
346
|
-
if (event.target === imageRef.current) {
|
|
347
|
-
// TODO This is just a temporary workaround for FF to behave like other browsers.
|
|
348
|
-
// Ideally, this handles drag & drop too (and all browsers).
|
|
349
|
-
event.preventDefault();
|
|
350
|
-
return true;
|
|
351
|
-
}
|
|
352
|
-
return false;
|
|
353
107
|
}, lexical_1.COMMAND_PRIORITY_LOW), editor.registerCommand(lexical_1.KEY_DELETE_COMMAND, onDelete, lexical_1.COMMAND_PRIORITY_LOW), editor.registerCommand(lexical_1.KEY_BACKSPACE_COMMAND, onDelete, lexical_1.COMMAND_PRIORITY_LOW), editor.registerCommand(lexical_1.KEY_ENTER_COMMAND, onEnter, lexical_1.COMMAND_PRIORITY_LOW), editor.registerCommand(lexical_1.KEY_ESCAPE_COMMAND, onEscape, lexical_1.COMMAND_PRIORITY_LOW));
|
|
354
108
|
return () => {
|
|
355
|
-
isMounted = false;
|
|
356
109
|
unregister();
|
|
357
110
|
};
|
|
358
|
-
}, [clearSelection, editor,
|
|
359
|
-
const
|
|
360
|
-
// Delay hiding the resize bars for click case
|
|
361
|
-
setTimeout(() => {
|
|
362
|
-
setIsResizing(false);
|
|
363
|
-
}, 200);
|
|
364
|
-
editor.update(() => {
|
|
365
|
-
const node = (0, lexical_1.$getNodeByKey)(nodeKey);
|
|
366
|
-
if ($isImageNode(node)) {
|
|
367
|
-
node.setWidthAndHeight(nextWidth, nextHeight);
|
|
368
|
-
}
|
|
369
|
-
});
|
|
370
|
-
};
|
|
371
|
-
const onResizeStart = () => {
|
|
372
|
-
setIsResizing(true);
|
|
373
|
-
};
|
|
374
|
-
const draggable = isSelected && (0, lexical_1.$isNodeSelection)(selection) && !isResizing;
|
|
375
|
-
const isFocused = isSelected || isResizing;
|
|
111
|
+
}, [clearSelection, editor, isSelected, nodeKey, onDelete, onEnter, onEscape, setSelected]);
|
|
112
|
+
const isFocused = isSelected;
|
|
376
113
|
return (react_1.default.createElement(react_1.Suspense, { fallback: null },
|
|
377
|
-
react_1.default.createElement(
|
|
378
|
-
react_1.default.createElement("div", { draggable: draggable },
|
|
379
|
-
react_1.default.createElement(LazyImage, { className: isFocused ? `focused ${(0, lexical_1.$isNodeSelection)(selection) ? 'draggable' : ''}` : null, src: src, altText: altText, imageRef: imageRef, width: width, height: height, maxWidth: maxWidth })),
|
|
380
|
-
resizable && (0, lexical_1.$isNodeSelection)(selection) && isFocused && (react_1.default.createElement(ImageResizer, { editor: editor, imageRef: imageRef, maxWidth: typeof maxWidth === 'number' ? maxWidth : null, onResizeStart: onResizeStart, onResizeEnd: onResizeEnd })))));
|
|
114
|
+
react_1.default.createElement(LazyImage, { className: isFocused ? `focused` : null, src: src, altText: altText, imageRef: imageRef, width: width, height: height })));
|
|
381
115
|
}
|
|
382
116
|
function convertImageElement(domNode) {
|
|
383
117
|
if (domNode instanceof HTMLImageElement) {
|
|
384
|
-
const { alt: altText, src, width, height } = domNode;
|
|
385
|
-
const node = $createImageNode({ altText, height, src, width
|
|
118
|
+
const { alt: altText, src, dataset: { width, height } } = domNode;
|
|
119
|
+
const node = $createImageNode({ altText, height: Number(height), src, width: Number(width) });
|
|
386
120
|
return { node };
|
|
387
121
|
}
|
|
388
122
|
return null;
|
|
389
123
|
}
|
|
390
124
|
class ImageNode extends lexical_1.DecoratorNode {
|
|
391
|
-
constructor(src, altText,
|
|
125
|
+
constructor(src, altText, width, height, key) {
|
|
392
126
|
super(key);
|
|
393
127
|
this.__src = src;
|
|
394
128
|
this.__altText = altText;
|
|
395
|
-
this.
|
|
396
|
-
this.
|
|
397
|
-
this.__height = height || 'inherit';
|
|
129
|
+
this.__width = width;
|
|
130
|
+
this.__height = height;
|
|
398
131
|
}
|
|
399
132
|
static getType() {
|
|
400
133
|
return 'image';
|
|
401
134
|
}
|
|
402
135
|
static clone(node) {
|
|
403
|
-
return new ImageNode(node.__src, node.__altText, node.
|
|
136
|
+
return new ImageNode(node.__src, node.__altText, node.__width, node.__height, node.__key);
|
|
404
137
|
}
|
|
405
138
|
setWidthAndHeight(width, height) {
|
|
406
139
|
const writable = this.getWritable();
|
|
@@ -434,24 +167,26 @@ class ImageNode extends lexical_1.DecoratorNode {
|
|
|
434
167
|
}) }, dom);
|
|
435
168
|
}
|
|
436
169
|
exportDOM() {
|
|
437
|
-
const
|
|
438
|
-
element.
|
|
439
|
-
element.setAttribute('
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
170
|
+
const aspectRatio = getAspectRatio(this.__width, this.__height);
|
|
171
|
+
const element = document.createElement('div');
|
|
172
|
+
element.setAttribute('style', `position: relative;padding-bottom:${100 / aspectRatio}%`);
|
|
173
|
+
const image = document.createElement('img');
|
|
174
|
+
image.setAttribute('src', this.__src);
|
|
175
|
+
image.setAttribute('alt', this.__altText);
|
|
176
|
+
image.setAttribute('style', `position: absolute;width:100%;height:100%;`);
|
|
177
|
+
image.setAttribute('data-width', `${this.__width}`);
|
|
178
|
+
image.setAttribute('data-height', `${this.__height}`);
|
|
179
|
+
element.appendChild(image);
|
|
443
180
|
return { element };
|
|
444
181
|
}
|
|
445
182
|
decorate() {
|
|
446
|
-
|
|
447
|
-
return (react_1.default.createElement(ImageComponent, { src: this.__src, altText: this.__altText, width: this.__width, height: this.__height, maxWidth: this.__maxWidth, nodeKey: this.getKey(), resizable: true }));
|
|
183
|
+
return react_1.default.createElement(ImageComponent, { src: this.__src, altText: this.__altText, width: this.__width, height: this.__height, nodeKey: this.getKey() });
|
|
448
184
|
}
|
|
449
185
|
static importJSON(serializedNode) {
|
|
450
|
-
const { altText, height, width,
|
|
186
|
+
const { altText, height, width, src } = serializedNode;
|
|
451
187
|
const node = $createImageNode({
|
|
452
188
|
altText,
|
|
453
189
|
height,
|
|
454
|
-
maxWidth,
|
|
455
190
|
src,
|
|
456
191
|
width
|
|
457
192
|
});
|
|
@@ -460,18 +195,17 @@ class ImageNode extends lexical_1.DecoratorNode {
|
|
|
460
195
|
exportJSON() {
|
|
461
196
|
return {
|
|
462
197
|
altText: this.getAltText(),
|
|
463
|
-
height: this.__height
|
|
464
|
-
maxWidth: this.__maxWidth,
|
|
198
|
+
height: this.__height,
|
|
465
199
|
src: this.getSrc(),
|
|
466
200
|
type: 'image',
|
|
467
201
|
version: 1,
|
|
468
|
-
width: this.__width
|
|
202
|
+
width: this.__width
|
|
469
203
|
};
|
|
470
204
|
}
|
|
471
205
|
}
|
|
472
206
|
exports.ImageNode = ImageNode;
|
|
473
|
-
function $createImageNode({ src, altText,
|
|
474
|
-
return new ImageNode(src, altText,
|
|
207
|
+
function $createImageNode({ src, altText, width, height }) {
|
|
208
|
+
return new ImageNode(src, altText, width, height);
|
|
475
209
|
}
|
|
476
210
|
exports.$createImageNode = $createImageNode;
|
|
477
211
|
function $isImageNode(node) {
|
|
@@ -94,7 +94,7 @@ function ImagePlugin() {
|
|
|
94
94
|
if ((0, lexical_1.$isRootNode)(selection.anchor.getNode())) {
|
|
95
95
|
selection.insertParagraph();
|
|
96
96
|
}
|
|
97
|
-
const imageNode = (0, ImageNode_1.$createImageNode)({ src: payload.src, altText: payload.altText,
|
|
97
|
+
const imageNode = (0, ImageNode_1.$createImageNode)({ src: payload.src, altText: payload.altText, width: payload.width, height: payload.height });
|
|
98
98
|
selection.insertNodes([imageNode]);
|
|
99
99
|
}
|
|
100
100
|
return true;
|
|
@@ -28,6 +28,7 @@ const PREFIX = 'SCFeed';
|
|
|
28
28
|
const classes = {
|
|
29
29
|
root: `${PREFIX}-root`,
|
|
30
30
|
left: `${PREFIX}-left`,
|
|
31
|
+
leftItems: `${PREFIX}-left-items`,
|
|
31
32
|
start: `${PREFIX}-start`,
|
|
32
33
|
end: `${PREFIX}-end`,
|
|
33
34
|
endMessage: `${PREFIX}-end-message`,
|
|
@@ -414,14 +415,14 @@ const Feed = (inProps, ref) => {
|
|
|
414
415
|
react_1.default.createElement(CustomAdv_1.default, Object.assign({ position: types_1.SCCustomAdvPosition.POSITION_BELOW_TOPBAR }, CustomAdvProps)))) : null,
|
|
415
416
|
react_1.default.createElement(material_1.Grid, { item: true, xs: 12, md: 7 },
|
|
416
417
|
react_1.default.createElement("div", { style: { overflow: 'visible' } },
|
|
417
|
-
react_1.default.createElement(InfiniteScroll_1.default, { className: classes.left, dataLength: feedDataLeft.length, next: getNextPage, previous: getPreviousPage, hasMoreNext: Boolean(feedDataObject.next), hasMorePrevious: Boolean(feedDataObject.previous), header: PreviousPageLink, footer: NextPageLink, loaderNext: react_1.default.createElement(ItemSkeleton, Object.assign({}, ItemSkeletonProps)), loaderPrevious: react_1.default.createElement(ItemSkeleton, Object.assign({}, ItemSkeletonProps)), scrollThreshold:
|
|
418
|
+
react_1.default.createElement(InfiniteScroll_1.default, { className: classes.left, dataLength: feedDataLeft.length, next: getNextPage, previous: getPreviousPage, hasMoreNext: Boolean(feedDataObject.next), hasMorePrevious: Boolean(feedDataObject.previous), header: PreviousPageLink, footer: NextPageLink, loaderNext: react_1.default.createElement(ItemSkeleton, Object.assign({}, ItemSkeletonProps)), loaderPrevious: react_1.default.createElement(ItemSkeleton, Object.assign({}, ItemSkeletonProps)), scrollThreshold: '80%', endMessage: react_1.default.createElement(material_1.Box, { className: classes.end },
|
|
418
419
|
react_1.default.createElement(Widget_1.default, { className: classes.endMessage },
|
|
419
420
|
react_1.default.createElement(material_1.CardContent, null, endMessage)),
|
|
420
421
|
advEnabled && !hideAdvs && enabledCustomAdvPositions.includes(types_1.SCCustomAdvPosition.POSITION_ABOVE_FOOTER_BAR) ? (react_1.default.createElement(CustomAdv_1.default, Object.assign({ position: types_1.SCCustomAdvPosition.POSITION_ABOVE_FOOTER_BAR }, CustomAdvProps))) : null,
|
|
421
422
|
FooterComponent ? react_1.default.createElement(FooterComponent, Object.assign({}, FooterComponentProps)) : null), refreshFunction: refresh, pullDownToRefresh: true, pullDownToRefreshThreshold: 1000, pullDownToRefreshContent: null, releaseToRefreshContent: react_1.default.createElement(Widget_1.default, { variant: "outlined", className: classes.refresh },
|
|
422
423
|
react_1.default.createElement(material_1.CardContent, null, refreshMessage)), style: { overflow: 'visible' } },
|
|
423
424
|
renderHeaderComponent(),
|
|
424
|
-
react_1.default.createElement(VirtualizedScroller_1.default, Object.assign({ items: feedDataLeft, itemComponent: InnerItem, onMount: onScrollerMount, onScrollerStateChange: onScrollerStateChange, getItemId: getScrollItemId, preserveScrollPosition: true, preserveScrollPositionOnPrependItems: true, cacheScrollStateKey: react_core_1.SCCache.getVirtualizedScrollStateCacheKey(id), cacheScrollerPositionKey: react_core_1.SCCache.getFeedSPCacheKey(id), cacheStrategy: cacheStrategy }, VirtualizedScrollerProps))))),
|
|
425
|
+
react_1.default.createElement(VirtualizedScroller_1.default, Object.assign({ className: classes.leftItems, items: feedDataLeft, itemComponent: InnerItem, onMount: onScrollerMount, onScrollerStateChange: onScrollerStateChange, getItemId: getScrollItemId, preserveScrollPosition: true, preserveScrollPositionOnPrependItems: true, cacheScrollStateKey: react_core_1.SCCache.getVirtualizedScrollStateCacheKey(id), cacheScrollerPositionKey: react_core_1.SCCache.getFeedSPCacheKey(id), cacheStrategy: cacheStrategy }, VirtualizedScrollerProps))))),
|
|
425
426
|
feedDataRight.length > 0 && !hideAdvs && (react_1.default.createElement(material_1.Hidden, { smDown: true },
|
|
426
427
|
react_1.default.createElement(material_1.Grid, { item: true, xs: 12, md: 5 },
|
|
427
428
|
react_1.default.createElement(StickyBox_1.default, Object.assign({ className: classes.right }, FeedSidebarProps),
|
|
@@ -16,7 +16,6 @@ import { LinkPlugin } from '@lexical/react/LexicalLinkPlugin';
|
|
|
16
16
|
import ApiPlugin from './plugins/ApiPlugin';
|
|
17
17
|
import ToolbarPlugin from './plugins/ToolbarPlugin';
|
|
18
18
|
import { ListPlugin } from '@lexical/react/LexicalListPlugin';
|
|
19
|
-
import useMediaQuery from '@mui/material/useMediaQuery';
|
|
20
19
|
import FloatingLinkPlugin from './plugins/FloatingLinkPlugin';
|
|
21
20
|
import OnBlurPlugin from './plugins/OnBlurPlugin';
|
|
22
21
|
import OnFocusPlugin from './plugins/OnFocusPlugin';
|
|
@@ -107,7 +106,6 @@ const Editor = (inProps, ref) => {
|
|
|
107
106
|
const apiRef = useRef();
|
|
108
107
|
// MEMO
|
|
109
108
|
const theme = useTheme();
|
|
110
|
-
const isMobile = useMediaQuery(theme.breakpoints.down('md'));
|
|
111
109
|
// HANDLERS
|
|
112
110
|
const handleChange = (value) => {
|
|
113
111
|
onChange && onChange(value);
|
|
@@ -3,33 +3,30 @@ import { DecoratorNode, DOMExportOutput, EditorConfig, LexicalNode, NodeKey, Ser
|
|
|
3
3
|
export interface ImagePayload {
|
|
4
4
|
altText: string;
|
|
5
5
|
className?: string;
|
|
6
|
-
height
|
|
6
|
+
height: number;
|
|
7
7
|
imageRef?: LegacyRef<HTMLImageElement>;
|
|
8
|
-
maxWidth: number | string;
|
|
9
8
|
src: string;
|
|
10
|
-
width
|
|
9
|
+
width: number;
|
|
11
10
|
}
|
|
12
11
|
declare function convertImageElement(domNode: any): {
|
|
13
12
|
node: ImageNode;
|
|
14
13
|
};
|
|
15
14
|
export declare type SerializedImageNode = Spread<{
|
|
16
15
|
altText: string;
|
|
17
|
-
height
|
|
18
|
-
maxWidth: number | string;
|
|
16
|
+
height: number;
|
|
19
17
|
src: string;
|
|
20
|
-
width
|
|
18
|
+
width: number;
|
|
21
19
|
type: 'image';
|
|
22
20
|
version: 1;
|
|
23
21
|
}, SerializedLexicalNode>;
|
|
24
22
|
export declare class ImageNode extends DecoratorNode<JSX.Element> {
|
|
25
23
|
__src: string;
|
|
26
24
|
__altText: string;
|
|
27
|
-
__width:
|
|
28
|
-
__height:
|
|
29
|
-
__maxWidth: number | string;
|
|
25
|
+
__width: number;
|
|
26
|
+
__height: number;
|
|
30
27
|
static getType(): string;
|
|
31
28
|
static clone(node: ImageNode): ImageNode;
|
|
32
|
-
constructor(src: string, altText: string,
|
|
29
|
+
constructor(src: string, altText: string, width: number, height: number, key?: NodeKey);
|
|
33
30
|
setWidthAndHeight(width: 'inherit' | number, height: 'inherit' | number): void;
|
|
34
31
|
createDOM(config: EditorConfig): HTMLElement;
|
|
35
32
|
updateDOM(): false;
|
|
@@ -44,6 +41,6 @@ export declare class ImageNode extends DecoratorNode<JSX.Element> {
|
|
|
44
41
|
static importJSON(serializedNode: SerializedImageNode): ImageNode;
|
|
45
42
|
exportJSON(): SerializedImageNode;
|
|
46
43
|
}
|
|
47
|
-
export declare function $createImageNode({ src, altText,
|
|
44
|
+
export declare function $createImageNode({ src, altText, width, height }: ImagePayload): ImageNode;
|
|
48
45
|
export declare function $isImageNode(node?: LexicalNode): boolean;
|
|
49
46
|
export {};
|