@expcat/tigercat-react 0.3.69 → 0.4.0

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 (45) hide show
  1. package/dist/chunk-2EOXY2LP.mjs +353 -0
  2. package/dist/chunk-5CLXOFRZ.mjs +248 -0
  3. package/dist/chunk-6W6CRBBG.mjs +169 -0
  4. package/dist/chunk-EHYSER2Z.js +144 -0
  5. package/dist/chunk-GNMOOYHG.js +250 -0
  6. package/dist/chunk-JWFEJ4XG.js +543 -0
  7. package/dist/chunk-NV3JUZ3N.js +57 -0
  8. package/dist/chunk-PJCY45UP.mjs +536 -0
  9. package/dist/chunk-QFYS5QIZ.mjs +142 -0
  10. package/dist/chunk-QIJG42YQ.mjs +54 -0
  11. package/dist/chunk-U3JOBIDU.js +355 -0
  12. package/dist/chunk-Z7SXK2KO.js +171 -0
  13. package/dist/components/ActivityFeed.js +4 -4
  14. package/dist/components/ActivityFeed.mjs +2 -2
  15. package/dist/components/CropUpload.d.mts +52 -0
  16. package/dist/components/CropUpload.d.ts +52 -0
  17. package/dist/components/CropUpload.js +14 -0
  18. package/dist/components/CropUpload.mjs +5 -0
  19. package/dist/components/Image.d.mts +20 -0
  20. package/dist/components/Image.d.ts +20 -0
  21. package/dist/components/Image.js +13 -0
  22. package/dist/components/Image.mjs +4 -0
  23. package/dist/components/ImageCropper.d.mts +21 -0
  24. package/dist/components/ImageCropper.d.ts +21 -0
  25. package/dist/components/ImageCropper.js +10 -0
  26. package/dist/components/ImageCropper.mjs +1 -0
  27. package/dist/components/ImageGroup.d.mts +30 -0
  28. package/dist/components/ImageGroup.d.ts +30 -0
  29. package/dist/components/ImageGroup.js +16 -0
  30. package/dist/components/ImageGroup.mjs +3 -0
  31. package/dist/components/ImagePreview.d.mts +20 -0
  32. package/dist/components/ImagePreview.d.ts +20 -0
  33. package/dist/components/ImagePreview.js +11 -0
  34. package/dist/components/ImagePreview.mjs +2 -0
  35. package/dist/components/TaskBoard.d.mts +13 -0
  36. package/dist/components/TaskBoard.d.ts +13 -0
  37. package/dist/components/TaskBoard.js +17 -0
  38. package/dist/components/TaskBoard.mjs +2 -0
  39. package/dist/index.d.mts +6 -0
  40. package/dist/index.d.ts +6 -0
  41. package/dist/index.js +108 -74
  42. package/dist/index.mjs +23 -17
  43. package/package.json +2 -2
  44. package/dist/{chunk-MTL2QUM3.mjs → chunk-FTY2W4L2.mjs} +1 -1
  45. package/dist/{chunk-J3HKED4B.js → chunk-IOM7DWWQ.js} +1 -1
