@ludo.ninja/components 1.4.3 → 1.4.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.
@@ -1,235 +0,0 @@
1
- // link to carousel source https://dev.to/holdmypotion/react-3d-image-slider-5g6
2
- import React, { useEffect, useState } from 'react';
3
-
4
- import Slider, { Settings } from 'react-slick';
5
- import 'slick-carousel/slick/slick.css';
6
- import styled from 'styled-components';
7
-
8
- import { adaptiveValueCalc } from '@ludo.ninja/ui/build/utils/4k';
9
-
10
- import { mediaQuery } from '@/styles/ScreenWidth';
11
- import { TextGrayColor, WhiteColor } from '@/styles/colors';
12
-
13
- import { useSliderStore } from '@/components/assetPage/slider/store';
14
-
15
- import { H6 } from '@system';
16
-
17
- import Media from '@/dto/common/Media';
18
-
19
- import { SlideItem } from './slideItem';
20
-
21
- const Wrapper = styled.div`
22
- margin: 0 0 60px -160px;
23
- width: 1400px;
24
-
25
- ${mediaQuery.desktop} {
26
- margin: 0 auto;
27
- width: 100%;
28
- }
29
-
30
- ${mediaQuery.mobile} {
31
- width: 95vw;
32
- position: relative;
33
- left: calc(((100vw - 320px) / -2) - -2.5vw);
34
- }
35
-
36
- .prevArrow {
37
- display: flex;
38
- align-items: center;
39
- justify-content: center;
40
- width: 50px;
41
- height: 50px;
42
- border-radius: 50%;
43
- background: ${WhiteColor};
44
- position: absolute;
45
- top: calc(50% - 25px);
46
- left: 165px;
47
- z-index: 100;
48
- cursor: pointer;
49
- font-size: 2rem;
50
-
51
- ${mediaQuery.desktop} {
52
- left: 10px;
53
- }
54
-
55
- ${mediaQuery.tablet} {
56
- left: 0;
57
- }
58
- }
59
-
60
- .nextArrow {
61
- left: calc(100% - 195px);
62
- transform: rotate(180deg);
63
-
64
- ${mediaQuery.desktop} {
65
- left: calc(100% - 65px);
66
- }
67
-
68
- ${mediaQuery.tablet} {
69
- left: calc(100% - 48px);
70
- }
71
- }
72
-
73
- .disable {
74
- display: none;
75
- }
76
-
77
- .slick-track {
78
- display: flex;
79
- align-items: center;
80
- }
81
-
82
- .slick-slide {
83
- padding: 0 10px;
84
- transform: scale(0.63);
85
- transition: all 400ms;
86
- opacity: 0.2;
87
-
88
- ${mediaQuery.tablet} {
89
- transform: scale(0.5);
90
- }
91
-
92
- &:not(.slick-active) {
93
- pointer-events: none;
94
- }
95
- }
96
-
97
- .slick-slide.slick-active.slick-center.slick-current {
98
- transform: scale(1);
99
- transition: all 400ms;
100
- opacity: 1;
101
- }
102
-
103
- .medias-count {
104
- margin-top: 15px;
105
- }
106
-
107
- ${mediaQuery.minWidthFourK} {
108
- margin: 0 0 ${adaptiveValueCalc(60)} ${adaptiveValueCalc(-160)};
109
- width: ${adaptiveValueCalc(1400)};
110
-
111
- .medias-count {
112
- margin-top: ${adaptiveValueCalc(15)};
113
- }
114
-
115
- .prevArrow {
116
- width: ${adaptiveValueCalc(50)};
117
- height: ${adaptiveValueCalc(50)};
118
- top: calc(50% - ${adaptiveValueCalc(25)});
119
- left: ${adaptiveValueCalc(165)};
120
- font-size: ${adaptiveValueCalc(20)};
121
-
122
- img {
123
- width: ${adaptiveValueCalc(12)};
124
- height: ${adaptiveValueCalc(15)};
125
- }
126
- }
127
-
128
- .nextArrow {
129
- left: calc(100% - ${adaptiveValueCalc(195)});
130
- }
131
-
132
- .slick-slide {
133
- padding: 0 ${adaptiveValueCalc(10)};
134
- }
135
- }
136
- `;
137
-
138
- const PrevArrow = ({
139
- disable,
140
- onClick,
141
- }: {
142
- disable: boolean;
143
- onClick: () => void;
144
- }) => {
145
- return (
146
- <div
147
- className={`${disable ? 'disable prevArrow' : 'prevArrow'}`}
148
- onClick={onClick}
149
- >
150
- <img src={'/assetPage/arrow.svg'} width={12} height={15} alt="arrow" />
151
- </div>
152
- );
153
- };
154
-
155
- const NextArrow = ({
156
- disable,
157
- onClick,
158
- }: {
159
- disable: boolean;
160
- onClick: () => void;
161
- }) => {
162
- return (
163
- <div
164
- className={`${
165
- disable ? 'disable prevArrow nextArrow' : 'prevArrow nextArrow'
166
- }`}
167
- onClick={onClick}
168
- >
169
- <img src={'/assetPage/arrow.svg'} width={12} height={15} alt="arrow" />
170
- </div>
171
- );
172
- };
173
-
174
- export const CollectionSlider = ({ medias }: { medias: Media[] | null }) => {
175
- if (!medias) return null;
176
- return <SliderMedias medias={medias} />;
177
- };
178
-
179
- const SliderMedias = ({ medias }: { medias: Media[] }) => {
180
- const setIsActiveSlider = useSliderStore((state) => state.setIsActiveSlider);
181
- const isDisabled = useSliderStore((state) => state.isDisabled);
182
-
183
- useEffect(() => {
184
- setIsActiveSlider(true);
185
- return () => {
186
- setIsActiveSlider(false);
187
- };
188
- }, []);
189
-
190
- const [imageIndex, setImageIndex] = useState(0);
191
-
192
- const settings: Settings = {
193
- draggable: !isDisabled,
194
- swipe: !isDisabled,
195
- arrows: !isDisabled,
196
- centerMode: true,
197
- infinite: false,
198
- dots: false,
199
- speed: 400,
200
- swipeToSlide: true,
201
- focusOnSelect: true,
202
- variableWidth: true,
203
- nextArrow: (
204
- <NextArrow
205
- disable={imageIndex === medias.length - 1}
206
- onClick={() => setImageIndex((val) => val + 1)}
207
- />
208
- ),
209
- prevArrow: (
210
- <PrevArrow
211
- disable={imageIndex === 0}
212
- onClick={() => setImageIndex((val) => val - 1)}
213
- />
214
- ),
215
- beforeChange: (current: number, next: number) => setImageIndex(next),
216
- };
217
-
218
- const collectionTemplate = medias.map((image, idx) => {
219
- if (!image) return null;
220
- return <SlideItem item={image} key={idx} />;
221
- });
222
-
223
- return (
224
- <Wrapper>
225
- <Slider {...settings}>{collectionTemplate}</Slider>
226
- <H6
227
- style={{ textAlign: 'center' }}
228
- color={TextGrayColor}
229
- className={'medias-count'}
230
- >
231
- {imageIndex + 1 + '/' + medias.length + ' medias'}
232
- </H6>
233
- </Wrapper>
234
- );
235
- };
@@ -1,55 +0,0 @@
1
- // link to carousel source https://dev.to/holdmypotion/react-3d-image-slider-5g6
2
- import React from 'react';
3
-
4
- import styled from 'styled-components';
5
-
6
- import { adaptiveValueCalc } from '@ludo.ninja/ui/build/utils/4k';
7
-
8
- import { mediaQuery } from '@/styles/ScreenWidth';
9
-
10
- import { ReactPlayerWrapper } from '@/components/assetPage/audioVideoPlayer';
11
-
12
- import Media from '@/dto/common/Media';
13
-
14
- const SlideWrapper = styled.div`
15
- display: flex;
16
- flex-direction: column;
17
- align-items: center;
18
- justify-content: center;
19
- //width: 450px;
20
- //height: 450px;
21
- position: relative;
22
- border-radius: 16px;
23
- background-size: contain;
24
- background-repeat: no-repeat;
25
- margin: 0 auto;
26
-
27
- ${ReactPlayerWrapper} {
28
- margin-right: 0;
29
- }
30
-
31
- ${mediaQuery.desktop} {
32
- width: 280px;
33
- height: 280px;
34
- }
35
-
36
- ${mediaQuery.tablet} {
37
- width: 240px;
38
- height: 240px;
39
- }
40
-
41
- & > div {
42
- width: 100%;
43
-
44
- /* ${mediaQuery.desktop} {
45
- width:100%;
46
- } */
47
- }
48
- ${mediaQuery.minWidthFourK} {
49
- border-radius: ${adaptiveValueCalc(16)};
50
- }
51
- `;
52
-
53
- export const SlideItem = ({ item, key }: { item: Media; key: number }) => {
54
- return <SlideWrapper key={key}>{item.displayLinkedMedia()}</SlideWrapper>;
55
- };
@@ -1,23 +0,0 @@
1
- import { create } from 'zustand';
2
-
3
- interface ISliderStore {
4
- isActiveSlider: boolean;
5
- setIsActiveSlider: (isActiveSlider: boolean) => void;
6
-
7
- isDisabled: boolean;
8
- setIsDisabled: (isDisabled: boolean) => void;
9
- }
10
-
11
- export const useSliderStore = create<ISliderStore>()((setState, getState) => ({
12
- isActiveSlider: false,
13
- setIsActiveSlider: (isActiveSlider) => {
14
- setState({ isActiveSlider });
15
- },
16
-
17
- isDisabled: false,
18
- setIsDisabled: (isDisabled) => {
19
- if (getState().isActiveSlider) {
20
- setState({ isDisabled });
21
- }
22
- },
23
- }));
@@ -1,143 +0,0 @@
1
- import React, { useEffect, useState } from 'react';
2
-
3
- import Link from 'next/link';
4
-
5
- import styled from 'styled-components';
6
-
7
- import { assetSchema as schema } from '@ludo.ninja/api';
8
- import { adaptiveValueCalc } from '@ludo.ninja/ui/build/utils/4k';
9
-
10
- import { mediaQuery } from '@/styles/ScreenWidth';
11
- import { AccentColor, BlackColor } from '@/styles/colors';
12
-
13
- import { ImageInterceptor } from '@/system/Img/ImageInterceptor';
14
-
15
- import { ExternalImage, Flex, H1 } from '@system';
16
-
17
- import { getAssetImage, mediaSizes } from '@/dto/common/Media/Urls';
18
-
19
- const SCollection = styled(Flex)`
20
- margin-bottom: 8px;
21
-
22
- img {
23
- margin-right: 8px;
24
- width: 28px;
25
- height: 28px;
26
- border-radius: 2px;
27
- }
28
-
29
- a {
30
- font-size: 18px;
31
- font-weight: 600;
32
- color: ${AccentColor};
33
- }
34
-
35
- ${mediaQuery.minWidthFourK} {
36
- margin-bottom: ${adaptiveValueCalc(8)};
37
-
38
- img {
39
- margin-right: ${adaptiveValueCalc(8)};
40
- width: ${adaptiveValueCalc(28)};
41
- height: ${adaptiveValueCalc(28)};
42
- border-radius: ${adaptiveValueCalc(2)};
43
- }
44
-
45
- a {
46
- font-size: ${adaptiveValueCalc(18)};
47
- }
48
- }
49
- `;
50
-
51
- const SH1 = styled(H1)`
52
- color: ${BlackColor};
53
- line-height: 42px;
54
- word-break: break-word;
55
-
56
- span {
57
- padding-left: 5px;
58
- color: blue;
59
- cursor: pointer;
60
- }
61
-
62
- ${mediaQuery.minWidthFourK} {
63
- line-height: ${adaptiveValueCalc(42)};
64
-
65
- span {
66
- padding-left: ${adaptiveValueCalc(5)};
67
- }
68
- }
69
- `;
70
-
71
- const Collection = (
72
- props: Pick<
73
- schema.IAsset,
74
- 'collectionTitle' | 'collectionMedias' | 'collectionId'
75
- >
76
- ) => {
77
- if (!props.collectionTitle || !props.collectionId) return null;
78
-
79
- return (
80
- <SCollection alignItems="center">
81
- {!!props.collectionMedias && (
82
- <ImageInterceptor>
83
- <ExternalImage
84
- src={getAssetImage(
85
- props.collectionMedias[0]?.url,
86
- '/noContent/noContent.svg',
87
- mediaSizes.small
88
- )}
89
- alt="collection_img"
90
- width={28}
91
- height={28}
92
- borderRadius={2}
93
- />
94
- </ImageInterceptor>
95
- )}
96
- <Link href={`/collection/${props?.collectionId}`}>
97
- {props.collectionTitle}
98
- </Link>
99
- </SCollection>
100
- );
101
- };
102
-
103
- type TitleProps = {
104
- collectionId: string | null;
105
- collectionTitle: string | null;
106
- collectionMedias: schema.IMedia[];
107
- name: null | string;
108
- };
109
-
110
- export const Title = ({
111
- name,
112
- collectionTitle,
113
- collectionMedias,
114
- collectionId,
115
- }: TitleProps) => {
116
- const [cuttedString, setCuttedString] = useState<typeof name | null>(name);
117
- const [isNeedReadMore, setNeedReadMore] = useState<boolean>(false);
118
-
119
- useEffect(() => {
120
- if (name && name.length > 35) {
121
- setCuttedString(name.slice(0, 35));
122
- setNeedReadMore(true);
123
- }
124
- }, []);
125
-
126
- const handleReadMore = () => {
127
- setCuttedString(name);
128
- setNeedReadMore(false);
129
- };
130
- return (
131
- <Flex flexDirection="column">
132
- <Collection
133
- collectionId={collectionId}
134
- collectionTitle={collectionTitle}
135
- collectionMedias={collectionMedias}
136
- />
137
- <SH1>
138
- {cuttedString}
139
- {isNeedReadMore && <span onClick={handleReadMore}>...</span>}
140
- </SH1>
141
- </Flex>
142
- );
143
- };
@@ -1,206 +0,0 @@
1
- import React, { Suspense, useEffect, useState } from 'react';
2
-
3
- import {
4
- Center,
5
- ContactShadows,
6
- OrbitControls,
7
- Stage,
8
- useGLTF,
9
- } from '@react-three/drei';
10
- import { Canvas, useFrame } from '@react-three/fiber';
11
- import Skeleton from 'react-loading-skeleton';
12
- import styled from 'styled-components';
13
-
14
- import { adaptiveValueCalc } from '@ludo.ninja/ui/build/utils/4k';
15
-
16
- import { mediaQuery } from '@/styles/ScreenWidth';
17
- import {
18
- BlackColor,
19
- InactiveButtonColor,
20
- TextGrayColor,
21
- WhiteColor,
22
- } from '@/styles/colors';
23
-
24
- import AssetImage from '@/components/assetPage/media/AssetImage';
25
- import { useSliderStore } from '@/components/assetPage/slider/store';
26
- import NoSsr from '@/components/base/NoSSR';
27
-
28
- import { Flex } from '@system';
29
-
30
- type Viewer3dProps = {
31
- file2D?: string | undefined | null;
32
- file3D: string | undefined | null;
33
- };
34
-
35
- const Togler = styled(Flex)`
36
- border-radius: 8px;
37
- position: absolute;
38
- top: 16px;
39
- right: 16px;
40
- overflow: hidden;
41
- z-index: 1;
42
- border: 1px solid ${BlackColor};
43
-
44
- ${mediaQuery.minWidthFourK} {
45
- border-radius: ${adaptiveValueCalc(8)};
46
- top: ${adaptiveValueCalc(16)};
47
- right: ${adaptiveValueCalc(16)};
48
- border: ${adaptiveValueCalc(1)} solid ${BlackColor};
49
- }
50
- `;
51
-
52
- const ButtonTogler = styled.button<{ isActive: boolean }>`
53
- border: none;
54
- cursor: pointer;
55
- background: ${(props) => (props.isActive ? InactiveButtonColor : WhiteColor)};
56
- padding: 0;
57
- width: 36px;
58
- height: 36px;
59
- font-size: 13px;
60
- font-weight: 40;
61
- color: ${(props) => (props.isActive ? BlackColor : TextGrayColor)};
62
-
63
- ${mediaQuery.minWidthFourK} {
64
- width: ${adaptiveValueCalc(36)};
65
- height: ${adaptiveValueCalc(36)};
66
- font-size: ${adaptiveValueCalc(13)};
67
- }
68
- `;
69
-
70
- const StyledAsset = styled.div<{ is3D: boolean }>`
71
- max-height: 100%;
72
- max-width: 100%;
73
- width: 510px;
74
- height: 510px;
75
- margin-right: 60px;
76
- position: relative;
77
- overflow: hidden;
78
- border-radius: 16px;
79
- background-color: ${WhiteColor};
80
- display: flex;
81
- align-items: center;
82
- justify-content: center;
83
-
84
- //border: 2px solid rgba(0, 0, 0, 0.5);
85
-
86
- ${mediaQuery.desktop} {
87
- width: 335px;
88
- margin-right: 30px;
89
- }
90
-
91
- ${mediaQuery.tablet} {
92
- align-items: flex-start;
93
- width: 320px;
94
- margin-right: 0;
95
- }
96
-
97
- ${mediaQuery.minWidthFourK} {
98
- width: ${adaptiveValueCalc(510)};
99
- height: ${adaptiveValueCalc(510)};
100
- margin-right: ${adaptiveValueCalc(60)};
101
- border-radius: ${adaptiveValueCalc(16)};
102
- }
103
- `;
104
-
105
- const ModelPreview = ({ file3D }: { file3D: string }) => {
106
- const gltf = useGLTF(file3D);
107
- useFrame(() => {
108
- gltf.scene.rotateY(0.002);
109
- });
110
-
111
- useEffect(() => {
112
- return () => {
113
- gltf.scene.rotation.set(0, 0, 0);
114
- };
115
- }, [gltf]);
116
-
117
- return <primitive object={gltf.scene} />;
118
- };
119
-
120
- export const ScenePreview = ({ file3D }: Pick<Viewer3dProps, 'file3D'>) => {
121
- if (typeof window === 'undefined' || !file3D) return null;
122
- return (
123
- <NoSsr>
124
- <Suspense
125
- fallback={
126
- <Skeleton
127
- style={{ position: 'absolute', left: 0, top: 0 }}
128
- height="100%"
129
- width="100%"
130
- />
131
- }
132
- >
133
- <Canvas resize={{ scroll: false }}>
134
- <ContactShadows
135
- opacity={1}
136
- scale={1000}
137
- blur={0.5}
138
- far={100}
139
- resolution={2048}
140
- color="#003366"
141
- />
142
- <Stage environment="city" preset="rembrandt">
143
- <Center>
144
- <ModelPreview file3D={file3D} />
145
- </Center>
146
- </Stage>
147
- <OrbitControls />
148
- </Canvas>
149
- </Suspense>
150
- </NoSsr>
151
- );
152
- };
153
-
154
- export const Viewer3D = ({ file3D, file2D }: Viewer3dProps) => {
155
- const [activeTab, setActiveTab] = useState<'3D' | '2D'>('2D');
156
- const setIsDisabledSlider = useSliderStore((state) => state.setIsDisabled);
157
- return (
158
- <div
159
- style={{
160
- width: '100%',
161
- height: '100%',
162
- }}
163
- >
164
- <StyledAsset is3D={activeTab === '3D'}>
165
- <Togler>
166
- <ButtonTogler
167
- isActive={activeTab === '2D'}
168
- onClick={() => {
169
- setActiveTab('2D');
170
- setIsDisabledSlider(false);
171
- }}
172
- >
173
- 2D
174
- </ButtonTogler>
175
- <ButtonTogler
176
- isActive={activeTab === '3D'}
177
- onClick={() => {
178
- setActiveTab('3D');
179
- setIsDisabledSlider(true);
180
- }}
181
- >
182
- 3D
183
- </ButtonTogler>
184
- </Togler>
185
-
186
- {activeTab === '3D' && file3D ? (
187
- <div
188
- style={{
189
- cursor: 'pointer',
190
- width: '100%',
191
- height: '100%',
192
- }}
193
- >
194
- <ScenePreview file3D={file3D} />
195
- </div>
196
- ) : (
197
- <AssetImage
198
- alt="fallback"
199
- imageUrl={file2D || '/noContent/noContentObject.svg'}
200
- errorImg={'/noContent/noContentObject.svg'}
201
- />
202
- )}
203
- </StyledAsset>
204
- </div>
205
- );
206
- };