@qwanyx/carousel 0.1.2 → 0.1.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/index.d.mts +15 -3
- package/dist/index.d.ts +15 -3
- package/dist/index.js +104 -2
- package/dist/index.mjs +104 -2
- package/package.json +8 -2
package/dist/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { CSSProperties, ReactNode } from 'react';
|
|
1
|
+
import React$1, { CSSProperties, ReactNode } from 'react';
|
|
2
2
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
3
3
|
|
|
4
4
|
/**
|
|
@@ -272,6 +272,18 @@ interface CarouselProps {
|
|
|
272
272
|
onThumbnailReorder?: (fromIndex: number, toIndex: number) => void;
|
|
273
273
|
/** Called when delete button is clicked on a thumbnail */
|
|
274
274
|
onThumbnailDelete?: (index: number) => void;
|
|
275
|
+
/** Called when an image is edited and saved (enables editing on double-click) */
|
|
276
|
+
onImageEdit?: (index: number, blob: Blob) => void;
|
|
277
|
+
/** Default aspect ratio for the image editor */
|
|
278
|
+
editorAspectRatio?: '4/3' | '16/9' | '1/1' | '3/4' | '9/16' | 'free';
|
|
279
|
+
/** ImageEditor component from @qwanyx/stack (pass it to enable editing) */
|
|
280
|
+
ImageEditor?: React.ComponentType<{
|
|
281
|
+
src: string;
|
|
282
|
+
onSave: (blob: Blob) => void;
|
|
283
|
+
onCancel?: () => void;
|
|
284
|
+
aspectRatio?: '4/3' | '16/9' | '1/1' | '3/4' | '9/16' | 'free';
|
|
285
|
+
theme?: 'light' | 'dark';
|
|
286
|
+
}>;
|
|
275
287
|
}
|
|
276
288
|
/**
|
|
277
289
|
* Carousel ref methods
|
|
@@ -305,7 +317,7 @@ declare function createImageSlide(id: string, src: string, options?: {
|
|
|
305
317
|
/**
|
|
306
318
|
* Qwanyx Carousel - Universal slide/presentation engine
|
|
307
319
|
*/
|
|
308
|
-
declare const Carousel: React.ForwardRefExoticComponent<CarouselProps & React.RefAttributes<CarouselRef>>;
|
|
320
|
+
declare const Carousel: React$1.ForwardRefExoticComponent<CarouselProps & React$1.RefAttributes<CarouselRef>>;
|
|
309
321
|
|
|
310
322
|
interface SlideRendererProps {
|
|
311
323
|
slide: Slide;
|
|
@@ -386,7 +398,7 @@ declare const createSlide: {
|
|
|
386
398
|
component: (id: string, render: (props: {
|
|
387
399
|
isActive: boolean;
|
|
388
400
|
slideIndex: number;
|
|
389
|
-
}) => React.ReactNode, options?: Partial<Omit<Slide, "id" | "layers">>) => Slide;
|
|
401
|
+
}) => React$1.ReactNode, options?: Partial<Omit<Slide, "id" | "layers">>) => Slide;
|
|
390
402
|
/**
|
|
391
403
|
* Create a slide to display a markdown file
|
|
392
404
|
*/
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { CSSProperties, ReactNode } from 'react';
|
|
1
|
+
import React$1, { CSSProperties, ReactNode } from 'react';
|
|
2
2
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
3
3
|
|
|
4
4
|
/**
|
|
@@ -272,6 +272,18 @@ interface CarouselProps {
|
|
|
272
272
|
onThumbnailReorder?: (fromIndex: number, toIndex: number) => void;
|
|
273
273
|
/** Called when delete button is clicked on a thumbnail */
|
|
274
274
|
onThumbnailDelete?: (index: number) => void;
|
|
275
|
+
/** Called when an image is edited and saved (enables editing on double-click) */
|
|
276
|
+
onImageEdit?: (index: number, blob: Blob) => void;
|
|
277
|
+
/** Default aspect ratio for the image editor */
|
|
278
|
+
editorAspectRatio?: '4/3' | '16/9' | '1/1' | '3/4' | '9/16' | 'free';
|
|
279
|
+
/** ImageEditor component from @qwanyx/stack (pass it to enable editing) */
|
|
280
|
+
ImageEditor?: React.ComponentType<{
|
|
281
|
+
src: string;
|
|
282
|
+
onSave: (blob: Blob) => void;
|
|
283
|
+
onCancel?: () => void;
|
|
284
|
+
aspectRatio?: '4/3' | '16/9' | '1/1' | '3/4' | '9/16' | 'free';
|
|
285
|
+
theme?: 'light' | 'dark';
|
|
286
|
+
}>;
|
|
275
287
|
}
|
|
276
288
|
/**
|
|
277
289
|
* Carousel ref methods
|
|
@@ -305,7 +317,7 @@ declare function createImageSlide(id: string, src: string, options?: {
|
|
|
305
317
|
/**
|
|
306
318
|
* Qwanyx Carousel - Universal slide/presentation engine
|
|
307
319
|
*/
|
|
308
|
-
declare const Carousel: React.ForwardRefExoticComponent<CarouselProps & React.RefAttributes<CarouselRef>>;
|
|
320
|
+
declare const Carousel: React$1.ForwardRefExoticComponent<CarouselProps & React$1.RefAttributes<CarouselRef>>;
|
|
309
321
|
|
|
310
322
|
interface SlideRendererProps {
|
|
311
323
|
slide: Slide;
|
|
@@ -386,7 +398,7 @@ declare const createSlide: {
|
|
|
386
398
|
component: (id: string, render: (props: {
|
|
387
399
|
isActive: boolean;
|
|
388
400
|
slideIndex: number;
|
|
389
|
-
}) => React.ReactNode, options?: Partial<Omit<Slide, "id" | "layers">>) => Slide;
|
|
401
|
+
}) => React$1.ReactNode, options?: Partial<Omit<Slide, "id" | "layers">>) => Slide;
|
|
390
402
|
/**
|
|
391
403
|
* Create a slide to display a markdown file
|
|
392
404
|
*/
|
package/dist/index.js
CHANGED
|
@@ -788,12 +788,37 @@ var Carousel = (0, import_react4.forwardRef)(
|
|
|
788
788
|
onCopySlide,
|
|
789
789
|
// Thumbnail callbacks
|
|
790
790
|
onThumbnailReorder,
|
|
791
|
-
onThumbnailDelete
|
|
791
|
+
onThumbnailDelete,
|
|
792
|
+
// Image editing
|
|
793
|
+
onImageEdit,
|
|
794
|
+
editorAspectRatio = "4/3",
|
|
795
|
+
ImageEditor
|
|
792
796
|
}, ref) => {
|
|
793
797
|
const containerRef = (0, import_react4.useRef)(null);
|
|
794
798
|
const [isFullscreen, setIsFullscreen] = (0, import_react4.useState)(false);
|
|
795
799
|
const [touchStart, setTouchStart] = (0, import_react4.useState)(null);
|
|
796
800
|
const [copiedState, setCopiedState] = (0, import_react4.useState)(null);
|
|
801
|
+
const [editingIndex, setEditingIndex] = (0, import_react4.useState)(null);
|
|
802
|
+
const canEdit = ImageEditor !== void 0 && onImageEdit !== void 0;
|
|
803
|
+
const handleSlideDoubleClick = (0, import_react4.useCallback)((index) => {
|
|
804
|
+
if (!canEdit) return;
|
|
805
|
+
setEditingIndex(index);
|
|
806
|
+
}, [canEdit]);
|
|
807
|
+
const handleImageSave = (0, import_react4.useCallback)((blob) => {
|
|
808
|
+
if (editingIndex !== null && onImageEdit) {
|
|
809
|
+
onImageEdit(editingIndex, blob);
|
|
810
|
+
}
|
|
811
|
+
setEditingIndex(null);
|
|
812
|
+
}, [editingIndex, onImageEdit]);
|
|
813
|
+
const handleEditorCancel = (0, import_react4.useCallback)(() => {
|
|
814
|
+
setEditingIndex(null);
|
|
815
|
+
}, []);
|
|
816
|
+
const getEditingImageUrl = (0, import_react4.useCallback)(() => {
|
|
817
|
+
if (editingIndex === null) return void 0;
|
|
818
|
+
const slide = slides[editingIndex];
|
|
819
|
+
if (!slide) return void 0;
|
|
820
|
+
return getSlideUrl ? getSlideUrl(slide) : extractSlideUrl(slide);
|
|
821
|
+
}, [editingIndex, slides, getSlideUrl]);
|
|
797
822
|
const copyToClipboard = (0, import_react4.useCallback)(async (text, type) => {
|
|
798
823
|
try {
|
|
799
824
|
await navigator.clipboard.writeText(text);
|
|
@@ -1009,8 +1034,11 @@ var Carousel = (0, import_react4.forwardRef)(
|
|
|
1009
1034
|
left: 0,
|
|
1010
1035
|
opacity: transition === "fade" ? index === currentIndex ? 1 : 0 : 1,
|
|
1011
1036
|
transition: `opacity ${transitionDuration}ms ease-in-out`,
|
|
1012
|
-
pointerEvents: index === currentIndex ? "auto" : "none"
|
|
1037
|
+
pointerEvents: index === currentIndex ? "auto" : "none",
|
|
1038
|
+
cursor: canEdit ? "pointer" : "default",
|
|
1039
|
+
zIndex: index === currentIndex ? 1 : 0
|
|
1013
1040
|
},
|
|
1041
|
+
onDoubleClick: () => handleSlideDoubleClick(index),
|
|
1014
1042
|
children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(SlideRenderer, { slide, isActive: index === currentIndex, slideIndex: index })
|
|
1015
1043
|
},
|
|
1016
1044
|
slide.id
|
|
@@ -1249,6 +1277,80 @@ var Carousel = (0, import_react4.forwardRef)(
|
|
|
1249
1277
|
onDelete: onThumbnailDelete,
|
|
1250
1278
|
theme: theme === "auto" ? "light" : theme
|
|
1251
1279
|
}
|
|
1280
|
+
),
|
|
1281
|
+
editingIndex !== null && ImageEditor && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
1282
|
+
"div",
|
|
1283
|
+
{
|
|
1284
|
+
className: "qc-carousel__editor-overlay",
|
|
1285
|
+
style: {
|
|
1286
|
+
position: "fixed",
|
|
1287
|
+
top: 0,
|
|
1288
|
+
left: 0,
|
|
1289
|
+
right: 0,
|
|
1290
|
+
bottom: 0,
|
|
1291
|
+
zIndex: 9999,
|
|
1292
|
+
backgroundColor: theme === "dark" ? "#1a1a1a" : "#f5f5f5",
|
|
1293
|
+
display: "flex",
|
|
1294
|
+
flexDirection: "column"
|
|
1295
|
+
},
|
|
1296
|
+
children: [
|
|
1297
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
1298
|
+
"div",
|
|
1299
|
+
{
|
|
1300
|
+
style: {
|
|
1301
|
+
padding: "12px 16px",
|
|
1302
|
+
display: "flex",
|
|
1303
|
+
alignItems: "center",
|
|
1304
|
+
justifyContent: "space-between",
|
|
1305
|
+
borderBottom: `1px solid ${theme === "dark" ? "#333" : "#ddd"}`,
|
|
1306
|
+
backgroundColor: theme === "dark" ? "#242424" : "#fff"
|
|
1307
|
+
},
|
|
1308
|
+
children: [
|
|
1309
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { style: {
|
|
1310
|
+
color: theme === "dark" ? "#fff" : "#333",
|
|
1311
|
+
fontWeight: 500,
|
|
1312
|
+
fontSize: "16px"
|
|
1313
|
+
}, children: [
|
|
1314
|
+
"Edit Image ",
|
|
1315
|
+
editingIndex + 1,
|
|
1316
|
+
" / ",
|
|
1317
|
+
totalSlides
|
|
1318
|
+
] }),
|
|
1319
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1320
|
+
"button",
|
|
1321
|
+
{
|
|
1322
|
+
onClick: handleEditorCancel,
|
|
1323
|
+
style: {
|
|
1324
|
+
background: "none",
|
|
1325
|
+
border: "none",
|
|
1326
|
+
color: theme === "dark" ? "#aaa" : "#666",
|
|
1327
|
+
cursor: "pointer",
|
|
1328
|
+
fontSize: "24px",
|
|
1329
|
+
lineHeight: 1,
|
|
1330
|
+
padding: "4px"
|
|
1331
|
+
},
|
|
1332
|
+
children: "\xD7"
|
|
1333
|
+
}
|
|
1334
|
+
)
|
|
1335
|
+
]
|
|
1336
|
+
}
|
|
1337
|
+
),
|
|
1338
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: { flex: 1, minHeight: 0 }, children: (() => {
|
|
1339
|
+
const imageUrl = getEditingImageUrl();
|
|
1340
|
+
if (!imageUrl) return null;
|
|
1341
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1342
|
+
ImageEditor,
|
|
1343
|
+
{
|
|
1344
|
+
src: imageUrl,
|
|
1345
|
+
onSave: handleImageSave,
|
|
1346
|
+
onCancel: handleEditorCancel,
|
|
1347
|
+
aspectRatio: editorAspectRatio,
|
|
1348
|
+
theme: theme === "auto" ? "dark" : theme
|
|
1349
|
+
}
|
|
1350
|
+
);
|
|
1351
|
+
})() })
|
|
1352
|
+
]
|
|
1353
|
+
}
|
|
1252
1354
|
)
|
|
1253
1355
|
]
|
|
1254
1356
|
}
|
package/dist/index.mjs
CHANGED
|
@@ -753,12 +753,37 @@ var Carousel = forwardRef(
|
|
|
753
753
|
onCopySlide,
|
|
754
754
|
// Thumbnail callbacks
|
|
755
755
|
onThumbnailReorder,
|
|
756
|
-
onThumbnailDelete
|
|
756
|
+
onThumbnailDelete,
|
|
757
|
+
// Image editing
|
|
758
|
+
onImageEdit,
|
|
759
|
+
editorAspectRatio = "4/3",
|
|
760
|
+
ImageEditor
|
|
757
761
|
}, ref) => {
|
|
758
762
|
const containerRef = useRef3(null);
|
|
759
763
|
const [isFullscreen, setIsFullscreen] = useState3(false);
|
|
760
764
|
const [touchStart, setTouchStart] = useState3(null);
|
|
761
765
|
const [copiedState, setCopiedState] = useState3(null);
|
|
766
|
+
const [editingIndex, setEditingIndex] = useState3(null);
|
|
767
|
+
const canEdit = ImageEditor !== void 0 && onImageEdit !== void 0;
|
|
768
|
+
const handleSlideDoubleClick = useCallback2((index) => {
|
|
769
|
+
if (!canEdit) return;
|
|
770
|
+
setEditingIndex(index);
|
|
771
|
+
}, [canEdit]);
|
|
772
|
+
const handleImageSave = useCallback2((blob) => {
|
|
773
|
+
if (editingIndex !== null && onImageEdit) {
|
|
774
|
+
onImageEdit(editingIndex, blob);
|
|
775
|
+
}
|
|
776
|
+
setEditingIndex(null);
|
|
777
|
+
}, [editingIndex, onImageEdit]);
|
|
778
|
+
const handleEditorCancel = useCallback2(() => {
|
|
779
|
+
setEditingIndex(null);
|
|
780
|
+
}, []);
|
|
781
|
+
const getEditingImageUrl = useCallback2(() => {
|
|
782
|
+
if (editingIndex === null) return void 0;
|
|
783
|
+
const slide = slides[editingIndex];
|
|
784
|
+
if (!slide) return void 0;
|
|
785
|
+
return getSlideUrl ? getSlideUrl(slide) : extractSlideUrl(slide);
|
|
786
|
+
}, [editingIndex, slides, getSlideUrl]);
|
|
762
787
|
const copyToClipboard = useCallback2(async (text, type) => {
|
|
763
788
|
try {
|
|
764
789
|
await navigator.clipboard.writeText(text);
|
|
@@ -974,8 +999,11 @@ var Carousel = forwardRef(
|
|
|
974
999
|
left: 0,
|
|
975
1000
|
opacity: transition === "fade" ? index === currentIndex ? 1 : 0 : 1,
|
|
976
1001
|
transition: `opacity ${transitionDuration}ms ease-in-out`,
|
|
977
|
-
pointerEvents: index === currentIndex ? "auto" : "none"
|
|
1002
|
+
pointerEvents: index === currentIndex ? "auto" : "none",
|
|
1003
|
+
cursor: canEdit ? "pointer" : "default",
|
|
1004
|
+
zIndex: index === currentIndex ? 1 : 0
|
|
978
1005
|
},
|
|
1006
|
+
onDoubleClick: () => handleSlideDoubleClick(index),
|
|
979
1007
|
children: /* @__PURE__ */ jsx3(SlideRenderer, { slide, isActive: index === currentIndex, slideIndex: index })
|
|
980
1008
|
},
|
|
981
1009
|
slide.id
|
|
@@ -1214,6 +1242,80 @@ var Carousel = forwardRef(
|
|
|
1214
1242
|
onDelete: onThumbnailDelete,
|
|
1215
1243
|
theme: theme === "auto" ? "light" : theme
|
|
1216
1244
|
}
|
|
1245
|
+
),
|
|
1246
|
+
editingIndex !== null && ImageEditor && /* @__PURE__ */ jsxs3(
|
|
1247
|
+
"div",
|
|
1248
|
+
{
|
|
1249
|
+
className: "qc-carousel__editor-overlay",
|
|
1250
|
+
style: {
|
|
1251
|
+
position: "fixed",
|
|
1252
|
+
top: 0,
|
|
1253
|
+
left: 0,
|
|
1254
|
+
right: 0,
|
|
1255
|
+
bottom: 0,
|
|
1256
|
+
zIndex: 9999,
|
|
1257
|
+
backgroundColor: theme === "dark" ? "#1a1a1a" : "#f5f5f5",
|
|
1258
|
+
display: "flex",
|
|
1259
|
+
flexDirection: "column"
|
|
1260
|
+
},
|
|
1261
|
+
children: [
|
|
1262
|
+
/* @__PURE__ */ jsxs3(
|
|
1263
|
+
"div",
|
|
1264
|
+
{
|
|
1265
|
+
style: {
|
|
1266
|
+
padding: "12px 16px",
|
|
1267
|
+
display: "flex",
|
|
1268
|
+
alignItems: "center",
|
|
1269
|
+
justifyContent: "space-between",
|
|
1270
|
+
borderBottom: `1px solid ${theme === "dark" ? "#333" : "#ddd"}`,
|
|
1271
|
+
backgroundColor: theme === "dark" ? "#242424" : "#fff"
|
|
1272
|
+
},
|
|
1273
|
+
children: [
|
|
1274
|
+
/* @__PURE__ */ jsxs3("span", { style: {
|
|
1275
|
+
color: theme === "dark" ? "#fff" : "#333",
|
|
1276
|
+
fontWeight: 500,
|
|
1277
|
+
fontSize: "16px"
|
|
1278
|
+
}, children: [
|
|
1279
|
+
"Edit Image ",
|
|
1280
|
+
editingIndex + 1,
|
|
1281
|
+
" / ",
|
|
1282
|
+
totalSlides
|
|
1283
|
+
] }),
|
|
1284
|
+
/* @__PURE__ */ jsx3(
|
|
1285
|
+
"button",
|
|
1286
|
+
{
|
|
1287
|
+
onClick: handleEditorCancel,
|
|
1288
|
+
style: {
|
|
1289
|
+
background: "none",
|
|
1290
|
+
border: "none",
|
|
1291
|
+
color: theme === "dark" ? "#aaa" : "#666",
|
|
1292
|
+
cursor: "pointer",
|
|
1293
|
+
fontSize: "24px",
|
|
1294
|
+
lineHeight: 1,
|
|
1295
|
+
padding: "4px"
|
|
1296
|
+
},
|
|
1297
|
+
children: "\xD7"
|
|
1298
|
+
}
|
|
1299
|
+
)
|
|
1300
|
+
]
|
|
1301
|
+
}
|
|
1302
|
+
),
|
|
1303
|
+
/* @__PURE__ */ jsx3("div", { style: { flex: 1, minHeight: 0 }, children: (() => {
|
|
1304
|
+
const imageUrl = getEditingImageUrl();
|
|
1305
|
+
if (!imageUrl) return null;
|
|
1306
|
+
return /* @__PURE__ */ jsx3(
|
|
1307
|
+
ImageEditor,
|
|
1308
|
+
{
|
|
1309
|
+
src: imageUrl,
|
|
1310
|
+
onSave: handleImageSave,
|
|
1311
|
+
onCancel: handleEditorCancel,
|
|
1312
|
+
aspectRatio: editorAspectRatio,
|
|
1313
|
+
theme: theme === "auto" ? "dark" : theme
|
|
1314
|
+
}
|
|
1315
|
+
);
|
|
1316
|
+
})() })
|
|
1317
|
+
]
|
|
1318
|
+
}
|
|
1217
1319
|
)
|
|
1218
1320
|
]
|
|
1219
1321
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@qwanyx/carousel",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"private": false,
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -27,7 +27,13 @@
|
|
|
27
27
|
},
|
|
28
28
|
"peerDependencies": {
|
|
29
29
|
"react": ">=18.0.0",
|
|
30
|
-
"react-dom": ">=18.0.0"
|
|
30
|
+
"react-dom": ">=18.0.0",
|
|
31
|
+
"@qwanyx/stack": ">=0.2.71"
|
|
32
|
+
},
|
|
33
|
+
"peerDependenciesMeta": {
|
|
34
|
+
"@qwanyx/stack": {
|
|
35
|
+
"optional": true
|
|
36
|
+
}
|
|
31
37
|
},
|
|
32
38
|
"devDependencies": {
|
|
33
39
|
"@types/react": "^18.2.0",
|