tee3apps-cms-sdk-react 0.0.13 → 0.0.14
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.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2 -2
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/PageComponents/Visual-Components/TabComponent.tsx +416 -105
package/package.json
CHANGED
|
@@ -326,6 +326,33 @@ const TabComponent: React.FC<TabComponentMainProps> = ({ props, deviceMode = 'we
|
|
|
326
326
|
setCarouselIndex(0);
|
|
327
327
|
};
|
|
328
328
|
|
|
329
|
+
// Helper function to get sliding window indices for grid layouts
|
|
330
|
+
const getSlidingWindowIndices = (totalItems: number, itemsPerView: number, currentIndex: number): number[] => {
|
|
331
|
+
if (totalItems <= itemsPerView) {
|
|
332
|
+
// If total items <= items per view, show all items
|
|
333
|
+
return Array.from({ length: totalItems }, (_, i) => i);
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
// Calculate max possible index for sliding window
|
|
337
|
+
// For sliding window, we can slide until the last item is shown
|
|
338
|
+
// Max index is when we show the last itemsPerView items
|
|
339
|
+
const maxIndex = totalItems - itemsPerView;
|
|
340
|
+
const clampedIndex = Math.min(Math.max(0, currentIndex), maxIndex);
|
|
341
|
+
|
|
342
|
+
// Sliding window: start from clampedIndex, show itemsPerView items
|
|
343
|
+
return Array.from({ length: itemsPerView }, (_, i) => clampedIndex + i);
|
|
344
|
+
};
|
|
345
|
+
|
|
346
|
+
// Helper function to calculate max carousel index for grid layouts
|
|
347
|
+
const getMaxCarouselIndex = (totalItems: number, itemsPerView: number): number => {
|
|
348
|
+
if (totalItems <= itemsPerView) {
|
|
349
|
+
return 0; // No carousel needed
|
|
350
|
+
}
|
|
351
|
+
// For sliding window, max index is when we show the last itemsPerView items
|
|
352
|
+
// This allows us to slide through all items with overlapping windows
|
|
353
|
+
return Math.max(0, totalItems - itemsPerView);
|
|
354
|
+
};
|
|
355
|
+
|
|
329
356
|
const getCurrentLayout = (tab: TabItem): string => {
|
|
330
357
|
switch (deviceMode) {
|
|
331
358
|
case 'mobileweb': return tab.mode.mobileweb.layout;
|
|
@@ -599,7 +626,7 @@ const TabComponent: React.FC<TabComponentMainProps> = ({ props, deviceMode = 'we
|
|
|
599
626
|
);
|
|
600
627
|
}
|
|
601
628
|
|
|
602
|
-
// Other layouts: grid display with
|
|
629
|
+
// Other layouts: grid display with sliding window carousel
|
|
603
630
|
const getMaxImages = () => {
|
|
604
631
|
switch (layout) {
|
|
605
632
|
case '1x2': return 2;
|
|
@@ -609,8 +636,11 @@ const TabComponent: React.FC<TabComponentMainProps> = ({ props, deviceMode = 'we
|
|
|
609
636
|
}
|
|
610
637
|
};
|
|
611
638
|
|
|
612
|
-
const
|
|
613
|
-
const
|
|
639
|
+
const itemsPerView = getMaxImages();
|
|
640
|
+
const maxCarouselIndex = getMaxCarouselIndex(images.length, itemsPerView);
|
|
641
|
+
const displayIndices = getSlidingWindowIndices(images.length, itemsPerView, carouselIndex);
|
|
642
|
+
const displayImages = displayIndices.map(idx => images[idx]);
|
|
643
|
+
const needsCarousel = images.length > itemsPerView;
|
|
614
644
|
|
|
615
645
|
// Create dynamic content style for GROUPIMAGE
|
|
616
646
|
const groupImageContentStyle = {
|
|
@@ -623,46 +653,137 @@ const TabComponent: React.FC<TabComponentMainProps> = ({ props, deviceMode = 'we
|
|
|
623
653
|
};
|
|
624
654
|
|
|
625
655
|
return (
|
|
626
|
-
<div style={
|
|
627
|
-
{
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
656
|
+
<div style={{ position: 'relative', width: '100%' }}>
|
|
657
|
+
<div style={groupImageContentStyle} className='media-box'>
|
|
658
|
+
{displayImages.map((image, displayIndex) => {
|
|
659
|
+
const originalIndex = displayIndices[displayIndex];
|
|
660
|
+
const linkUrl = buildLinkForSlide(image);
|
|
661
|
+
const imageElement = (
|
|
662
|
+
<div key={originalIndex} className="media-box">
|
|
663
|
+
<img
|
|
664
|
+
src={getImageUrl(
|
|
665
|
+
tab.tabContentGroupImage.type === 'DYNAMIC'
|
|
666
|
+
? image.image.url
|
|
667
|
+
: image.attr?.url
|
|
668
|
+
)}
|
|
669
|
+
alt={
|
|
670
|
+
tab.tabContentGroupImage.type === 'DYNAMIC'
|
|
671
|
+
? image.image.alt
|
|
672
|
+
: image.attr?.alt
|
|
673
|
+
}
|
|
674
|
+
className="media-content"
|
|
675
|
+
/>
|
|
676
|
+
</div>
|
|
677
|
+
);
|
|
678
|
+
|
|
679
|
+
return linkUrl ? (
|
|
680
|
+
<a
|
|
681
|
+
key={originalIndex}
|
|
682
|
+
href={linkUrl}
|
|
683
|
+
target={
|
|
684
|
+
image.link_type === 'EXTERNALLINK'
|
|
685
|
+
? image.external_link?.target || '_blank'
|
|
686
|
+
: '_self'
|
|
641
687
|
}
|
|
642
|
-
className=
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
688
|
+
className='media-box'
|
|
689
|
+
>
|
|
690
|
+
{imageElement}
|
|
691
|
+
</a>
|
|
692
|
+
) : (
|
|
693
|
+
<div key={originalIndex} style={{ width: '100%', height: '100%' }}>
|
|
694
|
+
{imageElement}
|
|
695
|
+
</div>
|
|
696
|
+
);
|
|
697
|
+
})}
|
|
698
|
+
</div>
|
|
699
|
+
|
|
700
|
+
{/* Carousel Navigation for Grid Layouts */}
|
|
701
|
+
{needsCarousel && (
|
|
702
|
+
<>
|
|
703
|
+
{/* Previous Button */}
|
|
704
|
+
<button
|
|
705
|
+
onClick={prevCarouselItem}
|
|
706
|
+
disabled={carouselIndex === 0}
|
|
707
|
+
style={{
|
|
708
|
+
position: 'absolute',
|
|
709
|
+
left: '10px',
|
|
710
|
+
top: '50%',
|
|
711
|
+
transform: 'translateY(-50%)',
|
|
712
|
+
background: 'rgba(0,0,0,0.5)',
|
|
713
|
+
color: 'white',
|
|
714
|
+
border: 'none',
|
|
715
|
+
borderRadius: '50%',
|
|
716
|
+
width: '40px',
|
|
717
|
+
height: '40px',
|
|
718
|
+
cursor: carouselIndex === 0 ? 'not-allowed' : 'pointer',
|
|
719
|
+
opacity: carouselIndex === 0 ? 0.5 : 1,
|
|
720
|
+
display: 'flex',
|
|
721
|
+
alignItems: 'center',
|
|
722
|
+
justifyContent: 'center',
|
|
723
|
+
fontSize: '18px',
|
|
724
|
+
zIndex: 10,
|
|
725
|
+
}}
|
|
657
726
|
>
|
|
658
|
-
|
|
659
|
-
</
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
727
|
+
‹
|
|
728
|
+
</button>
|
|
729
|
+
|
|
730
|
+
{/* Next Button */}
|
|
731
|
+
<button
|
|
732
|
+
onClick={nextCarouselItem}
|
|
733
|
+
disabled={carouselIndex >= maxCarouselIndex}
|
|
734
|
+
style={{
|
|
735
|
+
position: 'absolute',
|
|
736
|
+
right: '10px',
|
|
737
|
+
top: '50%',
|
|
738
|
+
transform: 'translateY(-50%)',
|
|
739
|
+
background: 'rgba(0,0,0,0.5)',
|
|
740
|
+
color: 'white',
|
|
741
|
+
border: 'none',
|
|
742
|
+
borderRadius: '50%',
|
|
743
|
+
width: '40px',
|
|
744
|
+
height: '40px',
|
|
745
|
+
cursor: carouselIndex >= maxCarouselIndex ? 'not-allowed' : 'pointer',
|
|
746
|
+
opacity: carouselIndex >= maxCarouselIndex ? 0.5 : 1,
|
|
747
|
+
display: 'flex',
|
|
748
|
+
alignItems: 'center',
|
|
749
|
+
justifyContent: 'center',
|
|
750
|
+
fontSize: '18px',
|
|
751
|
+
zIndex: 10,
|
|
752
|
+
}}
|
|
753
|
+
>
|
|
754
|
+
›
|
|
755
|
+
</button>
|
|
756
|
+
|
|
757
|
+
{/* Dots Indicator */}
|
|
758
|
+
<div
|
|
759
|
+
style={{
|
|
760
|
+
position: 'absolute',
|
|
761
|
+
bottom: '10px',
|
|
762
|
+
left: '50%',
|
|
763
|
+
transform: 'translateX(-50%)',
|
|
764
|
+
display: 'flex',
|
|
765
|
+
gap: '8px',
|
|
766
|
+
zIndex: 10,
|
|
767
|
+
}}
|
|
768
|
+
>
|
|
769
|
+
{Array.from({ length: maxCarouselIndex + 1 }, (_, index) => (
|
|
770
|
+
<button
|
|
771
|
+
key={index}
|
|
772
|
+
onClick={() => goToCarouselItem(index)}
|
|
773
|
+
style={{
|
|
774
|
+
width: index === carouselIndex ? '12px' : '8px',
|
|
775
|
+
height: index === carouselIndex ? '12px' : '8px',
|
|
776
|
+
borderRadius: '50%',
|
|
777
|
+
border: 'none',
|
|
778
|
+
background: index === carouselIndex ? 'white' : 'rgba(255,255,255,0.5)',
|
|
779
|
+
cursor: 'pointer',
|
|
780
|
+
transition: 'all 0.3s ease',
|
|
781
|
+
}}
|
|
782
|
+
/>
|
|
783
|
+
))}
|
|
663
784
|
</div>
|
|
664
|
-
|
|
665
|
-
|
|
785
|
+
</>
|
|
786
|
+
)}
|
|
666
787
|
</div>
|
|
667
788
|
);
|
|
668
789
|
|
|
@@ -827,7 +948,7 @@ const TabComponent: React.FC<TabComponentMainProps> = ({ props, deviceMode = 'we
|
|
|
827
948
|
);
|
|
828
949
|
}
|
|
829
950
|
|
|
830
|
-
// Other layouts: grid display with
|
|
951
|
+
// Other layouts: grid display with sliding window carousel
|
|
831
952
|
const getMaxVideos = () => {
|
|
832
953
|
switch (layout) {
|
|
833
954
|
case '1x2': return 2;
|
|
@@ -837,8 +958,11 @@ const TabComponent: React.FC<TabComponentMainProps> = ({ props, deviceMode = 'we
|
|
|
837
958
|
}
|
|
838
959
|
};
|
|
839
960
|
|
|
840
|
-
const
|
|
841
|
-
const
|
|
961
|
+
const itemsPerView = getMaxVideos();
|
|
962
|
+
const maxCarouselIndex = getMaxCarouselIndex(videos.length, itemsPerView);
|
|
963
|
+
const displayIndices = getSlidingWindowIndices(videos.length, itemsPerView, carouselIndex);
|
|
964
|
+
const displayVideos = displayIndices.map(idx => videos[idx]);
|
|
965
|
+
const needsCarousel = videos.length > itemsPerView;
|
|
842
966
|
|
|
843
967
|
// Create dynamic content style for GROUPVIDEO
|
|
844
968
|
const groupVideoContentStyle = {
|
|
@@ -851,49 +975,140 @@ const TabComponent: React.FC<TabComponentMainProps> = ({ props, deviceMode = 'we
|
|
|
851
975
|
};
|
|
852
976
|
|
|
853
977
|
return (
|
|
854
|
-
<div style={
|
|
855
|
-
{
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
978
|
+
<div style={{ position: 'relative', width: '100%' }}>
|
|
979
|
+
<div style={groupVideoContentStyle} className='media-box'>
|
|
980
|
+
{displayVideos.map((video, displayIndex) => {
|
|
981
|
+
const originalIndex = displayIndices[displayIndex];
|
|
982
|
+
const linkUrl = buildLinkForSlide(video);
|
|
983
|
+
|
|
984
|
+
const videoElement = (
|
|
985
|
+
<div key={originalIndex} className="media-box">
|
|
986
|
+
<video
|
|
987
|
+
src={getImageUrl(
|
|
988
|
+
tab.tabContentGroupVideo.type === 'DYNAMIC'
|
|
989
|
+
? video.video?.url
|
|
990
|
+
: video.attr?.url
|
|
991
|
+
)}
|
|
992
|
+
title={
|
|
993
|
+
tab.tabContentGroupVideo.type === 'DYNAMIC'
|
|
994
|
+
? video.video?.alt || video.name
|
|
995
|
+
: video.attr?.alt
|
|
996
|
+
}
|
|
997
|
+
className="media-content"
|
|
998
|
+
controls
|
|
999
|
+
style={{ width: '100%', height: 'auto', objectFit: 'cover' }}
|
|
1000
|
+
/>
|
|
1001
|
+
</div>
|
|
1002
|
+
);
|
|
877
1003
|
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
1004
|
+
return linkUrl ? (
|
|
1005
|
+
<a
|
|
1006
|
+
key={originalIndex}
|
|
1007
|
+
href={linkUrl}
|
|
1008
|
+
target={
|
|
1009
|
+
video.link_type === 'EXTERNALLINK'
|
|
1010
|
+
? video.external_link?.target || '_blank'
|
|
1011
|
+
: '_self'
|
|
1012
|
+
}
|
|
1013
|
+
className='media-box'
|
|
1014
|
+
>
|
|
1015
|
+
{videoElement}
|
|
1016
|
+
</a>
|
|
1017
|
+
) : (
|
|
1018
|
+
<div key={originalIndex} style={{ width: '100%', height: '100%' }}>
|
|
1019
|
+
{videoElement}
|
|
1020
|
+
</div>
|
|
1021
|
+
);
|
|
1022
|
+
})}
|
|
1023
|
+
</div>
|
|
1024
|
+
|
|
1025
|
+
{/* Carousel Navigation for Grid Layouts */}
|
|
1026
|
+
{needsCarousel && (
|
|
1027
|
+
<>
|
|
1028
|
+
{/* Previous Button */}
|
|
1029
|
+
<button
|
|
1030
|
+
onClick={prevCarouselItem}
|
|
1031
|
+
disabled={carouselIndex === 0}
|
|
1032
|
+
style={{
|
|
1033
|
+
position: 'absolute',
|
|
1034
|
+
left: '10px',
|
|
1035
|
+
top: '50%',
|
|
1036
|
+
transform: 'translateY(-50%)',
|
|
1037
|
+
background: 'rgba(0,0,0,0.5)',
|
|
1038
|
+
color: 'white',
|
|
1039
|
+
border: 'none',
|
|
1040
|
+
borderRadius: '50%',
|
|
1041
|
+
width: '40px',
|
|
1042
|
+
height: '40px',
|
|
1043
|
+
cursor: carouselIndex === 0 ? 'not-allowed' : 'pointer',
|
|
1044
|
+
opacity: carouselIndex === 0 ? 0.5 : 1,
|
|
1045
|
+
display: 'flex',
|
|
1046
|
+
alignItems: 'center',
|
|
1047
|
+
justifyContent: 'center',
|
|
1048
|
+
fontSize: '18px',
|
|
1049
|
+
zIndex: 10,
|
|
1050
|
+
}}
|
|
888
1051
|
>
|
|
889
|
-
|
|
890
|
-
</
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
1052
|
+
‹
|
|
1053
|
+
</button>
|
|
1054
|
+
|
|
1055
|
+
{/* Next Button */}
|
|
1056
|
+
<button
|
|
1057
|
+
onClick={nextCarouselItem}
|
|
1058
|
+
disabled={carouselIndex >= maxCarouselIndex}
|
|
1059
|
+
style={{
|
|
1060
|
+
position: 'absolute',
|
|
1061
|
+
right: '10px',
|
|
1062
|
+
top: '50%',
|
|
1063
|
+
transform: 'translateY(-50%)',
|
|
1064
|
+
background: 'rgba(0,0,0,0.5)',
|
|
1065
|
+
color: 'white',
|
|
1066
|
+
border: 'none',
|
|
1067
|
+
borderRadius: '50%',
|
|
1068
|
+
width: '40px',
|
|
1069
|
+
height: '40px',
|
|
1070
|
+
cursor: carouselIndex >= maxCarouselIndex ? 'not-allowed' : 'pointer',
|
|
1071
|
+
opacity: carouselIndex >= maxCarouselIndex ? 0.5 : 1,
|
|
1072
|
+
display: 'flex',
|
|
1073
|
+
alignItems: 'center',
|
|
1074
|
+
justifyContent: 'center',
|
|
1075
|
+
fontSize: '18px',
|
|
1076
|
+
zIndex: 10,
|
|
1077
|
+
}}
|
|
1078
|
+
>
|
|
1079
|
+
›
|
|
1080
|
+
</button>
|
|
1081
|
+
|
|
1082
|
+
{/* Dots Indicator */}
|
|
1083
|
+
<div
|
|
1084
|
+
style={{
|
|
1085
|
+
position: 'absolute',
|
|
1086
|
+
bottom: '10px',
|
|
1087
|
+
left: '50%',
|
|
1088
|
+
transform: 'translateX(-50%)',
|
|
1089
|
+
display: 'flex',
|
|
1090
|
+
gap: '8px',
|
|
1091
|
+
zIndex: 10,
|
|
1092
|
+
}}
|
|
1093
|
+
>
|
|
1094
|
+
{Array.from({ length: maxCarouselIndex + 1 }, (_, index) => (
|
|
1095
|
+
<button
|
|
1096
|
+
key={index}
|
|
1097
|
+
onClick={() => goToCarouselItem(index)}
|
|
1098
|
+
style={{
|
|
1099
|
+
width: index === carouselIndex ? '12px' : '8px',
|
|
1100
|
+
height: index === carouselIndex ? '12px' : '8px',
|
|
1101
|
+
borderRadius: '50%',
|
|
1102
|
+
border: 'none',
|
|
1103
|
+
background: index === carouselIndex ? 'white' : 'rgba(255,255,255,0.5)',
|
|
1104
|
+
cursor: 'pointer',
|
|
1105
|
+
transition: 'all 0.3s ease',
|
|
1106
|
+
}}
|
|
1107
|
+
/>
|
|
1108
|
+
))}
|
|
894
1109
|
</div>
|
|
895
|
-
|
|
896
|
-
|
|
1110
|
+
</>
|
|
1111
|
+
)}
|
|
897
1112
|
</div>
|
|
898
1113
|
);
|
|
899
1114
|
|
|
@@ -1023,7 +1238,7 @@ const TabComponent: React.FC<TabComponentMainProps> = ({ props, deviceMode = 'we
|
|
|
1023
1238
|
);
|
|
1024
1239
|
}
|
|
1025
1240
|
|
|
1026
|
-
// Other layouts: Grid view with
|
|
1241
|
+
// Other layouts: Grid view with sliding window carousel
|
|
1027
1242
|
const getMaxProducts = () => {
|
|
1028
1243
|
switch (layout) {
|
|
1029
1244
|
case '1x2': return 2;
|
|
@@ -1033,8 +1248,11 @@ const TabComponent: React.FC<TabComponentMainProps> = ({ props, deviceMode = 'we
|
|
|
1033
1248
|
}
|
|
1034
1249
|
};
|
|
1035
1250
|
|
|
1036
|
-
const
|
|
1037
|
-
const
|
|
1251
|
+
const itemsPerView = getMaxProducts();
|
|
1252
|
+
const maxCarouselIndex = getMaxCarouselIndex(products.length, itemsPerView);
|
|
1253
|
+
const displayIndices = getSlidingWindowIndices(products.length, itemsPerView, carouselIndex);
|
|
1254
|
+
const displayProducts = displayIndices.map(idx => products[idx]);
|
|
1255
|
+
const needsCarousel = products.length > itemsPerView;
|
|
1038
1256
|
|
|
1039
1257
|
// Create dynamic content style for GROUPPRODUCT
|
|
1040
1258
|
const groupProductContentStyle = {
|
|
@@ -1049,26 +1267,119 @@ const TabComponent: React.FC<TabComponentMainProps> = ({ props, deviceMode = 'we
|
|
|
1049
1267
|
};
|
|
1050
1268
|
|
|
1051
1269
|
return (
|
|
1052
|
-
<div style={
|
|
1053
|
-
{
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1270
|
+
<div style={{ position: 'relative', width: '100%' }}>
|
|
1271
|
+
<div style={groupProductContentStyle}>
|
|
1272
|
+
{displayProducts.map((product, displayIndex) => {
|
|
1273
|
+
const originalIndex = displayIndices[displayIndex];
|
|
1274
|
+
return (
|
|
1275
|
+
<div
|
|
1276
|
+
key={originalIndex}
|
|
1277
|
+
style={{
|
|
1278
|
+
width: '100%',
|
|
1279
|
+
height: '100%',
|
|
1280
|
+
display: 'flex',
|
|
1281
|
+
alignItems: 'stretch',
|
|
1282
|
+
justifyContent: 'center',
|
|
1283
|
+
minHeight: '200px',
|
|
1284
|
+
}}
|
|
1285
|
+
>
|
|
1286
|
+
<ProductCard product={product} layout={layout} />
|
|
1287
|
+
</div>
|
|
1288
|
+
);
|
|
1289
|
+
})}
|
|
1290
|
+
</div>
|
|
1291
|
+
|
|
1292
|
+
{/* Carousel Navigation for Grid Layouts */}
|
|
1293
|
+
{needsCarousel && (
|
|
1294
|
+
<>
|
|
1295
|
+
{/* Previous Button */}
|
|
1296
|
+
<button
|
|
1297
|
+
onClick={prevCarouselItem}
|
|
1298
|
+
disabled={carouselIndex === 0}
|
|
1299
|
+
style={{
|
|
1300
|
+
position: 'absolute',
|
|
1301
|
+
left: '10px',
|
|
1302
|
+
top: '50%',
|
|
1303
|
+
transform: 'translateY(-50%)',
|
|
1304
|
+
background: 'rgba(0,0,0,0.5)',
|
|
1305
|
+
color: 'white',
|
|
1306
|
+
border: 'none',
|
|
1307
|
+
borderRadius: '50%',
|
|
1308
|
+
width: '40px',
|
|
1309
|
+
height: '40px',
|
|
1310
|
+
cursor: carouselIndex === 0 ? 'not-allowed' : 'pointer',
|
|
1311
|
+
opacity: carouselIndex === 0 ? 0.5 : 1,
|
|
1312
|
+
display: 'flex',
|
|
1313
|
+
alignItems: 'center',
|
|
1314
|
+
justifyContent: 'center',
|
|
1315
|
+
fontSize: '18px',
|
|
1316
|
+
zIndex: 10,
|
|
1317
|
+
}}
|
|
1318
|
+
>
|
|
1319
|
+
‹
|
|
1320
|
+
</button>
|
|
1321
|
+
|
|
1322
|
+
{/* Next Button */}
|
|
1323
|
+
<button
|
|
1324
|
+
onClick={nextCarouselItem}
|
|
1325
|
+
disabled={carouselIndex >= maxCarouselIndex}
|
|
1326
|
+
style={{
|
|
1327
|
+
position: 'absolute',
|
|
1328
|
+
right: '10px',
|
|
1329
|
+
top: '50%',
|
|
1330
|
+
transform: 'translateY(-50%)',
|
|
1331
|
+
background: 'rgba(0,0,0,0.5)',
|
|
1332
|
+
color: 'white',
|
|
1333
|
+
border: 'none',
|
|
1334
|
+
borderRadius: '50%',
|
|
1335
|
+
width: '40px',
|
|
1336
|
+
height: '40px',
|
|
1337
|
+
cursor: carouselIndex >= maxCarouselIndex ? 'not-allowed' : 'pointer',
|
|
1338
|
+
opacity: carouselIndex >= maxCarouselIndex ? 0.5 : 1,
|
|
1339
|
+
display: 'flex',
|
|
1340
|
+
alignItems: 'center',
|
|
1341
|
+
justifyContent: 'center',
|
|
1342
|
+
fontSize: '18px',
|
|
1343
|
+
zIndex: 10,
|
|
1344
|
+
}}
|
|
1345
|
+
>
|
|
1346
|
+
›
|
|
1347
|
+
</button>
|
|
1348
|
+
|
|
1349
|
+
{/* Dots Indicator */}
|
|
1350
|
+
<div
|
|
1351
|
+
style={{
|
|
1352
|
+
position: 'absolute',
|
|
1353
|
+
bottom: '10px',
|
|
1354
|
+
left: '50%',
|
|
1355
|
+
transform: 'translateX(-50%)',
|
|
1356
|
+
display: 'flex',
|
|
1357
|
+
gap: '8px',
|
|
1358
|
+
zIndex: 10,
|
|
1359
|
+
}}
|
|
1360
|
+
>
|
|
1361
|
+
{Array.from({ length: maxCarouselIndex + 1 }, (_, index) => (
|
|
1362
|
+
<button
|
|
1363
|
+
key={index}
|
|
1364
|
+
onClick={() => goToCarouselItem(index)}
|
|
1365
|
+
style={{
|
|
1366
|
+
width: index === carouselIndex ? '12px' : '8px',
|
|
1367
|
+
height: index === carouselIndex ? '12px' : '8px',
|
|
1368
|
+
borderRadius: '50%',
|
|
1369
|
+
border: 'none',
|
|
1370
|
+
background: index === carouselIndex ? 'white' : 'rgba(255,255,255,0.5)',
|
|
1371
|
+
cursor: 'pointer',
|
|
1372
|
+
transition: 'all 0.3s ease',
|
|
1373
|
+
}}
|
|
1374
|
+
/>
|
|
1375
|
+
))}
|
|
1376
|
+
</div>
|
|
1377
|
+
</>
|
|
1378
|
+
)}
|
|
1066
1379
|
</div>
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
}
|
|
1071
|
-
break;
|
|
1380
|
+
);
|
|
1381
|
+
}
|
|
1382
|
+
break;
|
|
1072
1383
|
|
|
1073
1384
|
default:
|
|
1074
1385
|
return (
|