@@ -0,0 +1,54 @@
1
+ import { ImagePreview } from './chunk-5CLXOFRZ.mjs';
2
+ import { createContext, useState, useRef, useCallback, useMemo } from 'react';
3
+ import { jsx, jsxs } from 'react/jsx-runtime';
4
+
5
+ var ImageGroupContext = createContext(null);
6
+ var ImageGroup = ({
7
+ preview = true,
8
+ onPreviewVisibleChange,
9
+ children,
10
+ className
11
+ }) => {
12
+ const [previewVisible, setPreviewVisible] = useState(false);
13
+ const [previewIndex, setPreviewIndex] = useState(0);
14
+ const imagesRef = useRef([]);
15
+ const register = useCallback((src) => {
16
+ const idx = imagesRef.current.length;
17
+ imagesRef.current = [...imagesRef.current, src];
18
+ return idx;
19
+ }, []);
20
+ const unregister = useCallback((src) => {
21
+ imagesRef.current = imagesRef.current.filter((s) => s !== src);
22
+ }, []);
23
+ const openPreview = useCallback(
24
+ (index) => {
25
+ if (!preview) return;
26
+ setPreviewIndex(index);
27
+ setPreviewVisible(true);
28
+ onPreviewVisibleChange?.(true);
29
+ },
30
+ [preview, onPreviewVisibleChange]
31
+ );
32
+ const contextValue = useMemo(
33
+ () => ({ register, unregister, openPreview }),
34
+ [register, unregister, openPreview]
35
+ );
36
+ return /* @__PURE__ */ jsx(ImageGroupContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsxs("div", { className: className || "tiger-image-group", role: "group", children: [
37
+ children,
38
+ preview && /* @__PURE__ */ jsx(
39
+ ImagePreview,
40
+ {
41
+ visible: previewVisible,
42
+ images: imagesRef.current,
43
+ currentIndex: previewIndex,
44
+ onVisibleChange: (val) => {
45
+ setPreviewVisible(val);
46
+ if (!val) onPreviewVisibleChange?.(false);
47
+ },
48
+ onCurrentIndexChange: setPreviewIndex
49
+ }
50
+ )
51
+ ] }) });
52
+ };
53
+
54
+ export { ImageGroup, ImageGroupContext };
@@ -0,0 +1,355 @@
1
+ 'use strict';
2
+
3
+ var react = require('react');
4
+ var tigercatCore = require('@expcat/tigercat-core');
5
+ var jsxRuntime = require('react/jsx-runtime');
6
+
7
+ // src/components/ImageCropper.tsx
8
+ var ImageCropper = react.forwardRef(
9
+ ({
10
+ src,
11
+ aspectRatio,
12
+ minWidth = 20,
13
+ minHeight = 20,
14
+ outputType = "image/png",
15
+ quality = 0.92,
16
+ guides = true,
17
+ className,
18
+ style,
19
+ onCropChange,
20
+ onReady
21
+ }, ref) => {
22
+ const containerRef = react.useRef(null);
23
+ const imageRef = react.useRef(null);
24
+ const [imageLoaded, setImageLoaded] = react.useState(false);
25
+ const [displayWidth, setDisplayWidth] = react.useState(0);
26
+ const [displayHeight, setDisplayHeight] = react.useState(0);
27
+ const [cropRect, setCropRect] = react.useState({ x: 0, y: 0, width: 0, height: 0 });
28
+ const dragModeRef = react.useRef("none");
29
+ const activeHandleRef = react.useRef(null);
30
+ const dragStartPosRef = react.useRef({ x: 0, y: 0 });
31
+ const dragStartRectRef = react.useRef({ x: 0, y: 0, width: 0, height: 0 });
32
+ const displayDimsRef = react.useRef({ w: 0, h: 0 });
33
+ react.useEffect(() => {
34
+ displayDimsRef.current = { w: displayWidth, h: displayHeight };
35
+ }, [displayWidth, displayHeight]);
36
+ react.useEffect(() => {
37
+ setImageLoaded(false);
38
+ const img = new window.Image();
39
+ img.crossOrigin = "anonymous";
40
+ img.onload = () => {
41
+ imageRef.current = img;
42
+ const container = containerRef.current;
43
+ const containerW = container ? container.clientWidth : img.naturalWidth;
44
+ const containerH = container ? container.clientHeight || 400 : img.naturalHeight;
45
+ const ratio = Math.min(containerW / img.naturalWidth, containerH / img.naturalHeight, 1);
46
+ const dw = img.naturalWidth * ratio;
47
+ const dh = img.naturalHeight * ratio;
48
+ setDisplayWidth(dw);
49
+ setDisplayHeight(dh);
50
+ displayDimsRef.current = { w: dw, h: dh };
51
+ const initial = tigercatCore.getInitialCropRect(dw, dh, aspectRatio);
52
+ setCropRect(initial);
53
+ setImageLoaded(true);
54
+ onReady?.();
55
+ };
56
+ img.src = src;
57
+ }, [src, aspectRatio, onReady]);
58
+ react.useImperativeHandle(
59
+ ref,
60
+ () => ({
61
+ getCropResult: () => {
62
+ return new Promise((resolve, reject) => {
63
+ if (!imageRef.current) {
64
+ reject(new Error("Image not loaded"));
65
+ return;
66
+ }
67
+ const { canvas, dataUrl } = tigercatCore.cropCanvas(
68
+ imageRef.current,
69
+ cropRect,
70
+ displayWidth,
71
+ displayHeight,
72
+ outputType,
73
+ quality
74
+ );
75
+ canvas.toBlob(
76
+ (blob) => {
77
+ if (blob) {
78
+ resolve({ canvas, blob, dataUrl, cropRect: { ...cropRect } });
79
+ } else {
80
+ reject(new Error("Failed to create blob"));
81
+ }
82
+ },
83
+ outputType,
84
+ quality
85
+ );
86
+ });
87
+ }
88
+ }),
89
+ [cropRect, displayWidth, displayHeight, outputType, quality]
90
+ );
91
+ const handleMouseDown = react.useCallback(
92
+ (e, mode, handle) => {
93
+ e.preventDefault();
94
+ e.stopPropagation();
95
+ dragModeRef.current = mode;
96
+ activeHandleRef.current = handle || null;
97
+ dragStartPosRef.current = { x: e.clientX, y: e.clientY };
98
+ dragStartRectRef.current = { ...cropRect };
99
+ const onMouseMove = (ev) => {
100
+ const dx = ev.clientX - dragStartPosRef.current.x;
101
+ const dy = ev.clientY - dragStartPosRef.current.y;
102
+ const dims = displayDimsRef.current;
103
+ let newRect;
104
+ if (dragModeRef.current === "move") {
105
+ newRect = tigercatCore.moveCropRect(dragStartRectRef.current, dx, dy, dims.w, dims.h);
106
+ } else {
107
+ newRect = tigercatCore.resizeCropRect(
108
+ dragStartRectRef.current,
109
+ activeHandleRef.current,
110
+ dx,
111
+ dy,
112
+ dims.w,
113
+ dims.h,
114
+ aspectRatio,
115
+ minWidth,
116
+ minHeight
117
+ );
118
+ }
119
+ setCropRect(newRect);
120
+ onCropChange?.(newRect);
121
+ };
122
+ const onMouseUp = () => {
123
+ dragModeRef.current = "none";
124
+ activeHandleRef.current = null;
125
+ document.removeEventListener("mousemove", onMouseMove);
126
+ document.removeEventListener("mouseup", onMouseUp);
127
+ };
128
+ document.addEventListener("mousemove", onMouseMove);
129
+ document.addEventListener("mouseup", onMouseUp);
130
+ },
131
+ [cropRect, aspectRatio, minWidth, minHeight, onCropChange]
132
+ );
133
+ const handleTouchStart = react.useCallback(
134
+ (e, mode, handle) => {
135
+ if (e.touches.length !== 1) return;
136
+ e.preventDefault();
137
+ e.stopPropagation();
138
+ const touch = e.touches[0];
139
+ dragModeRef.current = mode;
140
+ activeHandleRef.current = handle || null;
141
+ dragStartPosRef.current = { x: touch.clientX, y: touch.clientY };
142
+ dragStartRectRef.current = { ...cropRect };
143
+ const onTouchMove = (ev) => {
144
+ if (ev.touches.length !== 1) return;
145
+ const t = ev.touches[0];
146
+ const dx = t.clientX - dragStartPosRef.current.x;
147
+ const dy = t.clientY - dragStartPosRef.current.y;
148
+ const dims = displayDimsRef.current;
149
+ let newRect;
150
+ if (dragModeRef.current === "move") {
151
+ newRect = tigercatCore.moveCropRect(dragStartRectRef.current, dx, dy, dims.w, dims.h);
152
+ } else {
153
+ newRect = tigercatCore.resizeCropRect(
154
+ dragStartRectRef.current,
155
+ activeHandleRef.current,
156
+ dx,
157
+ dy,
158
+ dims.w,
159
+ dims.h,
160
+ aspectRatio,
161
+ minWidth,
162
+ minHeight
163
+ );
164
+ }
165
+ setCropRect(newRect);
166
+ onCropChange?.(newRect);
167
+ };
168
+ const onTouchEnd = () => {
169
+ dragModeRef.current = "none";
170
+ activeHandleRef.current = null;
171
+ document.removeEventListener("touchmove", onTouchMove);
172
+ document.removeEventListener("touchend", onTouchEnd);
173
+ };
174
+ document.addEventListener("touchmove", onTouchMove, { passive: false });
175
+ document.addEventListener("touchend", onTouchEnd);
176
+ },
177
+ [cropRect, aspectRatio, minWidth, minHeight, onCropChange]
178
+ );
179
+ const containerClasses = react.useMemo(
180
+ () => tigercatCore.classNames(tigercatCore.imageCropperContainerClasses, className),
181
+ [className]
182
+ );
183
+ const cr = cropRect;
184
+ if (!imageLoaded) {
185
+ return /* @__PURE__ */ jsxRuntime.jsx(
186
+ "div",
187
+ {
188
+ ref: containerRef,
189
+ className: tigercatCore.classNames(containerClasses, "flex items-center justify-center"),
190
+ style: { ...style, minHeight: "200px" },
191
+ role: "img",
192
+ "aria-label": "Loading image for cropping",
193
+ children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-8 h-8 border-2 border-white/30 border-t-white rounded-full animate-spin" })
194
+ }
195
+ );
196
+ }
197
+ return /* @__PURE__ */ jsxRuntime.jsxs(
198
+ "div",
199
+ {
200
+ ref: containerRef,
201
+ className: containerClasses,
202
+ style: {
203
+ ...style,
204
+ width: `${displayWidth}px`,
205
+ height: `${displayHeight}px`
206
+ },
207
+ role: "application",
208
+ "aria-label": "Image cropper",
209
+ "aria-roledescription": "image cropper",
210
+ children: [
211
+ /* @__PURE__ */ jsxRuntime.jsx(
212
+ "img",
213
+ {
214
+ src,
215
+ className: tigercatCore.imageCropperImgClasses,
216
+ style: { width: `${displayWidth}px`, height: `${displayHeight}px` },
217
+ draggable: false,
218
+ alt: "Image to crop"
219
+ }
220
+ ),
221
+ /* @__PURE__ */ jsxRuntime.jsxs(
222
+ "svg",
223
+ {
224
+ className: tigercatCore.imageCropperMaskClasses,
225
+ width: displayWidth,
226
+ height: displayHeight,
227
+ xmlns: "http://www.w3.org/2000/svg",
228
+ children: [
229
+ /* @__PURE__ */ jsxRuntime.jsx("defs", { children: /* @__PURE__ */ jsxRuntime.jsxs("mask", { id: "crop-mask", children: [
230
+ /* @__PURE__ */ jsxRuntime.jsx("rect", { width: displayWidth, height: displayHeight, fill: "white" }),
231
+ /* @__PURE__ */ jsxRuntime.jsx("rect", { x: cr.x, y: cr.y, width: cr.width, height: cr.height, fill: "black" })
232
+ ] }) }),
233
+ /* @__PURE__ */ jsxRuntime.jsx(
234
+ "rect",
235
+ {
236
+ width: displayWidth,
237
+ height: displayHeight,
238
+ fill: "var(--tiger-image-cropper-mask, rgba(0,0,0,0.55))",
239
+ mask: "url(#crop-mask)"
240
+ }
241
+ )
242
+ ]
243
+ }
244
+ ),
245
+ /* @__PURE__ */ jsxRuntime.jsx(
246
+ "div",
247
+ {
248
+ className: tigercatCore.imageCropperSelectionClasses,
249
+ style: {
250
+ left: `${cr.x}px`,
251
+ top: `${cr.y}px`,
252
+ width: `${cr.width}px`,
253
+ height: `${cr.height}px`
254
+ }
255
+ }
256
+ ),
257
+ /* @__PURE__ */ jsxRuntime.jsx(
258
+ "div",
259
+ {
260
+ className: tigercatCore.imageCropperDragAreaClasses,
261
+ style: {
262
+ left: `${cr.x}px`,
263
+ top: `${cr.y}px`,
264
+ width: `${cr.width}px`,
265
+ height: `${cr.height}px`
266
+ },
267
+ onMouseDown: (e) => handleMouseDown(e, "move"),
268
+ onTouchStart: (e) => handleTouchStart(e, "move")
269
+ }
270
+ ),
271
+ guides && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
272
+ /* @__PURE__ */ jsxRuntime.jsx(
273
+ "div",
274
+ {
275
+ className: tigercatCore.imageCropperGuideClasses,
276
+ style: {
277
+ left: `${cr.x}px`,
278
+ top: `${cr.y + cr.height / 3}px`,
279
+ width: `${cr.width}px`,
280
+ height: 0,
281
+ borderTopWidth: "1px",
282
+ borderTopStyle: "dashed"
283
+ }
284
+ }
285
+ ),
286
+ /* @__PURE__ */ jsxRuntime.jsx(
287
+ "div",
288
+ {
289
+ className: tigercatCore.imageCropperGuideClasses,
290
+ style: {
291
+ left: `${cr.x}px`,
292
+ top: `${cr.y + cr.height * 2 / 3}px`,
293
+ width: `${cr.width}px`,
294
+ height: 0,
295
+ borderTopWidth: "1px",
296
+ borderTopStyle: "dashed"
297
+ }
298
+ }
299
+ ),
300
+ /* @__PURE__ */ jsxRuntime.jsx(
301
+ "div",
302
+ {
303
+ className: tigercatCore.imageCropperGuideClasses,
304
+ style: {
305
+ left: `${cr.x + cr.width / 3}px`,
306
+ top: `${cr.y}px`,
307
+ width: 0,
308
+ height: `${cr.height}px`,
309
+ borderLeftWidth: "1px",
310
+ borderLeftStyle: "dashed"
311
+ }
312
+ }
313
+ ),
314
+ /* @__PURE__ */ jsxRuntime.jsx(
315
+ "div",
316
+ {
317
+ className: tigercatCore.imageCropperGuideClasses,
318
+ style: {
319
+ left: `${cr.x + cr.width * 2 / 3}px`,
320
+ top: `${cr.y}px`,
321
+ width: 0,
322
+ height: `${cr.height}px`,
323
+ borderLeftWidth: "1px",
324
+ borderLeftStyle: "dashed"
325
+ }
326
+ }
327
+ )
328
+ ] }),
329
+ tigercatCore.CROP_HANDLES.map((handle) => {
330
+ const pos = {};
331
+ if (handle.includes("n")) pos.top = `${cr.y}px`;
332
+ if (handle.includes("s")) pos.top = `${cr.y + cr.height}px`;
333
+ if (handle === "e" || handle === "w") pos.top = `${cr.y + cr.height / 2}px`;
334
+ if (handle.includes("w")) pos.left = `${cr.x}px`;
335
+ if (handle.includes("e")) pos.left = `${cr.x + cr.width}px`;
336
+ if (handle === "n" || handle === "s") pos.left = `${cr.x + cr.width / 2}px`;
337
+ return /* @__PURE__ */ jsxRuntime.jsx(
338
+ "div",
339
+ {
340
+ className: tigercatCore.getCropperHandleClasses(handle),
341
+ style: pos,
342
+ onMouseDown: (e) => handleMouseDown(e, "resize", handle),
343
+ onTouchStart: (e) => handleTouchStart(e, "resize", handle)
344
+ },
345
+ handle
346
+ );
347
+ })
348
+ ]
349
+ }
350
+ );
351
+ }
352
+ );
353
+ ImageCropper.displayName = "ImageCropper";
354
+
355
+ exports.ImageCropper = ImageCropper;
@@ -0,0 +1,171 @@
1
+ 'use strict';
2
+
3
+ var chunkNV3JUZ3N_js = require('./chunk-NV3JUZ3N.js');
4
+ var chunkGNMOOYHG_js = require('./chunk-GNMOOYHG.js');
5
+ var react = require('react');
6
+ var tigercatCore = require('@expcat/tigercat-core');
7
+ var jsxRuntime = require('react/jsx-runtime');
8
+
9
+ var SvgIcon = ({ d, className = "w-8 h-8" }) => /* @__PURE__ */ jsxRuntime.jsx(
10
+ "svg",
11
+ {
12
+ className,
13
+ xmlns: "http://www.w3.org/2000/svg",
14
+ fill: "none",
15
+ viewBox: "0 0 24 24",
16
+ stroke: "currentColor",
17
+ children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "1.5", d })
18
+ }
19
+ );
20
+ var Image = ({
21
+ src,
22
+ alt = "",
23
+ width,
24
+ height,
25
+ fit = "cover",
26
+ fallbackSrc,
27
+ preview = true,
28
+ lazy = false,
29
+ className,
30
+ errorRender,
31
+ placeholderRender,
32
+ onPreviewVisibleChange,
33
+ onClick,
34
+ onKeyDown,
35
+ style,
36
+ ...props
37
+ }) => {
38
+ const [loading, setLoading] = react.useState(true);
39
+ const [error, setError] = react.useState(false);
40
+ const [actualSrc, setActualSrc] = react.useState(lazy ? "" : src);
41
+ const [previewVisible, setPreviewVisible] = react.useState(false);
42
+ const containerRef = react.useRef(null);
43
+ const group = react.useContext(chunkNV3JUZ3N_js.ImageGroupContext);
44
+ const registeredIndexRef = react.useRef(-1);
45
+ react.useEffect(() => {
46
+ if (group && src) {
47
+ registeredIndexRef.current = group.register(src);
48
+ return () => {
49
+ group.unregister(src);
50
+ };
51
+ }
52
+ }, [group, src]);
53
+ react.useEffect(() => {
54
+ if (!lazy || !containerRef.current) return;
55
+ const observer = new IntersectionObserver(
56
+ (entries) => {
57
+ if (entries[0]?.isIntersecting) {
58
+ setActualSrc(src);
59
+ observer.disconnect();
60
+ }
61
+ },
62
+ { threshold: 0.01 }
63
+ );
64
+ observer.observe(containerRef.current);
65
+ return () => observer.disconnect();
66
+ }, [lazy, src]);
67
+ react.useEffect(() => {
68
+ if (!lazy) {
69
+ setActualSrc(src);
70
+ setError(false);
71
+ setLoading(true);
72
+ }
73
+ }, [src, lazy]);
74
+ const handleLoad = react.useCallback(() => {
75
+ setLoading(false);
76
+ setError(false);
77
+ }, []);
78
+ const handleError = react.useCallback(() => {
79
+ setLoading(false);
80
+ setError(true);
81
+ if (fallbackSrc && actualSrc !== fallbackSrc) {
82
+ setActualSrc(fallbackSrc);
83
+ setError(false);
84
+ setLoading(true);
85
+ }
86
+ }, [fallbackSrc, actualSrc]);
87
+ const handleClick = react.useCallback(
88
+ (e) => {
89
+ onClick?.(e);
90
+ if (!preview) return;
91
+ if (group) {
92
+ group.openPreview(registeredIndexRef.current >= 0 ? registeredIndexRef.current : 0);
93
+ } else {
94
+ setPreviewVisible(true);
95
+ onPreviewVisibleChange?.(true);
96
+ }
97
+ },
98
+ [preview, group, onClick, onPreviewVisibleChange]
99
+ );
100
+ const handleKeyDown = react.useCallback(
101
+ (e) => {
102
+ onKeyDown?.(e);
103
+ if (preview && (e.key === "Enter" || e.key === " ")) {
104
+ e.preventDefault();
105
+ handleClick(e);
106
+ }
107
+ },
108
+ [preview, handleClick, onKeyDown]
109
+ );
110
+ const containerClasses = react.useMemo(
111
+ () => tigercatCore.classNames(tigercatCore.imageBaseClasses, preview && tigercatCore.imagePreviewCursorClass, className),
112
+ [preview, className]
113
+ );
114
+ const imgClasses = react.useMemo(() => tigercatCore.getImageImgClasses(fit), [fit]);
115
+ const containerStyle = react.useMemo(() => {
116
+ const s = { ...style };
117
+ const w = tigercatCore.toCSSSize(width);
118
+ const h = tigercatCore.toCSSSize(height);
119
+ if (w) s.width = w;
120
+ if (h) s.height = h;
121
+ return s;
122
+ }, [width, height, style]);
123
+ let content;
124
+ if (error && !fallbackSrc) {
125
+ content = errorRender || /* @__PURE__ */ jsxRuntime.jsx("div", { className: tigercatCore.imageErrorClasses, children: /* @__PURE__ */ jsxRuntime.jsx(SvgIcon, { d: tigercatCore.imageErrorIconPath }) });
126
+ } else if (loading && !actualSrc) {
127
+ content = placeholderRender || /* @__PURE__ */ jsxRuntime.jsx("div", { className: tigercatCore.imageLoadingClasses, children: /* @__PURE__ */ jsxRuntime.jsx(SvgIcon, { d: tigercatCore.imageErrorIconPath }) });
128
+ } else {
129
+ content = /* @__PURE__ */ jsxRuntime.jsx(
130
+ "img",
131
+ {
132
+ src: actualSrc,
133
+ alt,
134
+ className: imgClasses,
135
+ onLoad: handleLoad,
136
+ onError: handleError
137
+ }
138
+ );
139
+ }
140
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
141
+ /* @__PURE__ */ jsxRuntime.jsx(
142
+ "div",
143
+ {
144
+ ...props,
145
+ ref: containerRef,
146
+ className: containerClasses,
147
+ style: containerStyle,
148
+ role: preview ? "button" : void 0,
149
+ tabIndex: preview ? 0 : void 0,
150
+ "aria-label": preview ? `Preview ${alt || "image"}` : void 0,
151
+ onClick: handleClick,
152
+ onKeyDown: handleKeyDown,
153
+ children: content
154
+ }
155
+ ),
156
+ !group && previewVisible && src && /* @__PURE__ */ jsxRuntime.jsx(
157
+ chunkGNMOOYHG_js.ImagePreview,
158
+ {
159
+ visible: previewVisible,
160
+ images: [src],
161
+ currentIndex: 0,
162
+ onVisibleChange: (val) => {
163
+ setPreviewVisible(val);
164
+ onPreviewVisibleChange?.(val);
165
+ }
166
+ }
167
+ )
168
+ ] });
169
+ };
170
+
171
+ exports.Image = Image;
@@ -2,10 +2,10 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- var chunkJ3HKED4B_js = require('../chunk-J3HKED4B.js');
5
+ var chunkIOM7DWWQ_js = require('../chunk-IOM7DWWQ.js');
6
6
  require('../chunk-PR3PQUKM.js');
