@qwanyx/carousel 0.1.2 → 0.1.3
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 +103 -2
- package/dist/index.mjs +103 -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,10 @@ 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"
|
|
1013
1039
|
},
|
|
1040
|
+
onDoubleClick: () => handleSlideDoubleClick(index),
|
|
1014
1041
|
children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(SlideRenderer, { slide, isActive: index === currentIndex, slideIndex: index })
|
|
1015
1042
|
},
|
|
1016
1043
|
slide.id
|
|
@@ -1249,6 +1276,80 @@ var Carousel = (0, import_react4.forwardRef)(
|
|
|
1249
1276
|
onDelete: onThumbnailDelete,
|
|
1250
1277
|
theme: theme === "auto" ? "light" : theme
|
|
1251
1278
|
}
|
|
1279
|
+
),
|
|
1280
|
+
editingIndex !== null && ImageEditor && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
1281
|
+
"div",
|
|
1282
|
+
{
|
|
1283
|
+
className: "qc-carousel__editor-overlay",
|
|
1284
|
+
style: {
|
|
1285
|
+
position: "fixed",
|
|
1286
|
+
top: 0,
|
|
1287
|
+
left: 0,
|
|
1288
|
+
right: 0,
|
|
1289
|
+
bottom: 0,
|
|
1290
|
+
zIndex: 9999,
|
|
1291
|
+
backgroundColor: theme === "dark" ? "#1a1a1a" : "#f5f5f5",
|
|
1292
|
+
display: "flex",
|
|
1293
|
+
flexDirection: "column"
|
|
1294
|
+
},
|
|
1295
|
+
children: [
|
|
1296
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
1297
|
+
"div",
|
|
1298
|
+
{
|
|
1299
|
+
style: {
|
|
1300
|
+
padding: "12px 16px",
|
|
1301
|
+
display: "flex",
|
|
1302
|
+
alignItems: "center",
|
|
1303
|
+
justifyContent: "space-between",
|
|
1304
|
+
borderBottom: `1px solid ${theme === "dark" ? "#333" : "#ddd"}`,
|
|
1305
|
+
backgroundColor: theme === "dark" ? "#242424" : "#fff"
|
|
1306
|
+
},
|
|
1307
|
+
children: [
|
|
1308
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { style: {
|
|
1309
|
+
color: theme === "dark" ? "#fff" : "#333",
|
|
1310
|
+
fontWeight: 500,
|
|
1311
|
+
fontSize: "16px"
|
|
1312
|
+
}, children: [
|
|
1313
|
+
"Edit Image ",
|
|
1314
|
+
editingIndex + 1,
|
|
1315
|
+
" / ",
|
|
1316
|
+
totalSlides
|
|
1317
|
+
] }),
|
|
1318
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1319
|
+
"button",
|
|
1320
|
+
{
|
|
1321
|
+
onClick: handleEditorCancel,
|
|
1322
|
+
style: {
|
|
1323
|
+
background: "none",
|
|
1324
|
+
border: "none",
|
|
1325
|
+
color: theme === "dark" ? "#aaa" : "#666",
|
|
1326
|
+
cursor: "pointer",
|
|
1327
|
+
fontSize: "24px",
|
|
1328
|
+
lineHeight: 1,
|
|
1329
|
+
padding: "4px"
|
|
1330
|
+
},
|
|
1331
|
+
children: "\xD7"
|
|
1332
|
+
}
|
|
1333
|
+
)
|
|
1334
|
+
]
|
|
1335
|
+
}
|
|
1336
|
+
),
|
|
1337
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: { flex: 1, minHeight: 0 }, children: (() => {
|
|
1338
|
+
const imageUrl = getEditingImageUrl();
|
|
1339
|
+
if (!imageUrl) return null;
|
|
1340
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1341
|
+
ImageEditor,
|
|
1342
|
+
{
|
|
1343
|
+
src: imageUrl,
|
|
1344
|
+
onSave: handleImageSave,
|
|
1345
|
+
onCancel: handleEditorCancel,
|
|
1346
|
+
aspectRatio: editorAspectRatio,
|
|
1347
|
+
theme: theme === "auto" ? "dark" : theme
|
|
1348
|
+
}
|
|
1349
|
+
);
|
|
1350
|
+
})() })
|
|
1351
|
+
]
|
|
1352
|
+
}
|
|
1252
1353
|
)
|
|
1253
1354
|
]
|
|
1254
1355
|
}
|
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,10 @@ 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"
|
|
978
1004
|
},
|
|
1005
|
+
onDoubleClick: () => handleSlideDoubleClick(index),
|
|
979
1006
|
children: /* @__PURE__ */ jsx3(SlideRenderer, { slide, isActive: index === currentIndex, slideIndex: index })
|
|
980
1007
|
},
|
|
981
1008
|
slide.id
|
|
@@ -1214,6 +1241,80 @@ var Carousel = forwardRef(
|
|
|
1214
1241
|
onDelete: onThumbnailDelete,
|
|
1215
1242
|
theme: theme === "auto" ? "light" : theme
|
|
1216
1243
|
}
|
|
1244
|
+
),
|
|
1245
|
+
editingIndex !== null && ImageEditor && /* @__PURE__ */ jsxs3(
|
|
1246
|
+
"div",
|
|
1247
|
+
{
|
|
1248
|
+
className: "qc-carousel__editor-overlay",
|
|
1249
|
+
style: {
|
|
1250
|
+
position: "fixed",
|
|
1251
|
+
top: 0,
|
|
1252
|
+
left: 0,
|
|
1253
|
+
right: 0,
|
|
1254
|
+
bottom: 0,
|
|
1255
|
+
zIndex: 9999,
|
|
1256
|
+
backgroundColor: theme === "dark" ? "#1a1a1a" : "#f5f5f5",
|
|
1257
|
+
display: "flex",
|
|
1258
|
+
flexDirection: "column"
|
|
1259
|
+
},
|
|
1260
|
+
children: [
|
|
1261
|
+
/* @__PURE__ */ jsxs3(
|
|
1262
|
+
"div",
|
|
1263
|
+
{
|
|
1264
|
+
style: {
|
|
1265
|
+
padding: "12px 16px",
|
|
1266
|
+
display: "flex",
|
|
1267
|
+
alignItems: "center",
|
|
1268
|
+
justifyContent: "space-between",
|
|
1269
|
+
borderBottom: `1px solid ${theme === "dark" ? "#333" : "#ddd"}`,
|
|
1270
|
+
backgroundColor: theme === "dark" ? "#242424" : "#fff"
|
|
1271
|
+
},
|
|
1272
|
+
children: [
|
|
1273
|
+
/* @__PURE__ */ jsxs3("span", { style: {
|
|
1274
|
+
color: theme === "dark" ? "#fff" : "#333",
|
|
1275
|
+
fontWeight: 500,
|
|
1276
|
+
fontSize: "16px"
|
|
1277
|
+
}, children: [
|
|
1278
|
+
"Edit Image ",
|
|
1279
|
+
editingIndex + 1,
|
|
1280
|
+
" / ",
|
|
1281
|
+
totalSlides
|
|
1282
|
+
] }),
|
|
1283
|
+
/* @__PURE__ */ jsx3(
|
|
1284
|
+
"button",
|
|
1285
|
+
{
|
|
1286
|
+
onClick: handleEditorCancel,
|
|
1287
|
+
style: {
|
|
1288
|
+
background: "none",
|
|
1289
|
+
border: "none",
|
|
1290
|
+
color: theme === "dark" ? "#aaa" : "#666",
|
|
1291
|
+
cursor: "pointer",
|
|
1292
|
+
fontSize: "24px",
|
|
1293
|
+
lineHeight: 1,
|
|
1294
|
+
padding: "4px"
|
|
1295
|
+
},
|
|
1296
|
+
children: "\xD7"
|
|
1297
|
+
}
|
|
1298
|
+
)
|
|
1299
|
+
]
|
|
1300
|
+
}
|
|
1301
|
+
),
|
|
1302
|
+
/* @__PURE__ */ jsx3("div", { style: { flex: 1, minHeight: 0 }, children: (() => {
|
|
1303
|
+
const imageUrl = getEditingImageUrl();
|
|
1304
|
+
if (!imageUrl) return null;
|
|
1305
|
+
return /* @__PURE__ */ jsx3(
|
|
1306
|
+
ImageEditor,
|
|
1307
|
+
{
|
|
1308
|
+
src: imageUrl,
|
|
1309
|
+
onSave: handleImageSave,
|
|
1310
|
+
onCancel: handleEditorCancel,
|
|
1311
|
+
aspectRatio: editorAspectRatio,
|
|
1312
|
+
theme: theme === "auto" ? "dark" : theme
|
|
1313
|
+
}
|
|
1314
|
+
);
|
|
1315
|
+
})() })
|
|
1316
|
+
]
|
|
1317
|
+
}
|
|
1217
1318
|
)
|
|
1218
1319
|
]
|
|
1219
1320
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@qwanyx/carousel",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
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",
|