@jhits/plugin-images 0.0.6 → 0.0.8

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.
Files changed (169) hide show
  1. package/dist/api/fallback/route.d.ts +7 -0
  2. package/dist/api/fallback/route.d.ts.map +1 -0
  3. package/dist/api/fallback/route.js +65 -0
  4. package/dist/api/index.d.ts +9 -0
  5. package/dist/api/index.d.ts.map +1 -0
  6. package/dist/api/index.js +8 -0
  7. package/dist/api/list/index.d.ts +21 -0
  8. package/dist/api/list/index.d.ts.map +1 -0
  9. package/dist/api/list/index.js +80 -0
  10. package/dist/api/resolve/route.d.ts +39 -0
  11. package/dist/api/resolve/route.d.ts.map +1 -0
  12. package/dist/api/resolve/route.js +213 -0
  13. package/dist/api/router.d.ts +14 -0
  14. package/dist/api/router.d.ts.map +1 -0
  15. package/dist/api/router.js +67 -0
  16. package/dist/api/upload/index.d.ts +20 -0
  17. package/dist/api/upload/index.d.ts.map +1 -0
  18. package/dist/api/upload/index.js +65 -0
  19. package/dist/api/uploads/[filename]/route.d.ts +21 -0
  20. package/dist/api/uploads/[filename]/route.d.ts.map +1 -0
  21. package/dist/api/uploads/[filename]/route.js +80 -0
  22. package/dist/api-server.d.ts +9 -0
  23. package/dist/api-server.d.ts.map +1 -0
  24. package/dist/api-server.js +9 -0
  25. package/dist/components/BackgroundImage.d.ts +11 -0
  26. package/dist/components/BackgroundImage.d.ts.map +1 -0
  27. package/dist/components/BackgroundImage.js +33 -0
  28. package/dist/components/GlobalImageEditor/config.d.ts +9 -0
  29. package/dist/components/GlobalImageEditor/config.d.ts.map +1 -0
  30. package/dist/components/GlobalImageEditor/config.js +17 -0
  31. package/dist/components/GlobalImageEditor/eventHandlers.d.ts +20 -0
  32. package/dist/components/GlobalImageEditor/eventHandlers.d.ts.map +1 -0
  33. package/dist/components/GlobalImageEditor/eventHandlers.js +210 -0
  34. package/dist/components/GlobalImageEditor/imageDetection.d.ts +16 -0
  35. package/dist/components/GlobalImageEditor/imageDetection.d.ts.map +1 -0
  36. package/dist/components/GlobalImageEditor/imageDetection.js +135 -0
  37. package/dist/components/GlobalImageEditor/imageSetup.d.ts +9 -0
  38. package/dist/components/GlobalImageEditor/imageSetup.d.ts.map +1 -0
  39. package/dist/components/GlobalImageEditor/imageSetup.js +260 -0
  40. package/dist/components/GlobalImageEditor/saveLogic.d.ts +26 -0
  41. package/dist/components/GlobalImageEditor/saveLogic.d.ts.map +1 -0
  42. package/dist/components/GlobalImageEditor/saveLogic.js +98 -0
  43. package/dist/components/GlobalImageEditor/stylingDetection.d.ts +9 -0
  44. package/dist/components/GlobalImageEditor/stylingDetection.d.ts.map +1 -0
  45. package/dist/components/GlobalImageEditor/stylingDetection.js +110 -0
  46. package/dist/components/GlobalImageEditor/transformParsing.d.ts +16 -0
  47. package/dist/components/GlobalImageEditor/transformParsing.d.ts.map +1 -0
  48. package/dist/components/GlobalImageEditor/transformParsing.js +68 -0
  49. package/dist/components/GlobalImageEditor/types.d.ts +36 -0
  50. package/dist/components/GlobalImageEditor/types.d.ts.map +1 -0
  51. package/dist/components/GlobalImageEditor/types.js +4 -0
  52. package/dist/components/GlobalImageEditor.d.ts +8 -0
  53. package/dist/components/GlobalImageEditor.d.ts.map +1 -0
  54. package/dist/components/GlobalImageEditor.js +232 -0
  55. package/dist/components/Image.d.ts +22 -0
  56. package/dist/components/Image.d.ts.map +1 -0
  57. package/dist/components/Image.js +227 -0
  58. package/dist/components/ImageBrowserModal.d.ts +13 -0
  59. package/dist/components/ImageBrowserModal.d.ts.map +1 -0
  60. package/dist/components/ImageBrowserModal.js +507 -0
  61. package/dist/components/ImageEditor.d.ts +27 -0
  62. package/dist/components/ImageEditor.d.ts.map +1 -0
  63. package/dist/components/ImageEditor.js +172 -0
  64. package/dist/components/ImageEffectsPanel.d.ts +10 -0
  65. package/dist/components/ImageEffectsPanel.d.ts.map +1 -0
  66. package/dist/components/ImageEffectsPanel.js +11 -0
  67. package/dist/components/ImagePicker.d.ts +3 -0
  68. package/dist/components/ImagePicker.d.ts.map +1 -0
  69. package/dist/components/ImagePicker.js +142 -0
  70. package/dist/components/ImagesPluginInit.d.ts +24 -0
  71. package/dist/components/ImagesPluginInit.d.ts.map +1 -0
  72. package/dist/components/ImagesPluginInit.js +28 -0
  73. package/dist/components/index.d.ts +9 -0
  74. package/dist/components/index.d.ts.map +1 -0
  75. package/dist/components/index.js +7 -0
  76. package/dist/config.d.ts +14 -0
  77. package/dist/config.d.ts.map +1 -0
  78. package/dist/config.js +172 -0
  79. package/dist/hooks/useImagePicker.d.ts +20 -0
  80. package/dist/hooks/useImagePicker.d.ts.map +1 -0
  81. package/dist/hooks/useImagePicker.js +320 -0
  82. package/dist/index.d.ts +23 -0
  83. package/dist/index.d.ts.map +1 -0
  84. package/dist/index.js +28 -0
  85. package/dist/index.server.d.ts +11 -0
  86. package/dist/index.server.d.ts.map +1 -0
  87. package/dist/index.server.js +10 -0
  88. package/dist/init.d.ts +33 -0
  89. package/dist/init.d.ts.map +1 -0
  90. package/dist/init.js +43 -0
  91. package/dist/types/index.d.ts +80 -0
  92. package/dist/types/index.d.ts.map +1 -0
  93. package/dist/types/index.js +4 -0
  94. package/dist/utils/fallback.d.ts +27 -0
  95. package/dist/utils/fallback.d.ts.map +1 -0
  96. package/dist/utils/fallback.js +63 -0
  97. package/dist/utils/transforms.d.ts +26 -0
  98. package/dist/utils/transforms.d.ts.map +1 -0
  99. package/dist/utils/transforms.js +38 -0
  100. package/dist/views/ImageManager.d.ts +10 -0
  101. package/dist/views/ImageManager.d.ts.map +1 -0
  102. package/dist/views/ImageManager.js +9 -0
  103. package/package.json +2 -2
  104. package/src/components/BackgroundImage.d.ts +11 -0
  105. package/src/components/BackgroundImage.d.ts.map +1 -0
  106. package/src/components/BackgroundImage.js +35 -0
  107. package/src/components/GlobalImageEditor/config.d.ts +9 -0
  108. package/src/components/GlobalImageEditor/config.d.ts.map +1 -0
  109. package/src/components/GlobalImageEditor/config.js +18 -0
  110. package/src/components/GlobalImageEditor/eventHandlers.d.ts +20 -0
  111. package/src/components/GlobalImageEditor/eventHandlers.d.ts.map +1 -0
  112. package/src/components/GlobalImageEditor/eventHandlers.js +206 -0
  113. package/src/components/GlobalImageEditor/imageDetection.d.ts +16 -0
  114. package/src/components/GlobalImageEditor/imageDetection.d.ts.map +1 -0
  115. package/src/components/GlobalImageEditor/imageDetection.js +130 -0
  116. package/src/components/GlobalImageEditor/imageSetup.d.ts +9 -0
  117. package/src/components/GlobalImageEditor/imageSetup.d.ts.map +1 -0
  118. package/src/components/GlobalImageEditor/imageSetup.js +261 -0
  119. package/src/components/GlobalImageEditor/saveLogic.d.ts +26 -0
  120. package/src/components/GlobalImageEditor/saveLogic.d.ts.map +1 -0
  121. package/src/components/GlobalImageEditor/saveLogic.js +99 -0
  122. package/src/components/GlobalImageEditor/stylingDetection.d.ts +9 -0
  123. package/src/components/GlobalImageEditor/stylingDetection.d.ts.map +1 -0
  124. package/src/components/GlobalImageEditor/stylingDetection.js +110 -0
  125. package/src/components/GlobalImageEditor/transformParsing.d.ts +16 -0
  126. package/src/components/GlobalImageEditor/transformParsing.d.ts.map +1 -0
  127. package/src/components/GlobalImageEditor/transformParsing.js +68 -0
  128. package/src/components/GlobalImageEditor/types.d.ts +36 -0
  129. package/src/components/GlobalImageEditor/types.d.ts.map +1 -0
  130. package/src/components/GlobalImageEditor/types.js +4 -0
  131. package/src/components/GlobalImageEditor.d.ts +8 -0
  132. package/src/components/GlobalImageEditor.d.ts.map +1 -0
  133. package/src/components/GlobalImageEditor.js +227 -0
  134. package/src/components/Image.d.ts +22 -0
  135. package/src/components/Image.d.ts.map +1 -0
  136. package/src/components/Image.js +229 -0
  137. package/src/components/ImageBrowserModal.d.ts +13 -0
  138. package/src/components/ImageBrowserModal.d.ts.map +1 -0
  139. package/src/components/ImageBrowserModal.js +504 -0
  140. package/src/components/ImageEditor.d.ts +27 -0
  141. package/src/components/ImageEditor.d.ts.map +1 -0
  142. package/src/components/ImageEditor.js +173 -0
  143. package/src/components/ImagePicker.d.ts +3 -0
  144. package/src/components/ImagePicker.d.ts.map +1 -0
  145. package/src/components/ImagePicker.js +143 -0
  146. package/src/components/ImagesPluginInit.d.ts +24 -0
  147. package/src/components/ImagesPluginInit.d.ts.map +1 -0
  148. package/src/components/ImagesPluginInit.js +28 -0
  149. package/src/hooks/useImagePicker.d.ts +20 -0
  150. package/src/hooks/useImagePicker.d.ts.map +1 -0
  151. package/src/hooks/useImagePicker.js +322 -0
  152. package/src/index.d.ts +23 -0
  153. package/src/index.d.ts.map +1 -0
  154. package/src/index.js +28 -0
  155. package/src/init.d.ts +33 -0
  156. package/src/init.d.ts.map +1 -0
  157. package/src/init.js +43 -0
  158. package/src/types/index.d.ts +80 -0
  159. package/src/types/index.d.ts.map +1 -0
  160. package/src/types/index.js +4 -0
  161. package/src/utils/fallback.d.ts +27 -0
  162. package/src/utils/fallback.d.ts.map +1 -0
  163. package/src/utils/fallback.js +63 -0
  164. package/src/utils/transforms.d.ts +26 -0
  165. package/src/utils/transforms.d.ts.map +1 -0
  166. package/src/utils/transforms.js +38 -0
  167. package/src/views/ImageManager.d.ts +10 -0
  168. package/src/views/ImageManager.d.ts.map +1 -0
  169. package/src/views/ImageManager.js +9 -0