7
- require('../chunk-QYYAXM5F.js');
8
7
  require('../chunk-2GKTVAAB.js');
8
+ require('../chunk-QYYAXM5F.js');
9
9
  require('../chunk-VCULFIZ5.js');
10
10
  require('../chunk-I5TCE5E7.js');
11
11
  require('../chunk-SSQOCZ6O.js');
@@ -15,9 +15,9 @@ require('../chunk-CI2WHAT2.js');
15
15
 
16
16
  Object.defineProperty(exports, "ActivityFeed", {
17
17
  enumerable: true,
18
- get: function () { return chunkJ3HKED4B_js.ActivityFeed; }
18
+ get: function () { return chunkIOM7DWWQ_js.ActivityFeed; }
19
19
  });
20
20
  Object.defineProperty(exports, "default", {
21
21
  enumerable: true,
22
- get: function () { return chunkJ3HKED4B_js.ActivityFeed_default; }
22
+ get: function () { return chunkIOM7DWWQ_js.ActivityFeed_default; }
23
23
  });
@@ -1,7 +1,7 @@
1
- export { ActivityFeed, ActivityFeed_default as default } from '../chunk-MTL2QUM3.mjs';
1
+ export { ActivityFeed, ActivityFeed_default as default } from '../chunk-FTY2W4L2.mjs';
2
2
  import '../chunk-JVTAKNRO.mjs';
