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