@flozy/editor 11.2.2 → 11.2.4
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/ChatEditor.js +7 -7
- package/dist/Editor/CommonEditor.js +86 -24
- package/dist/Editor/DialogWrapper.js +31 -25
- package/dist/Editor/Editor.css +37 -4
- package/dist/Editor/Elements/AI/PopoverAIInput.js +11 -3
- package/dist/Editor/Elements/AppHeader/AppHeader.js +3 -3
- package/dist/Editor/Elements/Attachments/AttachmentStyles.js +16 -0
- package/dist/Editor/Elements/Attachments/Attachments.js +239 -11
- package/dist/Editor/Elements/Attachments/AttachmentsButton.js +11 -4
- package/dist/Editor/Elements/Button/EditorButton.js +22 -7
- package/dist/Editor/Elements/Color Picker/ColorButtons.js +61 -14
- package/dist/Editor/Elements/Color Picker/ColorPicker.css +25 -1
- package/dist/Editor/Elements/Color Picker/ColorPicker.js +10 -7
- package/dist/Editor/Elements/Color Picker/Styles.js +15 -13
- package/dist/Editor/Elements/DataView/Layouts/DataTypes/Components/Select.js +134 -55
- package/dist/Editor/Elements/DataView/Layouts/DataTypes/Components/SelectV1.js +7 -8
- package/dist/Editor/Elements/DataView/Layouts/DataTypes/PersonType.js +8 -3
- package/dist/Editor/Elements/DataView/Layouts/Options/EditProperty.js +1 -1
- package/dist/Editor/Elements/DataView/Layouts/TableStyles.js +1 -1
- package/dist/Editor/Elements/Embed/Embed.js +37 -43
- package/dist/Editor/Elements/Embed/Image.js +307 -26
- package/dist/Editor/Elements/Embed/Video.js +355 -35
- package/dist/Editor/Elements/EmbedScript/EmbedScriptPopup.js +9 -6
- package/dist/Editor/Elements/EmbedScript/styles.js +17 -1
- package/dist/Editor/Elements/Form/FormField.js +1 -1
- package/dist/Editor/Elements/Form/Workflow/Styles.js +25 -22
- package/dist/Editor/Elements/Form/Workflow/constant.js +25 -1
- package/dist/Editor/Elements/FreeGrid/FreeGrid.js +37 -76
- package/dist/Editor/Elements/FreeGrid/FreeGridBox.js +9 -5
- package/dist/Editor/Elements/FreeGrid/FreeGridItem.js +3 -1
- package/dist/Editor/Elements/FreeGrid/helper.js +194 -0
- package/dist/Editor/Elements/FreeGrid/styles.js +15 -0
- package/dist/Editor/Elements/Grid/GridItem.js +1 -1
- package/dist/Editor/Elements/PageSettings/PageSettingsButton.js +2 -1
- package/dist/Editor/Elements/Table/Table.js +2 -1
- package/dist/Editor/Elements/Table/TableCell.js +10 -3
- package/dist/Editor/Elements/Title/title.js +4 -5
- package/dist/Editor/Elements/TopBanner/TopBanner.js +4 -2
- package/dist/Editor/Elements/TopBanner/TopBannerButton.js +5 -3
- package/dist/Editor/Styles/EditorStyles.js +19 -5
- package/dist/Editor/Toolbar/FormatTools/Dropdown.js +27 -3
- package/dist/Editor/Toolbar/FormatTools/FontFamilyAutocomplete.js +4 -3
- package/dist/Editor/Toolbar/FormatTools/MarkButton.js +2 -2
- package/dist/Editor/Toolbar/FormatTools/TextSize.js +33 -29
- package/dist/Editor/Toolbar/Mini/MiniToolbar.js +2 -1
- package/dist/Editor/Toolbar/PopupTool/MiniTextFormat/MiniColorPicker.js +3 -1
- package/dist/Editor/Toolbar/PopupTool/MiniTextFormat/SelectFontSize.js +25 -23
- package/dist/Editor/Toolbar/PopupTool/MiniTextFormat/SelectTypography.js +167 -42
- package/dist/Editor/Toolbar/PopupTool/MiniTextFormat/index.js +15 -5
- package/dist/Editor/Toolbar/PopupTool/PopperHeader.js +2 -1
- package/dist/Editor/Toolbar/PopupTool/PopupToolStyle.js +65 -7
- package/dist/Editor/Toolbar/PopupTool/TextFormat.js +66 -12
- package/dist/Editor/Toolbar/PopupTool/ThemeTextFormat.js +439 -0
- package/dist/Editor/Toolbar/PopupTool/index.js +6 -4
- package/dist/Editor/Toolbar/toolbarGroups.js +48 -6
- package/dist/Editor/assets/svg/BackIcon.js +18 -0
- package/dist/Editor/assets/svg/ThemeIcons.js +293 -0
- package/dist/Editor/common/ColorPickerButton.js +38 -19
- package/dist/Editor/common/CustomColorPicker/index.js +130 -0
- package/dist/Editor/common/CustomColorPicker/style.js +53 -0
- package/dist/Editor/common/CustomDialog2/index.js +94 -0
- package/dist/Editor/common/CustomDialog2/style.js +67 -0
- package/dist/Editor/common/CustomSelect.js +43 -0
- package/dist/Editor/common/DnD/DragHandleButton.js +1 -1
- package/dist/Editor/common/FontLoader/FontLoader.js +1 -0
- package/dist/Editor/common/Icon.js +28 -0
- package/dist/Editor/common/ImageSelector/ImageSelector.js +66 -13
- package/dist/Editor/common/ImageSelector/Options/ChooseAssets.js +1 -1
- package/dist/Editor/common/ImageSelector/Options/RecentUploads.js +483 -0
- package/dist/Editor/common/ImageSelector/Options/Upload.js +26 -11
- package/dist/Editor/common/ImageSelector/Styles.js +3 -9
- package/dist/Editor/common/RnD/ElementSettings/OtherSettings/Settings.js +2 -1
- package/dist/Editor/common/RnD/ElementSettings/Settings/AppHeaderSettings.js +3 -2
- package/dist/Editor/common/RnD/ElementSettings/Settings/BoxSettings.js +3 -2
- package/dist/Editor/common/RnD/ElementSettings/Settings/ButtonSettings.js +3 -2
- package/dist/Editor/common/RnD/ElementSettings/Settings/CodeSettings.js +3 -2
- package/dist/Editor/common/RnD/ElementSettings/Settings/FormSettings.js +3 -2
- package/dist/Editor/common/RnD/ElementSettings/Settings/ImageSettings.js +20 -7
- package/dist/Editor/common/RnD/ElementSettings/Settings/TableSettings.js +3 -2
- package/dist/Editor/common/RnD/ElementSettings/Settings/TextSettings.js +2 -0
- package/dist/Editor/common/RnD/ElementSettings/Settings/VideoSettings.js +20 -7
- package/dist/Editor/common/RnD/GuideLines/styles.js +1 -1
- package/dist/Editor/common/RnD/Theme/MainThemeProvider.js +17 -0
- package/dist/Editor/common/RnD/Theme/ViewportStimulator.js +6 -3
- package/dist/Editor/common/RnD/Utils/gridDropItem.js +28 -11
- package/dist/Editor/common/RnD/Utils/index.js +3 -1
- package/dist/Editor/common/RnD/VirtualElement/VirtualTextElement.js +52 -63
- package/dist/Editor/common/RnD/VirtualElement/helper.js +248 -68
- package/dist/Editor/common/RnD/VirtualElement/styles.js +22 -0
- package/dist/Editor/common/RnD/index.js +61 -14
- package/dist/Editor/common/Shorthands/elements.js +55 -3
- package/dist/Editor/common/StyleBuilder/buttonStyle.js +4 -2
- package/dist/Editor/common/StyleBuilder/embedVideoStyle.js +4 -0
- package/dist/Editor/common/StyleBuilder/fieldStyle.js +1 -0
- package/dist/Editor/common/StyleBuilder/fieldTypes/backgroundImage.js +13 -3
- package/dist/Editor/common/StyleBuilder/fieldTypes/bannerSpacing.js +12 -2
- package/dist/Editor/common/StyleBuilder/fieldTypes/borderRadius.js +15 -7
- package/dist/Editor/common/StyleBuilder/fieldTypes/color.js +36 -10
- package/dist/Editor/common/StyleBuilder/fieldTypes/fontSize.js +13 -4
- package/dist/Editor/common/StyleBuilder/fieldTypes/menusArray.js +2 -0
- package/dist/Editor/common/StyleBuilder/fieldTypes/text.js +16 -4
- package/dist/Editor/common/StyleBuilder/fieldTypes/textOptions.js +15 -7
- package/dist/Editor/common/StyleBuilder/formStyle.js +19 -13
- package/dist/Editor/common/StyleBuilder/index.js +8 -4
- package/dist/Editor/common/Uploader.js +118 -17
- package/dist/Editor/common/UploaderWithProgress.js +183 -0
- package/dist/Editor/common/iconslist.js +21 -0
- package/dist/Editor/commonStyle.js +111 -53
- package/dist/Editor/helper/index.js +4 -1
- package/dist/Editor/helper/theme.js +203 -2
- package/dist/Editor/hooks/useEditorTheme.js +153 -0
- package/dist/Editor/hooks/useMouseMove.js +12 -3
- package/dist/Editor/hooks/useTable.js +62 -1
- package/dist/Editor/hooks/useThemeValues.js +63 -0
- package/dist/Editor/plugins/withEmbeds.js +1 -1
- package/dist/Editor/plugins/withHTML.js +56 -3
- package/dist/Editor/plugins/withTable.js +1 -1
- package/dist/Editor/service/fileTracking.js +22 -0
- package/dist/Editor/service/fileupload.js +77 -0
- package/dist/Editor/theme/ThemeList.js +50 -173
- package/dist/Editor/theme/index.js +149 -0
- package/dist/Editor/themeSettings/ActiveTheme.js +82 -0
- package/dist/Editor/themeSettings/buttons/index.js +300 -0
- package/dist/Editor/themeSettings/buttons/style.js +23 -0
- package/dist/Editor/themeSettings/colorTheme/index.js +310 -0
- package/dist/Editor/themeSettings/colorTheme/style.js +81 -0
- package/dist/Editor/themeSettings/fonts/PreviewElement.js +121 -0
- package/dist/Editor/themeSettings/fonts/index.js +240 -0
- package/dist/Editor/themeSettings/fonts/style.js +62 -0
- package/dist/Editor/themeSettings/icons.js +60 -0
- package/dist/Editor/themeSettings/index.js +380 -0
- package/dist/Editor/themeSettings/style.js +299 -0
- package/dist/Editor/themeSettingsAI/icons.js +96 -0
- package/dist/Editor/themeSettingsAI/index.js +355 -0
- package/dist/Editor/themeSettingsAI/saveTheme.js +202 -0
- package/dist/Editor/themeSettingsAI/style.js +332 -0
- package/dist/Editor/utils/SlateUtilityFunctions.js +165 -40
- package/dist/Editor/utils/accordion.js +1 -1
- package/dist/Editor/utils/attachments.js +138 -2
- package/dist/Editor/utils/button.js +1 -17
- package/dist/Editor/utils/font.js +40 -37
- package/dist/Editor/utils/formfield.js +2 -2
- package/dist/Editor/utils/helper.js +101 -3
- package/dist/Editor/utils/insertAppHeader.js +8 -4
- package/package.json +1 -1
|
@@ -0,0 +1,483 @@
|
|
|
1
|
+
import React, { useEffect, useState, useCallback, useRef, useMemo } from "react";
|
|
2
|
+
import { Box, Grid, Typography, CircularProgress, ImageListItem, ImageListItemBar, IconButton } from "@mui/material";
|
|
3
|
+
import CheckCircleIcon from '@mui/icons-material/CheckCircle';
|
|
4
|
+
import { useEditorContext } from "../../../hooks/useMouseMove";
|
|
5
|
+
|
|
6
|
+
// Memoized RecentItem component to prevent unnecessary re-renders
|
|
7
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
8
|
+
import { jsxs as _jsxs } from "react/jsx-runtime";
|
|
9
|
+
const RecentItem = /*#__PURE__*/React.memo(({
|
|
10
|
+
item,
|
|
11
|
+
iconRef,
|
|
12
|
+
onSelect,
|
|
13
|
+
theme
|
|
14
|
+
}) => {
|
|
15
|
+
// Simple lazy loading image component
|
|
16
|
+
const LazyImage = /*#__PURE__*/React.memo(({
|
|
17
|
+
src,
|
|
18
|
+
alt,
|
|
19
|
+
...props
|
|
20
|
+
}) => {
|
|
21
|
+
const [isLoaded, setIsLoaded] = useState(false);
|
|
22
|
+
const [isInView, setIsInView] = useState(false);
|
|
23
|
+
const imgRef = useRef();
|
|
24
|
+
useEffect(() => {
|
|
25
|
+
const observer = new IntersectionObserver(([entry]) => {
|
|
26
|
+
if (entry.isIntersecting) {
|
|
27
|
+
setIsInView(true);
|
|
28
|
+
observer.disconnect();
|
|
29
|
+
}
|
|
30
|
+
}, {
|
|
31
|
+
threshold: 0.1
|
|
32
|
+
});
|
|
33
|
+
if (imgRef.current) {
|
|
34
|
+
observer.observe(imgRef.current);
|
|
35
|
+
}
|
|
36
|
+
return () => observer.disconnect();
|
|
37
|
+
}, []);
|
|
38
|
+
const {
|
|
39
|
+
sx,
|
|
40
|
+
...restProps
|
|
41
|
+
} = props;
|
|
42
|
+
return /*#__PURE__*/_jsxs(Box, {
|
|
43
|
+
ref: imgRef,
|
|
44
|
+
...restProps,
|
|
45
|
+
sx: {
|
|
46
|
+
...sx,
|
|
47
|
+
position: 'relative',
|
|
48
|
+
overflow: 'hidden'
|
|
49
|
+
},
|
|
50
|
+
children: [isInView && /*#__PURE__*/_jsx(Box, {
|
|
51
|
+
component: "img",
|
|
52
|
+
src: src,
|
|
53
|
+
alt: alt,
|
|
54
|
+
onLoad: () => setIsLoaded(true),
|
|
55
|
+
sx: {
|
|
56
|
+
width: '100%',
|
|
57
|
+
height: '100%',
|
|
58
|
+
objectFit: sx?.objectFit || 'cover',
|
|
59
|
+
borderRadius: sx?.borderRadius || 0,
|
|
60
|
+
opacity: isLoaded ? 1 : 0,
|
|
61
|
+
transition: 'opacity 0.3s ease-in-out',
|
|
62
|
+
willChange: 'opacity'
|
|
63
|
+
}
|
|
64
|
+
}), !isLoaded && isInView && /*#__PURE__*/_jsx(Box, {
|
|
65
|
+
sx: {
|
|
66
|
+
position: 'absolute',
|
|
67
|
+
top: 0,
|
|
68
|
+
left: 0,
|
|
69
|
+
right: 0,
|
|
70
|
+
bottom: 0,
|
|
71
|
+
backgroundColor: 'grey.100',
|
|
72
|
+
display: 'flex',
|
|
73
|
+
alignItems: 'center',
|
|
74
|
+
justifyContent: 'center',
|
|
75
|
+
borderRadius: sx?.borderRadius || 0
|
|
76
|
+
},
|
|
77
|
+
children: /*#__PURE__*/_jsx(CircularProgress, {
|
|
78
|
+
size: 24
|
|
79
|
+
})
|
|
80
|
+
})]
|
|
81
|
+
});
|
|
82
|
+
}, (prevProps, nextProps) => {
|
|
83
|
+
// Only re-render if src changes
|
|
84
|
+
return prevProps.src === nextProps.src && prevProps.alt === nextProps.alt;
|
|
85
|
+
});
|
|
86
|
+
LazyImage.displayName = 'LazyImage';
|
|
87
|
+
return /*#__PURE__*/_jsx(Grid, {
|
|
88
|
+
item: true,
|
|
89
|
+
xs: 4,
|
|
90
|
+
sx: {
|
|
91
|
+
cursor: "pointer",
|
|
92
|
+
"&:hover": {
|
|
93
|
+
opacity: 0.8
|
|
94
|
+
}
|
|
95
|
+
},
|
|
96
|
+
children: /*#__PURE__*/_jsxs(ImageListItem, {
|
|
97
|
+
sx: {
|
|
98
|
+
padding: "2px",
|
|
99
|
+
overflow: "hidden"
|
|
100
|
+
},
|
|
101
|
+
children: [(item.type === "image" || item.category === "IMAGE") && /*#__PURE__*/_jsx(LazyImage, {
|
|
102
|
+
src: item.file_url || item.url,
|
|
103
|
+
alt: item.name,
|
|
104
|
+
sx: {
|
|
105
|
+
width: "100%",
|
|
106
|
+
height: 145,
|
|
107
|
+
objectFit: "cover",
|
|
108
|
+
borderRadius: 1
|
|
109
|
+
}
|
|
110
|
+
}), (item.type === "video" || item.category === "VIDEO") && /*#__PURE__*/_jsx(Box, {
|
|
111
|
+
component: "video",
|
|
112
|
+
src: item.file_url || item.url,
|
|
113
|
+
sx: {
|
|
114
|
+
width: "100%",
|
|
115
|
+
height: 145,
|
|
116
|
+
borderRadius: 1,
|
|
117
|
+
objectFit: "cover"
|
|
118
|
+
}
|
|
119
|
+
}), (item.type === "document" || item.category === "DOCUMENT") && /*#__PURE__*/_jsxs(Box, {
|
|
120
|
+
sx: {
|
|
121
|
+
p: 2,
|
|
122
|
+
border: 1,
|
|
123
|
+
borderColor: theme?.palette?.editor?.uploadFileBorder || "#F3F3F3",
|
|
124
|
+
borderRadius: 1,
|
|
125
|
+
textAlign: "center",
|
|
126
|
+
height: 145,
|
|
127
|
+
display: "flex",
|
|
128
|
+
flexDirection: "column",
|
|
129
|
+
alignItems: "center",
|
|
130
|
+
justifyContent: "center",
|
|
131
|
+
backgroundColor: theme?.palette?.editor?.uploadFileBg || "#F3F3F3"
|
|
132
|
+
},
|
|
133
|
+
children: [/*#__PURE__*/_jsx(Typography, {
|
|
134
|
+
sx: {
|
|
135
|
+
fontSize: "24px",
|
|
136
|
+
mb: 1,
|
|
137
|
+
color: theme?.palette?.editor?.textColor || "#000000"
|
|
138
|
+
},
|
|
139
|
+
children: "\uD83D\uDCC4"
|
|
140
|
+
}), /*#__PURE__*/_jsx(Typography, {
|
|
141
|
+
sx: {
|
|
142
|
+
fontSize: "12px",
|
|
143
|
+
fontWeight: 500,
|
|
144
|
+
color: theme?.palette?.editor?.textColor || "#000000",
|
|
145
|
+
textAlign: "center",
|
|
146
|
+
wordBreak: "break-word",
|
|
147
|
+
lineHeight: 1.2,
|
|
148
|
+
maxHeight: "60px",
|
|
149
|
+
overflow: "hidden",
|
|
150
|
+
display: "-webkit-box",
|
|
151
|
+
WebkitLineClamp: 3,
|
|
152
|
+
WebkitBoxOrient: "vertical"
|
|
153
|
+
},
|
|
154
|
+
children: item.name || 'Untitled Document'
|
|
155
|
+
})]
|
|
156
|
+
}), /*#__PURE__*/_jsx(ImageListItemBar, {
|
|
157
|
+
sx: {
|
|
158
|
+
background: "none",
|
|
159
|
+
"& .MuiImageListItemBar-actionIcon": {
|
|
160
|
+
position: "absolute",
|
|
161
|
+
top: 8,
|
|
162
|
+
right: 8,
|
|
163
|
+
zIndex: 1
|
|
164
|
+
}
|
|
165
|
+
},
|
|
166
|
+
position: "top",
|
|
167
|
+
actionPosition: "right",
|
|
168
|
+
actionIcon: /*#__PURE__*/_jsx(IconButton, {
|
|
169
|
+
onClick: e => {
|
|
170
|
+
e.stopPropagation();
|
|
171
|
+
onSelect(item);
|
|
172
|
+
},
|
|
173
|
+
sx: {
|
|
174
|
+
transition: 'none',
|
|
175
|
+
'&:hover': {
|
|
176
|
+
backgroundColor: 'transparent'
|
|
177
|
+
}
|
|
178
|
+
},
|
|
179
|
+
children: /*#__PURE__*/_jsx(CheckCircleIcon, {
|
|
180
|
+
ref: iconRef,
|
|
181
|
+
sx: {
|
|
182
|
+
color: "#ccc",
|
|
183
|
+
transition: 'color 0.15s ease-in-out',
|
|
184
|
+
willChange: 'color'
|
|
185
|
+
}
|
|
186
|
+
})
|
|
187
|
+
})
|
|
188
|
+
})]
|
|
189
|
+
})
|
|
190
|
+
});
|
|
191
|
+
}, (prevProps, nextProps) => {
|
|
192
|
+
// Strict comparison function for React.memo
|
|
193
|
+
// Return true if props are equal (don't re-render), false if different (re-render)
|
|
194
|
+
// Note: iconRef is ignored as it's stable and doesn't cause re-renders
|
|
195
|
+
|
|
196
|
+
// Compare item properties - use strict equality for object reference first
|
|
197
|
+
if (prevProps.item !== nextProps.item) {
|
|
198
|
+
// If item reference changed, check if properties are the same
|
|
199
|
+
if (prevProps.item.id !== nextProps.item.id || prevProps.item.file_url !== nextProps.item.file_url || prevProps.item.url !== nextProps.item.url || prevProps.item.name !== nextProps.item.name || prevProps.item.type !== nextProps.item.type || prevProps.item.category !== nextProps.item.category) {
|
|
200
|
+
return false; // Re-render needed
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// Compare other props (iconRef is ignored as it's stable)
|
|
205
|
+
return prevProps.onSelect === nextProps.onSelect && prevProps.theme === nextProps.theme;
|
|
206
|
+
});
|
|
207
|
+
RecentItem.displayName = 'RecentItem';
|
|
208
|
+
const RecentUploads = ({
|
|
209
|
+
onUploaded,
|
|
210
|
+
customProps,
|
|
211
|
+
title
|
|
212
|
+
}) => {
|
|
213
|
+
const {
|
|
214
|
+
theme
|
|
215
|
+
} = useEditorContext();
|
|
216
|
+
// Memoize theme to prevent unnecessary re-renders if theme object reference changes
|
|
217
|
+
const stableTheme = useMemo(() => theme, [theme]);
|
|
218
|
+
const [recent, setRecent] = useState([]);
|
|
219
|
+
const [loading, setLoading] = useState(true);
|
|
220
|
+
const [loadingMore, setLoadingMore] = useState(false);
|
|
221
|
+
const [selectedUrl, setSelectedUrl] = useState(null);
|
|
222
|
+
const [pagination, setPagination] = useState({
|
|
223
|
+
total: 0,
|
|
224
|
+
limit: 20,
|
|
225
|
+
offset: 0
|
|
226
|
+
});
|
|
227
|
+
const observerRef = useRef();
|
|
228
|
+
const loadMoreRef = useRef();
|
|
229
|
+
|
|
230
|
+
// Use ref to track selected URL without causing re-renders for comparison
|
|
231
|
+
const selectedUrlRef = useRef(null);
|
|
232
|
+
|
|
233
|
+
// Ref map to track icon refs for each item URL - allows imperative updates without re-renders
|
|
234
|
+
const iconRefsMap = useRef(new Map());
|
|
235
|
+
|
|
236
|
+
// Memoize onUploaded callback to ensure it doesn't change
|
|
237
|
+
const stableOnUploaded = useCallback((url, source) => {
|
|
238
|
+
onUploaded(url, source);
|
|
239
|
+
}, [onUploaded]);
|
|
240
|
+
|
|
241
|
+
// Category mapping
|
|
242
|
+
const categoryMap = {
|
|
243
|
+
'image': 'IMAGE',
|
|
244
|
+
'video': 'VIDEO',
|
|
245
|
+
'document': 'DOCUMENT'
|
|
246
|
+
};
|
|
247
|
+
const fetchRecent = useCallback(async (offset = 0, append = false) => {
|
|
248
|
+
try {
|
|
249
|
+
const category = categoryMap[title] || title.toLowerCase();
|
|
250
|
+
|
|
251
|
+
// Try main app service first, fallback to direct implementation
|
|
252
|
+
let res;
|
|
253
|
+
if (customProps.services && typeof customProps.services === 'function') {
|
|
254
|
+
try {
|
|
255
|
+
res = await customProps.services('getRecentUploads', {
|
|
256
|
+
category,
|
|
257
|
+
limit: pagination.limit,
|
|
258
|
+
offset
|
|
259
|
+
});
|
|
260
|
+
} catch (error) {
|
|
261
|
+
console.warn('Main app service failed, falling back to direct API call:', error);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
// Handle validation errors from getRecentUploads
|
|
266
|
+
if (res && res.error) {
|
|
267
|
+
console.warn("Recent uploads validation error:", res.error);
|
|
268
|
+
if (!append) {
|
|
269
|
+
setRecent([]);
|
|
270
|
+
setPagination({
|
|
271
|
+
total: 0,
|
|
272
|
+
limit: 20,
|
|
273
|
+
offset: 0
|
|
274
|
+
});
|
|
275
|
+
}
|
|
276
|
+
} else if (res) {
|
|
277
|
+
// Handle both direct data array and nested data structure
|
|
278
|
+
const dataArray = res.data?.data || res.data || [];
|
|
279
|
+
const paginationData = res.data?.pagination || res.pagination || {
|
|
280
|
+
total: res.data?.total || res.total || 0,
|
|
281
|
+
limit: 20,
|
|
282
|
+
offset: 0,
|
|
283
|
+
hasMore: res.data?.hasMore || false
|
|
284
|
+
};
|
|
285
|
+
console.log("RecentUploads - Processing response:", {
|
|
286
|
+
res,
|
|
287
|
+
dataArray,
|
|
288
|
+
paginationData,
|
|
289
|
+
dataArrayLength: dataArray.length
|
|
290
|
+
});
|
|
291
|
+
if (append) {
|
|
292
|
+
setRecent(prev => [...prev, ...dataArray]);
|
|
293
|
+
} else {
|
|
294
|
+
setRecent(dataArray);
|
|
295
|
+
}
|
|
296
|
+
setPagination(paginationData);
|
|
297
|
+
}
|
|
298
|
+
} catch (err) {
|
|
299
|
+
console.error("Failed to fetch recent uploads", err);
|
|
300
|
+
if (!append) {
|
|
301
|
+
setRecent([]);
|
|
302
|
+
setPagination({
|
|
303
|
+
total: 0,
|
|
304
|
+
limit: 20,
|
|
305
|
+
offset: 0
|
|
306
|
+
});
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
}, [customProps, title, pagination.limit, categoryMap]);
|
|
310
|
+
const loadMore = useCallback(() => {
|
|
311
|
+
const hasMore = recent.length < pagination.total;
|
|
312
|
+
if (!loadingMore && hasMore) {
|
|
313
|
+
setLoadingMore(true);
|
|
314
|
+
fetchRecent(pagination.offset + pagination.limit, true).finally(() => {
|
|
315
|
+
setLoadingMore(false);
|
|
316
|
+
});
|
|
317
|
+
}
|
|
318
|
+
}, [loadingMore, recent.length, pagination.total, pagination.offset, pagination.limit, fetchRecent]);
|
|
319
|
+
useEffect(() => {
|
|
320
|
+
setLoading(true);
|
|
321
|
+
fetchRecent(0, false).finally(() => {
|
|
322
|
+
setLoading(false);
|
|
323
|
+
});
|
|
324
|
+
}, [customProps, title]);
|
|
325
|
+
|
|
326
|
+
// Intersection observer for infinite scroll
|
|
327
|
+
useEffect(() => {
|
|
328
|
+
if (observerRef.current) {
|
|
329
|
+
observerRef.current.disconnect();
|
|
330
|
+
}
|
|
331
|
+
const hasMore = recent.length < pagination.total;
|
|
332
|
+
observerRef.current = new IntersectionObserver(entries => {
|
|
333
|
+
if (entries[0].isIntersecting && hasMore && !loadingMore) {
|
|
334
|
+
loadMore();
|
|
335
|
+
}
|
|
336
|
+
}, {
|
|
337
|
+
threshold: 0.1
|
|
338
|
+
});
|
|
339
|
+
if (loadMoreRef.current) {
|
|
340
|
+
observerRef.current.observe(loadMoreRef.current);
|
|
341
|
+
}
|
|
342
|
+
return () => {
|
|
343
|
+
if (observerRef.current) {
|
|
344
|
+
observerRef.current.disconnect();
|
|
345
|
+
}
|
|
346
|
+
};
|
|
347
|
+
}, [recent.length, pagination.total, loadingMore, loadMore]);
|
|
348
|
+
const hasMoreContent = recent.length < pagination.total && !loadingMore;
|
|
349
|
+
|
|
350
|
+
// Memoize recent array reference - only recreate if length or item IDs change
|
|
351
|
+
// This ensures stableRecent only changes when items actually change
|
|
352
|
+
const recentKey = useMemo(() => {
|
|
353
|
+
return recent.length > 0 ? `${recent.length}-${recent.map(item => item.id).join('-')}` : 'empty';
|
|
354
|
+
}, [recent]);
|
|
355
|
+
|
|
356
|
+
// Stable recent array - only changes when items actually change
|
|
357
|
+
const stableRecent = useMemo(() => recent, [recentKey]);
|
|
358
|
+
const handleItemSelect = useCallback(item => {
|
|
359
|
+
const imgUrl = item.file_url || item.url;
|
|
360
|
+
const prevSelectedUrl = selectedUrlRef.current;
|
|
361
|
+
|
|
362
|
+
// Update previously selected icon to gray (if any)
|
|
363
|
+
if (prevSelectedUrl && prevSelectedUrl !== imgUrl) {
|
|
364
|
+
const prevIconRef = iconRefsMap.current.get(prevSelectedUrl);
|
|
365
|
+
if (prevIconRef?.current) {
|
|
366
|
+
prevIconRef.current.style.color = "#ccc";
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
// Update newly selected icon to blue
|
|
371
|
+
const newIconRef = iconRefsMap.current.get(imgUrl);
|
|
372
|
+
if (newIconRef?.current) {
|
|
373
|
+
newIconRef.current.style.color = "#2563eb";
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
// Update ref immediately
|
|
377
|
+
selectedUrlRef.current = imgUrl;
|
|
378
|
+
|
|
379
|
+
// Update state only for external tracking (doesn't cause re-renders of items)
|
|
380
|
+
setSelectedUrl(imgUrl);
|
|
381
|
+
|
|
382
|
+
// Immediately call onUploaded to enable the Save button
|
|
383
|
+
// Pass "recent" as the source to indicate this is from recent uploads
|
|
384
|
+
stableOnUploaded(imgUrl, "recent");
|
|
385
|
+
}, [stableOnUploaded]);
|
|
386
|
+
|
|
387
|
+
// Initialize icon refs when items change
|
|
388
|
+
useEffect(() => {
|
|
389
|
+
stableRecent.forEach(item => {
|
|
390
|
+
const imgUrl = item.file_url || item.url;
|
|
391
|
+
if (!iconRefsMap.current.has(imgUrl)) {
|
|
392
|
+
iconRefsMap.current.set(imgUrl, /*#__PURE__*/React.createRef());
|
|
393
|
+
}
|
|
394
|
+
});
|
|
395
|
+
}, [stableRecent]);
|
|
396
|
+
|
|
397
|
+
// Update icon colors when selection changes (without re-rendering components)
|
|
398
|
+
useEffect(() => {
|
|
399
|
+
iconRefsMap.current.forEach((iconRef, imgUrl) => {
|
|
400
|
+
if (iconRef?.current) {
|
|
401
|
+
iconRef.current.style.color = selectedUrl === imgUrl ? "#2563eb" : "#ccc";
|
|
402
|
+
}
|
|
403
|
+
});
|
|
404
|
+
}, [selectedUrl]);
|
|
405
|
+
if (loading) return /*#__PURE__*/_jsx(Box, {
|
|
406
|
+
sx: {
|
|
407
|
+
display: 'flex',
|
|
408
|
+
justifyContent: 'center',
|
|
409
|
+
mt: 2
|
|
410
|
+
},
|
|
411
|
+
children: /*#__PURE__*/_jsx(CircularProgress, {
|
|
412
|
+
size: 24,
|
|
413
|
+
sx: {
|
|
414
|
+
color: stableTheme?.palette?.editor?.activeColor || "#2563EB"
|
|
415
|
+
}
|
|
416
|
+
})
|
|
417
|
+
});
|
|
418
|
+
console.log("RecentUploads - Rendering state:", {
|
|
419
|
+
recent,
|
|
420
|
+
recentLength: recent.length,
|
|
421
|
+
pagination,
|
|
422
|
+
title,
|
|
423
|
+
selectedUrl
|
|
424
|
+
});
|
|
425
|
+
if (!recent.length) return /*#__PURE__*/_jsxs(Typography, {
|
|
426
|
+
sx: {
|
|
427
|
+
textAlign: "center",
|
|
428
|
+
mt: 2,
|
|
429
|
+
color: stableTheme?.palette?.editor?.textColor || "#000000",
|
|
430
|
+
fontSize: "14px",
|
|
431
|
+
fontWeight: 500
|
|
432
|
+
},
|
|
433
|
+
children: ["No recent ", title.toLowerCase(), " found."]
|
|
434
|
+
});
|
|
435
|
+
return /*#__PURE__*/_jsxs(Box, {
|
|
436
|
+
children: [/*#__PURE__*/_jsx(Grid, {
|
|
437
|
+
container: true,
|
|
438
|
+
spacing: 2,
|
|
439
|
+
sx: {
|
|
440
|
+
mt: 1
|
|
441
|
+
},
|
|
442
|
+
children: stableRecent.map(item => {
|
|
443
|
+
const imgUrl = item.file_url || item.url;
|
|
444
|
+
// Get or create ref (should already exist from useEffect, but fallback for safety)
|
|
445
|
+
if (!iconRefsMap.current.has(imgUrl)) {
|
|
446
|
+
iconRefsMap.current.set(imgUrl, /*#__PURE__*/React.createRef());
|
|
447
|
+
}
|
|
448
|
+
return /*#__PURE__*/_jsx(RecentItem, {
|
|
449
|
+
item: item,
|
|
450
|
+
iconRef: iconRefsMap.current.get(imgUrl),
|
|
451
|
+
onSelect: handleItemSelect,
|
|
452
|
+
theme: stableTheme
|
|
453
|
+
}, item.id);
|
|
454
|
+
})
|
|
455
|
+
}), hasMoreContent && /*#__PURE__*/_jsx(Box, {
|
|
456
|
+
ref: loadMoreRef,
|
|
457
|
+
sx: {
|
|
458
|
+
display: 'flex',
|
|
459
|
+
justifyContent: 'center',
|
|
460
|
+
mt: 2,
|
|
461
|
+
minHeight: 50
|
|
462
|
+
},
|
|
463
|
+
children: loadingMore && /*#__PURE__*/_jsx(CircularProgress, {
|
|
464
|
+
size: 24,
|
|
465
|
+
sx: {
|
|
466
|
+
color: stableTheme?.palette?.editor?.activeColor || "#2563EB"
|
|
467
|
+
}
|
|
468
|
+
})
|
|
469
|
+
})]
|
|
470
|
+
});
|
|
471
|
+
};
|
|
472
|
+
|
|
473
|
+
// Memoize RecentUploads with custom comparison to prevent unnecessary re-renders
|
|
474
|
+
export default /*#__PURE__*/React.memo(RecentUploads, (prevProps, nextProps) => {
|
|
475
|
+
// Only re-render if these props actually change
|
|
476
|
+
const propsEqual = prevProps.onUploaded === nextProps.onUploaded && prevProps.title === nextProps.title;
|
|
477
|
+
|
|
478
|
+
// Deep compare customProps.services since that's what we actually use
|
|
479
|
+
const customPropsEqual = prevProps.customProps === nextProps.customProps || prevProps.customProps?.services === nextProps.customProps?.services && prevProps.customProps?.translation === nextProps.customProps?.translation;
|
|
480
|
+
|
|
481
|
+
// Return true if props are equal (don't re-render), false if different (re-render)
|
|
482
|
+
return propsEqual && customPropsEqual;
|
|
483
|
+
});
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { Grid } from "@mui/material";
|
|
3
|
+
import UploaderWithProgress from "../../UploaderWithProgress";
|
|
3
4
|
import Uploader from "../../Uploader";
|
|
4
5
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
5
6
|
const Upload = props => {
|
|
@@ -9,11 +10,31 @@ const Upload = props => {
|
|
|
9
10
|
onUploaded,
|
|
10
11
|
customProps,
|
|
11
12
|
disableUpload = false,
|
|
12
|
-
title
|
|
13
|
+
title,
|
|
14
|
+
setS3UploadProp,
|
|
15
|
+
s3UploadProp,
|
|
16
|
+
disableProgress,
|
|
17
|
+
setUniqueId,
|
|
18
|
+
uniqueId
|
|
13
19
|
} = props;
|
|
14
20
|
const onDone = img => {
|
|
15
21
|
onUploaded(img);
|
|
16
22
|
};
|
|
23
|
+
const commonProps = {
|
|
24
|
+
classes,
|
|
25
|
+
value,
|
|
26
|
+
data: {
|
|
27
|
+
key: "url"
|
|
28
|
+
},
|
|
29
|
+
customProps,
|
|
30
|
+
onUploaded: onDone,
|
|
31
|
+
disableUpload,
|
|
32
|
+
title,
|
|
33
|
+
setS3UploadProp,
|
|
34
|
+
s3UploadProp,
|
|
35
|
+
setUniqueId,
|
|
36
|
+
uniqueId
|
|
37
|
+
};
|
|
17
38
|
return /*#__PURE__*/_jsx(Grid, {
|
|
18
39
|
item: true,
|
|
19
40
|
xs: 12,
|
|
@@ -22,16 +43,10 @@ const Upload = props => {
|
|
|
22
43
|
height: '100%'
|
|
23
44
|
},
|
|
24
45
|
className: "ims-right",
|
|
25
|
-
children: /*#__PURE__*/_jsx(Uploader, {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
key: "url"
|
|
30
|
-
},
|
|
31
|
-
customProps: customProps,
|
|
32
|
-
onUploaded: onDone,
|
|
33
|
-
disableUpload: disableUpload,
|
|
34
|
-
title: title
|
|
46
|
+
children: disableProgress ? /*#__PURE__*/_jsx(Uploader, {
|
|
47
|
+
...commonProps
|
|
48
|
+
}) : /*#__PURE__*/_jsx(UploaderWithProgress, {
|
|
49
|
+
...commonProps
|
|
35
50
|
})
|
|
36
51
|
});
|
|
37
52
|
};
|
|
@@ -76,7 +76,7 @@ const ImageSelectorStyles = theme => ({
|
|
|
76
76
|
background: theme?.palette?.editor?.deviderBgColor,
|
|
77
77
|
"@media only screen and (min-width: 899px)": {
|
|
78
78
|
margin: "0px 24px",
|
|
79
|
-
width:
|
|
79
|
+
width: "calc(100% - 48px)"
|
|
80
80
|
}
|
|
81
81
|
},
|
|
82
82
|
"& .primaryBtn": {
|
|
@@ -104,12 +104,6 @@ const ImageSelectorStyles = theme => ({
|
|
|
104
104
|
marginRight: "8px !important"
|
|
105
105
|
},
|
|
106
106
|
"& .MuiGrid-root": {
|
|
107
|
-
"&::-webkit-scrollbar-thumb": {
|
|
108
|
-
background: `none !important`
|
|
109
|
-
},
|
|
110
|
-
"&::-webkit-scrollbar-track": {
|
|
111
|
-
visibility: "hidden"
|
|
112
|
-
},
|
|
113
107
|
"&::-webkit-scrollbar-thumb": {
|
|
114
108
|
background: `${theme?.palette?.editor?.brainPopupScroll} !important`
|
|
115
109
|
},
|
|
@@ -118,10 +112,10 @@ const ImageSelectorStyles = theme => ({
|
|
|
118
112
|
}
|
|
119
113
|
},
|
|
120
114
|
"& .MuiImageList-root": {
|
|
121
|
-
margin:
|
|
115
|
+
margin: "0px"
|
|
122
116
|
},
|
|
123
117
|
"& .MuiDialogContent-root": {
|
|
124
|
-
padding:
|
|
118
|
+
padding: "20px 24px 5px 24px"
|
|
125
119
|
}
|
|
126
120
|
},
|
|
127
121
|
titleTypo: {
|
|
@@ -8,7 +8,8 @@ const AppHeaderSettings = props => {
|
|
|
8
8
|
const {
|
|
9
9
|
editor,
|
|
10
10
|
path,
|
|
11
|
-
customProps
|
|
11
|
+
customProps,
|
|
12
|
+
onClose
|
|
12
13
|
} = props;
|
|
13
14
|
const item_path = path?.split("|").map(m => parseInt(m));
|
|
14
15
|
const element_path = [...item_path, 0];
|
|
@@ -27,7 +28,7 @@ const AppHeaderSettings = props => {
|
|
|
27
28
|
});
|
|
28
29
|
};
|
|
29
30
|
const handleClose = () => {
|
|
30
|
-
|
|
31
|
+
onClose();
|
|
31
32
|
};
|
|
32
33
|
return /*#__PURE__*/_jsx(Box, {
|
|
33
34
|
component: "div",
|
|
@@ -8,7 +8,8 @@ const BoxSettings = props => {
|
|
|
8
8
|
const {
|
|
9
9
|
editor,
|
|
10
10
|
path,
|
|
11
|
-
customProps
|
|
11
|
+
customProps,
|
|
12
|
+
onClose
|
|
12
13
|
} = props;
|
|
13
14
|
const item_path = path?.split("|").map(m => parseInt(m));
|
|
14
15
|
const element_path = [...item_path];
|
|
@@ -27,7 +28,7 @@ const BoxSettings = props => {
|
|
|
27
28
|
});
|
|
28
29
|
};
|
|
29
30
|
const handleClose = () => {
|
|
30
|
-
|
|
31
|
+
onClose();
|
|
31
32
|
};
|
|
32
33
|
return /*#__PURE__*/_jsx(Box, {
|
|
33
34
|
component: "div",
|
|
@@ -8,7 +8,8 @@ const ButtonSettings = props => {
|
|
|
8
8
|
const {
|
|
9
9
|
editor,
|
|
10
10
|
path,
|
|
11
|
-
customProps
|
|
11
|
+
customProps,
|
|
12
|
+
onClose
|
|
12
13
|
} = props;
|
|
13
14
|
const item_path = path?.split("|").map(m => parseInt(m));
|
|
14
15
|
const element_path = [...item_path, 0];
|
|
@@ -28,7 +29,7 @@ const ButtonSettings = props => {
|
|
|
28
29
|
});
|
|
29
30
|
};
|
|
30
31
|
const handleClose = () => {
|
|
31
|
-
|
|
32
|
+
onClose();
|
|
32
33
|
};
|
|
33
34
|
return /*#__PURE__*/_jsx(Box, {
|
|
34
35
|
component: "div",
|
|
@@ -8,7 +8,8 @@ const CodeSettings = props => {
|
|
|
8
8
|
const {
|
|
9
9
|
editor,
|
|
10
10
|
path,
|
|
11
|
-
customProps
|
|
11
|
+
customProps,
|
|
12
|
+
onClose
|
|
12
13
|
} = props;
|
|
13
14
|
const item_path = path?.split("|").map(m => parseInt(m));
|
|
14
15
|
const element_path = [...item_path, 0];
|
|
@@ -27,7 +28,7 @@ const CodeSettings = props => {
|
|
|
27
28
|
});
|
|
28
29
|
};
|
|
29
30
|
const handleClose = () => {
|
|
30
|
-
|
|
31
|
+
onClose();
|
|
31
32
|
};
|
|
32
33
|
return /*#__PURE__*/_jsx(Box, {
|
|
33
34
|
component: "div",
|
|
@@ -12,7 +12,8 @@ const FormSettings = props => {
|
|
|
12
12
|
const {
|
|
13
13
|
editor,
|
|
14
14
|
path,
|
|
15
|
-
customProps
|
|
15
|
+
customProps,
|
|
16
|
+
onClose
|
|
16
17
|
} = props;
|
|
17
18
|
const item_path = path?.split("|").map(m => parseInt(m));
|
|
18
19
|
const element_path = [...item_path];
|
|
@@ -56,7 +57,7 @@ const FormSettings = props => {
|
|
|
56
57
|
}
|
|
57
58
|
};
|
|
58
59
|
const handleClose = () => {
|
|
59
|
-
|
|
60
|
+
onClose();
|
|
60
61
|
};
|
|
61
62
|
const muiTheme = createTheme({
|
|
62
63
|
components: {
|