3
- import '../chunk-XZVQ3PJS.mjs';
4
3
  import '../chunk-AVUXDQYO.mjs';
4
+ import '../chunk-XZVQ3PJS.mjs';
5
5
  import '../chunk-TGKNEMD4.mjs';
6
6
  import '../chunk-LIV33O73.mjs';
7
7
  import '../chunk-3M2IG6IN.mjs';
@@ -0,0 +1,52 @@
1
+ import React from 'react';
2
+ import { ImageCropperProps, CropResult } from '@expcat/tigercat-core';
3
+
4
+ interface CropUploadProps {
5
+ /**
6
+ * Accepted file types
7
+ * @default 'image/*'
8
+ */
9
+ accept?: string;
10
+ /**
11
+ * Whether the component is disabled
12
+ * @default false
13
+ */
14
+ disabled?: boolean;
15
+ /**
16
+ * Maximum file size in bytes
17
+ */
18
+ maxSize?: number;
19
+ /**
20
+ * Props to pass to the internal ImageCropper
21
+ */
22
+ cropperProps?: Partial<Omit<ImageCropperProps, 'src'>>;
23
+ /**
24
+ * Title for the crop modal
25
+ * @default '裁剪图片'
26
+ */
27
+ modalTitle?: string;
28
+ /**
29
+ * Width of the crop modal
30
+ * @default 520
31
+ */
32
+ modalWidth?: number;
33
+ /**
34
+ * Additional CSS classes
35
+ */
36
+ className?: string;
37
+ /**
38
+ * Custom trigger content
39
+ */
40
+ children?: React.ReactNode;
41
+ /**
42
+ * Callback after cropping completes
43
+ */
44
+ onCropComplete?: (result: CropResult) => void;
45
+ /**
46
+ * Callback on error
47
+ */
48
+ onError?: (error: Error) => void;
49
+ }
50
+ declare const CropUpload: React.FC<CropUploadProps>;
51
+
52
+ export { CropUpload, type CropUploadProps };