@@ -0,0 +1,322 @@
1
+ /**
2
+ * Hook for Image Picker Logic
3
+ */
4
+ import { useState, useEffect, useRef } from 'react';
5
+ export function useImagePicker({ value, images }) {
6
+ const [selectedImage, setSelectedImage] = useState(null);
7
+ const [uploading, setUploading] = useState(false);
8
+ const fileInputRef = useRef(null);
9
+ const lastResolvedValueRef = useRef(undefined);
10
+ const isResolvingRef = useRef(false);
11
+ const lastImagesRef = useRef('');
12
+ // Find selected image from value (can be ID or URL)
13
+ useEffect(() => {
14
+ // Create a stable reference for images array to detect actual changes
15
+ const imagesKey = JSON.stringify(images.map(img => ({ id: img.id, url: img.url })));
16
+ // Prevent infinite loops by checking if we're already resolving or if value and images haven't changed
17
+ if (isResolvingRef.current || (lastResolvedValueRef.current === value && lastImagesRef.current === imagesKey)) {
18
+ return;
19
+ }
20
+ lastImagesRef.current = imagesKey;
21
+ if (!value) {
22
+ if (selectedImage !== null) {
23
+ setSelectedImage(null);
24
+ }
25
+ lastResolvedValueRef.current = value;
26
+ return;
27
+ }
28
+ isResolvingRef.current = true;
29
+ const resolveImage = async () => {
30
+ var _a, _b, _c;
31
+ // Normalize the value - extract filename if it's a URL
32
+ const isFullUrl = value.startsWith('http://') || value.startsWith('https://');
33
+ const isRelativeUrl = value.startsWith('/');
34
+ const isUrl = isFullUrl || isRelativeUrl;
35
+ // Extract filename from URL if it's a URL
36
+ let filenameFromUrl = null;
37
+ let imageIdToResolve = value;
38
+ if (isUrl) {
39
+ const urlParts = value.split('/');
40
+ filenameFromUrl = ((_a = urlParts[urlParts.length - 1]) === null || _a === void 0 ? void 0 : _a.split('?')[0]) || null;
41
+ // If it's a full URL, try to resolve using the filename instead
42
+ if (isFullUrl && filenameFromUrl) {
43
+ imageIdToResolve = filenameFromUrl;
44
+ }
45
+ }
46
+ // First, try to find by ID (preferred method)
47
+ let found = images.find(img => img.id === value || img.id === imageIdToResolve);
48
+ // If not found by ID, try to find by URL
49
+ if (!found) {
50
+ found = images.find(img => img.url === value);
51
+ }
52
+ // If still not found, try to match by filename extracted from URL
53
+ if (!found && filenameFromUrl) {
54
+ found = images.find(img => img.id === filenameFromUrl || img.filename === filenameFromUrl);
55
+ }
56
+ if (found) {
57
+ // Only update if the image is actually different
58
+ setSelectedImage(prev => {
59
+ if ((prev === null || prev === void 0 ? void 0 : prev.id) === found.id && (prev === null || prev === void 0 ? void 0 : prev.url) === found.url) {
60
+ return prev;
61
+ }
62
+ return found;
63
+ });
64
+ }
65
+ else {
66
+ // If value is already a full URL, use it directly
67
+ if (isFullUrl) {
68
+ const newImage = {
69
+ id: value,
70
+ filename: filenameFromUrl || value,
71
+ url: value, // Use the full URL as-is
72
+ size: 0,
73
+ mimeType: 'image/jpeg',
74
+ uploadedAt: new Date().toISOString(),
75
+ };
76
+ setSelectedImage(prev => {
77
+ if ((prev === null || prev === void 0 ? void 0 : prev.id) === newImage.id && (prev === null || prev === void 0 ? void 0 : prev.url) === newImage.url) {
78
+ return prev;
79
+ }
80
+ return newImage;
81
+ });
82
+ lastResolvedValueRef.current = value;
83
+ isResolvingRef.current = false;
84
+ return;
85
+ }
86
+ // If value is a relative URL, use it directly
87
+ if (isRelativeUrl) {
88
+ const newImage = {
89
+ id: value,
90
+ filename: filenameFromUrl || value,
91
+ url: value, // Use the relative URL as-is
92
+ size: 0,
93
+ mimeType: 'image/jpeg',
94
+ uploadedAt: new Date().toISOString(),
95
+ };
96
+ setSelectedImage(prev => {
97
+ if ((prev === null || prev === void 0 ? void 0 : prev.id) === newImage.id && (prev === null || prev === void 0 ? void 0 : prev.url) === newImage.url) {
98
+ return prev;
99
+ }
100
+ return newImage;
101
+ });
102
+ lastResolvedValueRef.current = value;
103
+ isResolvingRef.current = false;
104
+ return;
105
+ }
106
+ // Check if value looks like a filename (has extension or starts with digits)
107
+ const isLikelyPath = /\.(jpg|jpeg|png|webp|gif|svg)$/i.test(value) || /^\d+-/.test(value);
108
+ if (isLikelyPath) {
109
+ // It's likely a filename, create image object directly
110
+ const newImage = {
111
+ id: value,
112
+ filename: value,
113
+ url: `/api/uploads/${value}`,
114
+ size: 0,
115
+ mimeType: 'image/jpeg',
116
+ uploadedAt: new Date().toISOString(),
117
+ };
118
+ setSelectedImage(prev => {
119
+ if ((prev === null || prev === void 0 ? void 0 : prev.id) === newImage.id && (prev === null || prev === void 0 ? void 0 : prev.url) === newImage.url) {
120
+ return prev;
121
+ }
122
+ return newImage;
123
+ });
124
+ lastResolvedValueRef.current = value;
125
+ isResolvingRef.current = false;
126
+ }
127
+ else {
128
+ // It might be a semantic ID, try to resolve via API
129
+ // Use the extracted ID (filename) if value was a URL, otherwise use value
130
+ try {
131
+ const response = await fetch(`/api/plugin-images/resolve?id=${encodeURIComponent(imageIdToResolve)}`);
132
+ if (response.ok) {
133
+ const data = await response.json();
134
+ // Normalize the URL - ensure it's a proper URL
135
+ let imageUrl;
136
+ if (data.url) {
137
+ // If API returns a URL, use it (but check if it's already a full URL)
138
+ if (data.url.startsWith('http://') || data.url.startsWith('https://')) {
139
+ imageUrl = data.url;
140
+ }
141
+ else if (data.url.startsWith('/')) {
142
+ imageUrl = data.url;
143
+ }
144
+ else {
145
+ // Relative path without leading slash
146
+ imageUrl = `/api/uploads/${data.url}`;
147
+ }
148
+ }
149
+ else if (data.filename) {
150
+ // Use filename to construct URL
151
+ imageUrl = `/api/uploads/${data.filename}`;
152
+ }
153
+ else {
154
+ // Fallback: if original value was a URL, use it; otherwise construct
155
+ imageUrl = isFullUrl ? value : (isRelativeUrl ? value : `/api/uploads/${value}`);
156
+ }
157
+ const newImage = {
158
+ id: value,
159
+ filename: data.filename || filenameFromUrl || value,
160
+ url: imageUrl,
161
+ size: 0,
162
+ mimeType: 'image/jpeg',
163
+ uploadedAt: new Date().toISOString(),
164
+ };
165
+ setSelectedImage(prev => {
166
+ if ((prev === null || prev === void 0 ? void 0 : prev.id) === newImage.id && (prev === null || prev === void 0 ? void 0 : prev.url) === newImage.url) {
167
+ return prev;
168
+ }
169
+ return newImage;
170
+ });
171
+ lastResolvedValueRef.current = value;
172
+ isResolvingRef.current = false;
173
+ }
174
+ else {
175
+ // API resolution failed - check if it's a semantic ID or actual filename
176
+ const isLikelyFilename = /\.(jpg|jpeg|png|webp|gif|svg)$/i.test(imageIdToResolve) || /^\d+-/.test(imageIdToResolve);
177
+ if (!isLikelyFilename) {
178
+ // It's a semantic ID that couldn't be resolved - clear selection
179
+ // This prevents showing broken URLs like /api/uploads/blog-featured-...
180
+ setSelectedImage(null);
181
+ lastResolvedValueRef.current = value;
182
+ isResolvingRef.current = false;
183
+ return;
184
+ }
185
+ // It's a filename, create fallback object
186
+ const isFullUrl = value.startsWith('http://') || value.startsWith('https://');
187
+ const isRelativeUrl = value.startsWith('/');
188
+ let imageUrl;
189
+ if (isFullUrl) {
190
+ // Already a full URL, use as-is
191
+ imageUrl = value;
192
+ }
193
+ else if (isRelativeUrl) {
194
+ // Already a relative URL starting with /, use as-is
195
+ imageUrl = value;
196
+ }
197
+ else {
198
+ // It's a filename, construct the URL
199
+ imageUrl = `/api/uploads/${value}`;
200
+ }
201
+ const urlParts = value.split('/');
202
+ const filename = ((_b = urlParts[urlParts.length - 1]) === null || _b === void 0 ? void 0 : _b.split('?')[0]) || value;
203
+ const newImage = {
204
+ id: value,
205
+ filename: filename,
206
+ url: imageUrl,
207
+ size: 0,
208
+ mimeType: 'image/jpeg',
209
+ uploadedAt: new Date().toISOString(),
210
+ };
211
+ setSelectedImage(prev => {
212
+ if ((prev === null || prev === void 0 ? void 0 : prev.id) === newImage.id && (prev === null || prev === void 0 ? void 0 : prev.url) === newImage.url) {
213
+ return prev;
214
+ }
215
+ return newImage;
216
+ });
217
+ lastResolvedValueRef.current = value;
218
+ isResolvingRef.current = false;
219
+ }
220
+ }
221
+ catch (error) {
222
+ // API call failed - check if it's a semantic ID or actual filename
223
+ const isLikelyFilename = /\.(jpg|jpeg|png|webp|gif|svg)$/i.test(imageIdToResolve) || /^\d+-/.test(imageIdToResolve);
224
+ if (!isLikelyFilename) {
225
+ // It's a semantic ID that couldn't be resolved - clear selection
226
+ // This prevents showing broken URLs like /api/uploads/blog-featured-...
227
+ setSelectedImage(null);
228
+ lastResolvedValueRef.current = value;
229
+ isResolvingRef.current = false;
230
+ return;
231
+ }
232
+ // It's a filename, create fallback object
233
+ const isFullUrl = value.startsWith('http://') || value.startsWith('https://');
234
+ const isRelativeUrl = value.startsWith('/');
235
+ let imageUrl;
236
+ if (isFullUrl) {
237
+ // Already a full URL, use as-is
238
+ imageUrl = value;
239
+ }
240
+ else if (isRelativeUrl) {
241
+ // Already a relative URL starting with /, use as-is
242
+ imageUrl = value;
243
+ }
244
+ else {
245
+ // It's a filename, construct the URL
246
+ imageUrl = `/api/uploads/${value}`;
247
+ }
248
+ const urlParts = value.split('/');
249
+ const filename = ((_c = urlParts[urlParts.length - 1]) === null || _c === void 0 ? void 0 : _c.split('?')[0]) || value;
250
+ const newImage = {
251
+ id: value,
252
+ filename: filename,
253
+ url: imageUrl,
254
+ size: 0,
255
+ mimeType: 'image/jpeg',
256
+ uploadedAt: new Date().toISOString(),
257
+ };
258
+ setSelectedImage(prev => {
259
+ if ((prev === null || prev === void 0 ? void 0 : prev.id) === newImage.id && (prev === null || prev === void 0 ? void 0 : prev.url) === newImage.url) {
260
+ return prev;
261
+ }
262
+ return newImage;
263
+ });
264
+ lastResolvedValueRef.current = value;
265
+ isResolvingRef.current = false;
266
+ }
267
+ }
268
+ }
269
+ };
270
+ resolveImage().catch(() => {
271
+ // Error already handled in catch block
272
+ isResolvingRef.current = false;
273
+ });
274
+ }, [value, images]);
275
+ // Handle file upload
276
+ const handleFileSelect = async (e) => {
277
+ var _a, _b;
278
+ const file = (_b = (_a = e === null || e === void 0 ? void 0 : e.target) === null || _a === void 0 ? void 0 : _a.files) === null || _b === void 0 ? void 0 : _b[0];
279
+ if (!file)
280
+ return null;
281
+ setUploading(true);
282
+ try {
283
+ const formData = new FormData();
284
+ formData.append('file', file);
285
+ const response = await fetch('/api/plugin-images/upload', {
286
+ method: 'POST',
287
+ body: formData,
288
+ });
289
+ const data = await response.json();
290
+ if (data.success && data.image) {
291
+ // Select the newly uploaded image
292
+ setSelectedImage(data.image);
293
+ if (fileInputRef.current) {
294
+ fileInputRef.current.value = '';
295
+ }
296
+ return data.image;
297
+ }
298
+ else {
299
+ alert(data.error || 'Failed to upload image');
300
+ return null;
301
+ }
302
+ }
303
+ catch (error) {
304
+ console.error('Upload error:', error);
305
+ alert('Failed to upload image');
306
+ return null;
307
+ }
308
+ finally {
309
+ setUploading(false);
310
+ if (fileInputRef.current) {
311
+ fileInputRef.current.value = '';
312
+ }
313
+ }
314
+ };
315
+ return {
316
+ selectedImage,
317
+ setSelectedImage,
318
+ uploading,
319
+ fileInputRef,
320
+ handleFileSelect,
321
+ };
322
+ }
package/src/index.d.ts ADDED
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Plugin Images - Main Entry Point
3
+ * Image management plugin for uploading, searching, and managing images
4
+ */
5
+ export interface PluginProps {
6
+ subPath: string[];
7
+ siteId: string;
8
+ locale: string;
9
+ }
10
+ export default function ImagesPlugin({ subPath, siteId, locale }: PluginProps): import("react/jsx-runtime").JSX.Element;
11
+ export { ImagesPlugin as Index };
12
+ export { ImagePicker } from './components/ImagePicker';
13
+ export { GlobalImageEditor } from './components/GlobalImageEditor';
14
+ export { ImagesPluginInit } from './components/ImagesPluginInit';
15
+ export { Image } from './components/Image';
16
+ export { BackgroundImage } from './components/BackgroundImage';
17
+ export type { ImagePickerProps, ImageMetadata } from './types';
18
+ export type { PluginImageProps } from './components/Image';
19
+ export type { BackgroundImageProps } from './components/BackgroundImage';
20
+ export { initImagesPlugin } from './init';
21
+ export type { ImagesPluginConfig } from './init';
22
+ export { getFallbackImageUrl, isValidImageUrl, getSafeImageUrl, constructImageUrl } from './utils/fallback';
23
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AAOH,MAAM,WAAW,WAAW;IACxB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,CAAC,OAAO,UAAU,YAAY,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,WAAW,2CAU5E;AAGD,OAAO,EAAE,YAAY,IAAI,KAAK,EAAE,CAAC;AAGjC,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AACnE,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AACjE,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAC/D,YAAY,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC/D,YAAY,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAC3D,YAAY,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AAGzE,OAAO,EAAE,gBAAgB,EAAE,MAAM,QAAQ,CAAC;AAC1C,YAAY,EAAE,kBAAkB,EAAE,MAAM,QAAQ,CAAC;AAGjD,OAAO,EACH,mBAAmB,EACnB,eAAe,EACf,eAAe,EACf,iBAAiB,EACpB,MAAM,kBAAkB,CAAC"}
package/src/index.js ADDED
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Plugin Images - Main Entry Point
3
+ * Image management plugin for uploading, searching, and managing images
4
+ */
5
+ 'use client';
6
+ import { jsx as _jsx } from "react/jsx-runtime";
7
+ import { ImageManagerView } from './views/ImageManager';
8
+ export default function ImagesPlugin({ subPath, siteId, locale }) {
9
+ const route = subPath[0] || 'manager';
10
+ switch (route) {
11
+ case 'manager':
12
+ return _jsx(ImageManagerView, { siteId: siteId, locale: locale });
13
+ default:
14
+ return _jsx(ImageManagerView, { siteId: siteId, locale: locale });
15
+ }
16
+ }
17
+ // Export for use as default
18
+ export { ImagesPlugin as Index };
19
+ // Export components for use in other plugins
20
+ export { ImagePicker } from './components/ImagePicker';
21
+ export { GlobalImageEditor } from './components/GlobalImageEditor';
22
+ export { ImagesPluginInit } from './components/ImagesPluginInit';
23
+ export { Image } from './components/Image';
24
+ export { BackgroundImage } from './components/BackgroundImage';
25
+ // Export initialization utility
26
+ export { initImagesPlugin } from './init';
27
+ // Export utility functions
28
+ export { getFallbackImageUrl, isValidImageUrl, getSafeImageUrl, constructImageUrl } from './utils/fallback';
package/src/init.d.ts ADDED
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Images Plugin Initialization Utility
3
+ *
4
+ * Simple function to initialize the images plugin with client configuration.
5
+ * Call this once in your app (e.g., in root layout) to enable global image editing.
6
+ *
7
+ * @example
8
+ * ```typescript
9
+ * import { initImagesPlugin } from '@jhits/plugin-images/init';
10
+ * import { imagesConfig } from '@/plugins/images-config';
11
+ *
12
+ * // Call once when your app loads
13
+ * initImagesPlugin(imagesConfig);
14
+ * ```
15
+ */
16
+ export interface ImagesPluginConfig {
17
+ /** Enable global image editor (default: true) */
18
+ enabled?: boolean;
19
+ /** Custom styling for the editor modal */
20
+ className?: string;
21
+ /** Custom styling for the modal overlay */
22
+ overlayClassName?: string;
23
+ }
24
+ /**
25
+ * Initialize the images plugin with client configuration
26
+ *
27
+ * This function sets up the window global that the plugin reads from automatically.
28
+ * Call this once when your app loads, before the plugin component is rendered.
29
+ *
30
+ * @param config - Images plugin configuration (enabled, styling, etc.)
31
+ */
32
+ export declare function initImagesPlugin(config?: ImagesPluginConfig): void;
33
+ //# sourceMappingURL=init.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["init.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAIH,MAAM,WAAW,kBAAkB;IAC/B,iDAAiD;IACjD,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,0CAA0C;IAC1C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,2CAA2C;IAC3C,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,CAAC,EAAE,kBAAkB,GAAG,IAAI,CAqBlE"}
package/src/init.js ADDED
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Images Plugin Initialization Utility
3
+ *
4
+ * Simple function to initialize the images plugin with client configuration.
5
+ * Call this once in your app (e.g., in root layout) to enable global image editing.
6
+ *
7
+ * @example
8
+ * ```typescript
9
+ * import { initImagesPlugin } from '@jhits/plugin-images/init';
10
+ * import { imagesConfig } from '@/plugins/images-config';
11
+ *
12
+ * // Call once when your app loads
13
+ * initImagesPlugin(imagesConfig);
14
+ * ```
15
+ */
16
+ 'use client';
17
+ /**
18
+ * Initialize the images plugin with client configuration
19
+ *
20
+ * This function sets up the window global that the plugin reads from automatically.
21
+ * Call this once when your app loads, before the plugin component is rendered.
22
+ *
23
+ * @param config - Images plugin configuration (enabled, styling, etc.)
24
+ */
25
+ export function initImagesPlugin(config) {
26
+ if (typeof window === 'undefined') {
27
+ // Server-side: no-op
28
+ return;
29
+ }
30
+ // Initialize the global plugin props object if it doesn't exist
31
+ if (!window.__JHITS_PLUGIN_PROPS__) {
32
+ window.__JHITS_PLUGIN_PROPS__ = {};
33
+ }
34
+ // Set images plugin configuration
35
+ window.__JHITS_PLUGIN_PROPS__['plugin-images'] = {
36
+ enabled: (config === null || config === void 0 ? void 0 : config.enabled) !== undefined ? config.enabled : true,
37
+ className: config === null || config === void 0 ? void 0 : config.className,
38
+ overlayClassName: config === null || config === void 0 ? void 0 : config.overlayClassName,
39
+ };
40
+ console.log('[ImagesPlugin] Initialized with config:', {
41
+ enabled: (config === null || config === void 0 ? void 0 : config.enabled) !== undefined ? config.enabled : true,
42
+ });
43
+ }
@@ -0,0 +1,80 @@
1
+ /**
2
+ * Image Plugin Types
3
+ */
4
+ export interface ImageMetadata {
5
+ /** Unique image ID */
6
+ id: string;
7
+ /** Original filename */
8
+ filename: string;
9
+ /** File path/URL */
10
+ url: string;
11
+ /** File size in bytes */
12
+ size: number;
13
+ /** MIME type */
14
+ mimeType: string;
15
+ /** Image dimensions */
16
+ width?: number;
17
+ height?: number;
18
+ /** Alt text */
19
+ alt?: string;
20
+ /** Upload timestamp */
21
+ uploadedAt: string;
22
+ /** Uploaded by user ID */
23
+ uploadedBy?: string;
24
+ /** Tags for searching */
25
+ tags?: string[];
26
+ }
27
+ export interface ImageUploadResponse {
28
+ success: boolean;
29
+ image?: ImageMetadata;
30
+ error?: string;
31
+ }
32
+ export interface ImageListResponse {
33
+ images: ImageMetadata[];
34
+ total: number;
35
+ page: number;
36
+ limit: number;
37
+ }
38
+ export interface ImagePickerProps {
39
+ /** Current selected image URL */
40
+ value?: string;
41
+ /** Callback when image is selected */
42
+ onChange: (image: ImageMetadata | null) => void;
43
+ /** Whether dark mode is enabled */
44
+ darkMode?: boolean;
45
+ /** Show brightness and blur controls */
46
+ showEffects?: boolean;
47
+ /** Current brightness value (0-200, 100 = normal) */
48
+ brightness?: number;
49
+ /** Current blur value (0-20) */
50
+ blur?: number;
51
+ /** Current scale value (0.1-3.0, 1.0 = normal) */
52
+ scale?: number;
53
+ /** Current X position offset (-100 to 100, 0 = center) */
54
+ positionX?: number;
55
+ /** Current Y position offset (-100 to 100, 0 = center) */
56
+ positionY?: number;
57
+ /** Aspect ratio for preview/editor (e.g., "4/5", "3/4", "16/9", "1/1") */
58
+ aspectRatio?: string;
59
+ /** Border radius class (e.g., "rounded-xl", "rounded-3xl") */
60
+ borderRadius?: string;
61
+ /** Object fit style (e.g., "cover", "contain") */
62
+ objectFit?: 'cover' | 'contain' | 'fill' | 'none' | 'scale-down';
63
+ /** Object position (e.g., "center", "top", "bottom") */
64
+ objectPosition?: string;
65
+ /** Callback when brightness changes */
66
+ onBrightnessChange?: (brightness: number) => void;
67
+ /** Callback when blur changes */
68
+ onBlurChange?: (blur: number) => void;
69
+ /** Callback when scale changes */
70
+ onScaleChange?: (scale: number) => void;
71
+ /** Callback when X position changes */
72
+ onPositionXChange?: (positionX: number) => void;
73
+ /** Callback when Y position changes */
74
+ onPositionYChange?: (positionY: number) => void;
75
+ /** Callback when editor "Done" button is clicked - triggers immediate save */
76
+ onEditorSave?: (scale: number, positionX: number, positionY: number, brightness?: number, blur?: number) => void;
77
+ /** Automatically open the editor when component mounts (useful for modal scenarios) */
78
+ autoOpenEditor?: boolean;
79
+ }
80
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,WAAW,aAAa;IAC1B,sBAAsB;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,wBAAwB;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,oBAAoB;IACpB,GAAG,EAAE,MAAM,CAAC;IACZ,yBAAyB;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,gBAAgB;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,uBAAuB;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,eAAe;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,uBAAuB;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,0BAA0B;IAC1B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,yBAAyB;IACzB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,MAAM,WAAW,mBAAmB;IAChC,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,iBAAiB;IAC9B,MAAM,EAAE,aAAa,EAAE,CAAC;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,gBAAgB;IAC7B,iCAAiC;IACjC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,sCAAsC;IACtC,QAAQ,EAAE,CAAC,KAAK,EAAE,aAAa,GAAG,IAAI,KAAK,IAAI,CAAC;IAChD,mCAAmC;IACnC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,wCAAwC;IACxC,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,qDAAqD;IACrD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gCAAgC;IAChC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,kDAAkD;IAClD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,0DAA0D;IAC1D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,0DAA0D;IAC1D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,0EAA0E;IAC1E,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,8DAA8D;IAC9D,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,kDAAkD;IAClD,SAAS,CAAC,EAAE,OAAO,GAAG,SAAS,GAAG,MAAM,GAAG,MAAM,GAAG,YAAY,CAAC;IACjE,wDAAwD;IACxD,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,uCAAuC;IACvC,kBAAkB,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;IAClD,iCAAiC;IACjC,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACtC,kCAAkC;IAClC,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,uCAAuC;IACvC,iBAAiB,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAChD,uCAAuC;IACvC,iBAAiB,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAChD,8EAA8E;IAC9E,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IACjH,uFAAuF;IACvF,cAAc,CAAC,EAAE,OAAO,CAAC;CAC5B"}
@@ -0,0 +1,4 @@
1
+ /**
2
+ * Image Plugin Types
3
+ */
4
+ export {};
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Fallback image utility
3
+ * Provides a default fallback image URL when images fail to load or are invalid
4
+ * Also handles URL construction for image filenames
5
+ */
6
+ /**
7
+ * Returns the URL for the fallback "image not found" image
8
+ * Served from the plugin's API route
9
+ */
10
+ export declare function getFallbackImageUrl(): string;
11
+ /**
12
+ * Constructs the full image URL from a filename or URL
13
+ * - If it's already a full URL (http://, https://, or starts with /), returns as-is
14
+ * - If it's a filename, constructs `/api/uploads/${filename}`
15
+ */
16
+ export declare function constructImageUrl(src: string | null | undefined): string | null;
17
+ /**
18
+ * Validates if a URL is valid and can be used with Next.js Image component
19
+ */
20
+ export declare function isValidImageUrl(url: string | null | undefined): boolean;
21
+ /**
22
+ * Gets a safe image URL with automatic URL construction and fallback
23
+ * - Constructs the full URL if src is a filename
24
+ * - Falls back to the plugin's fallback image if invalid or missing
25
+ */
26
+ export declare function getSafeImageUrl(src: string | null | undefined): string;
27
+ //# sourceMappingURL=fallback.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fallback.d.ts","sourceRoot":"","sources":["fallback.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;GAGG;AACH,wBAAgB,mBAAmB,IAAI,MAAM,CAE5C;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,GAAG,IAAI,CAY/E;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO,CAkBvE;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,CAUtE"}
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Fallback image utility
3
+ * Provides a default fallback image URL when images fail to load or are invalid
4
+ * Also handles URL construction for image filenames
5
+ */
6
+ /**
7
+ * Returns the URL for the fallback "image not found" image
8
+ * Served from the plugin's API route
9
+ */
10
+ export function getFallbackImageUrl() {
11
+ return '/api/plugin-images/fallback';
12
+ }
13
+ /**
14
+ * Constructs the full image URL from a filename or URL
15
+ * - If it's already a full URL (http://, https://, or starts with /), returns as-is
16
+ * - If it's a filename, constructs `/api/uploads/${filename}`
17
+ */
18
+ export function constructImageUrl(src) {
19
+ if (!src || typeof src !== 'string') {
20
+ return null;
21
+ }
22
+ // If it's already a full URL (absolute or relative), return as-is
23
+ if (src.startsWith('http://') || src.startsWith('https://') || src.startsWith('/')) {
24
+ return src;
25
+ }
26
+ // Otherwise, it's a filename - construct the API URL
27
+ return `/api/uploads/${src}`;
28
+ }
29
+ /**
30
+ * Validates if a URL is valid and can be used with Next.js Image component
31
+ */
32
+ export function isValidImageUrl(url) {
33
+ if (!url || typeof url !== 'string') {
34
+ return false;
35
+ }
36
+ // Check if it's a valid URL format
37
+ try {
38
+ // For relative URLs (starting with /), they're valid
39
+ if (url.startsWith('/')) {
40
+ return true;
41
+ }
42
+ // For absolute URLs, validate the URL format
43
+ new URL(url);
44
+ return true;
45
+ }
46
+ catch (_a) {
47
+ return false;
48
+ }
49
+ }
50
+ /**
51
+ * Gets a safe image URL with automatic URL construction and fallback
52
+ * - Constructs the full URL if src is a filename
53
+ * - Falls back to the plugin's fallback image if invalid or missing
54
+ */
55
+ export function getSafeImageUrl(src) {
56
+ // First, construct the URL if it's a filename
57
+ const constructedUrl = constructImageUrl(src);
58
+ // Then validate and return, or fallback
59
+ if (isValidImageUrl(constructedUrl)) {
60
+ return constructedUrl;
61
+ }
62
+ return getFallbackImageUrl();
63
+ }