parent
ef7a24d571
commit
9e6c9d9082
17
package-lock.json
generated
17
package-lock.json
generated
|
@ -115,7 +115,7 @@
|
||||||
"stylelint-config-standard-scss": "11.1.0",
|
"stylelint-config-standard-scss": "11.1.0",
|
||||||
"stylelint-order": "6.0.3",
|
"stylelint-order": "6.0.3",
|
||||||
"stylelint-scss": "5.3.1",
|
"stylelint-scss": "5.3.1",
|
||||||
"swiper": "9.4.1",
|
"swiper": "11.0.5",
|
||||||
"throttle-debounce": "5.0.0",
|
"throttle-debounce": "5.0.0",
|
||||||
"typescript": "5.2.2",
|
"typescript": "5.2.2",
|
||||||
"typograf": "7.1.0",
|
"typograf": "7.1.0",
|
||||||
|
@ -17436,12 +17436,6 @@
|
||||||
"integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==",
|
"integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/ssr-window": {
|
|
||||||
"version": "4.0.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/ssr-window/-/ssr-window-4.0.2.tgz",
|
|
||||||
"integrity": "sha512-ISv/Ch+ig7SOtw7G2+qkwfVASzazUnvlDTwypdLoPoySv+6MqlOV10VwPSE6EWkGjhW50lUmghPmpYZXMu/+AQ==",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"node_modules/stack-utils": {
|
"node_modules/stack-utils": {
|
||||||
"version": "2.0.6",
|
"version": "2.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz",
|
||||||
|
@ -17934,9 +17928,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/swiper": {
|
"node_modules/swiper": {
|
||||||
"version": "9.4.1",
|
"version": "11.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/swiper/-/swiper-9.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/swiper/-/swiper-11.0.5.tgz",
|
||||||
"integrity": "sha512-1nT2T8EzUpZ0FagEqaN/YAhRj33F2x/lN6cyB0/xoYJDMf8KwTFT3hMOeoB8Tg4o3+P/CKqskP+WX0Df046fqA==",
|
"integrity": "sha512-rhCwupqSyRnWrtNzWzemnBLMoyYuoDgGgspAm/8iBD3jCvAWycPLH4Z3TB0O5520DHLzMx94yUMH/B9Efpa48w==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
|
@ -17948,9 +17942,6 @@
|
||||||
"url": "http://opencollective.com/swiper"
|
"url": "http://opencollective.com/swiper"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"dependencies": {
|
|
||||||
"ssr-window": "^4.0.2"
|
|
||||||
},
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 4.7.0"
|
"node": ">= 4.7.0"
|
||||||
}
|
}
|
||||||
|
|
|
@ -136,7 +136,7 @@
|
||||||
"stylelint-config-standard-scss": "11.1.0",
|
"stylelint-config-standard-scss": "11.1.0",
|
||||||
"stylelint-order": "6.0.3",
|
"stylelint-order": "6.0.3",
|
||||||
"stylelint-scss": "5.3.1",
|
"stylelint-scss": "5.3.1",
|
||||||
"swiper": "9.4.1",
|
"swiper": "11.0.5",
|
||||||
"throttle-debounce": "5.0.0",
|
"throttle-debounce": "5.0.0",
|
||||||
"typescript": "5.2.2",
|
"typescript": "5.2.2",
|
||||||
"typograf": "7.1.0",
|
"typograf": "7.1.0",
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import { clsx } from 'clsx'
|
import { clsx } from 'clsx'
|
||||||
import { For, onMount, Show } from 'solid-js'
|
import { For, onMount, Show } from 'solid-js'
|
||||||
import SwiperCore, { Manipulation, Navigation, Pagination } from 'swiper'
|
import SwiperCore from 'swiper'
|
||||||
|
import { Manipulation, Navigation, Pagination } from 'swiper/modules'
|
||||||
|
|
||||||
import { Shout } from '../../../graphql/types.gen'
|
import { Shout } from '../../../graphql/types.gen'
|
||||||
import { ArticleCard } from '../../Feed/ArticleCard'
|
import { ArticleCard } from '../../Feed/ArticleCard'
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
import { createFileUploader } from '@solid-primitives/upload'
|
import { createFileUploader } from '@solid-primitives/upload'
|
||||||
import { clsx } from 'clsx'
|
import { clsx } from 'clsx'
|
||||||
import { createEffect, createSignal, For, Show, on, onMount, lazy } from 'solid-js'
|
import { createEffect, createSignal, For, Show, on, onMount, lazy } from 'solid-js'
|
||||||
import SwiperCore, { Manipulation, Navigation, Pagination } from 'swiper'
|
import SwiperCore from 'swiper'
|
||||||
|
import { Manipulation, Navigation, Pagination } from 'swiper/modules'
|
||||||
|
|
||||||
import { useLocalize } from '../../../context/localize'
|
import { useLocalize } from '../../../context/localize'
|
||||||
import { useSnackbar } from '../../../context/snackbar'
|
import { useSnackbar } from '../../../context/snackbar'
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import { clsx } from 'clsx'
|
import { clsx } from 'clsx'
|
||||||
import { createEffect, createSignal, For, Show, on, onMount, onCleanup } from 'solid-js'
|
import { createEffect, createSignal, For, Show, on, onMount, onCleanup } from 'solid-js'
|
||||||
import SwiperCore, { Manipulation, Navigation, Pagination } from 'swiper'
|
import SwiperCore from 'swiper'
|
||||||
|
import { Manipulation, Navigation, Pagination } from 'swiper/modules'
|
||||||
import { throttle } from 'throttle-debounce'
|
import { throttle } from 'throttle-debounce'
|
||||||
|
|
||||||
import { MediaItem } from '../../../pages/types'
|
import { MediaItem } from '../../../pages/types'
|
||||||
|
@ -27,7 +28,6 @@ export const ImageSwiper = (props: Props) => {
|
||||||
const mainSwipeRef: { current: SwiperRef } = { current: null }
|
const mainSwipeRef: { current: SwiperRef } = { current: null }
|
||||||
const thumbSwipeRef: { current: SwiperRef } = { current: null }
|
const thumbSwipeRef: { current: SwiperRef } = { current: null }
|
||||||
const swiperMainContainer: { current: HTMLDivElement } = { current: null }
|
const swiperMainContainer: { current: HTMLDivElement } = { current: null }
|
||||||
|
|
||||||
const [slideIndex, setSlideIndex] = createSignal(0)
|
const [slideIndex, setSlideIndex] = createSignal(0)
|
||||||
const [isMobileView, setIsMobileView] = createSignal(false)
|
const [isMobileView, setIsMobileView] = createSignal(false)
|
||||||
const [selectedImage, setSelectedImage] = createSignal('')
|
const [selectedImage, setSelectedImage] = createSignal('')
|
||||||
|
@ -52,18 +52,13 @@ export const ImageSwiper = (props: Props) => {
|
||||||
const { register } = await import('swiper/element/bundle')
|
const { register } = await import('swiper/element/bundle')
|
||||||
register()
|
register()
|
||||||
SwiperCore.use([Pagination, Navigation, Manipulation])
|
SwiperCore.use([Pagination, Navigation, Manipulation])
|
||||||
|
mainSwipeRef.current.swiper.on('slideChange', handleSlideChange)
|
||||||
})
|
})
|
||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
const updateDirection = () => {
|
const updateDirection = () => {
|
||||||
const width = window.innerWidth
|
const width = window.innerWidth
|
||||||
const direction = width > MIN_WIDTH ? 'vertical' : 'horizontal'
|
setIsMobileView(width < MIN_WIDTH)
|
||||||
if (direction === 'horizontal') {
|
|
||||||
setIsMobileView(true)
|
|
||||||
} else {
|
|
||||||
setIsMobileView(false)
|
|
||||||
}
|
|
||||||
thumbSwipeRef.current?.swiper?.changeDirection(direction)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
updateDirection()
|
updateDirection()
|
||||||
|
@ -96,13 +91,58 @@ export const ImageSwiper = (props: Props) => {
|
||||||
<div class={clsx(styles.Swiper, styles.articleMode, { [styles.mobileView]: isMobileView() })}>
|
<div class={clsx(styles.Swiper, styles.articleMode, { [styles.mobileView]: isMobileView() })}>
|
||||||
<div class={styles.container} ref={(el) => (swiperMainContainer.current = el)}>
|
<div class={styles.container} ref={(el) => (swiperMainContainer.current = el)}>
|
||||||
<Show when={props.images.length > 0}>
|
<Show when={props.images.length > 0}>
|
||||||
|
<div class={clsx(styles.holder, styles.thumbsHolder)}>
|
||||||
|
<div class={styles.thumbs}>
|
||||||
|
<swiper-container
|
||||||
|
class={'thumbSwiper'}
|
||||||
|
ref={(el) => (thumbSwipeRef.current = el)}
|
||||||
|
slides-per-view={'auto'}
|
||||||
|
space-between={isMobileView() ? 20 : 10}
|
||||||
|
auto-scroll-offset={1}
|
||||||
|
watch-overflow={true}
|
||||||
|
watch-slides-visibility={true}
|
||||||
|
direction={'horizontal'}
|
||||||
|
>
|
||||||
|
<For each={props.images}>
|
||||||
|
{(slide, index) => (
|
||||||
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||||
|
// @ts-ignore
|
||||||
|
<swiper-slide virtual-index={index()} style={{ width: 'auto', height: 'auto' }}>
|
||||||
|
<div
|
||||||
|
class={clsx(styles.imageThumb)}
|
||||||
|
style={{
|
||||||
|
'background-image': `url(${getImageUrl(slide.url, { width: 110, height: 75 })})`,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</swiper-slide>
|
||||||
|
)}
|
||||||
|
</For>
|
||||||
|
</swiper-container>
|
||||||
|
<div
|
||||||
|
class={clsx(styles.navigation, styles.thumbsNav, styles.prev, {
|
||||||
|
[styles.disabled]: slideIndex() === 0,
|
||||||
|
})}
|
||||||
|
onClick={() => thumbSwipeRef.current.swiper.slidePrev()}
|
||||||
|
>
|
||||||
|
<Icon name="swiper-l-arr" class={styles.icon} />
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class={clsx(styles.navigation, styles.thumbsNav, styles.next, {
|
||||||
|
[styles.disabled]: slideIndex() + 1 === props.images.length,
|
||||||
|
})}
|
||||||
|
onClick={() => thumbSwipeRef.current.swiper.slideTo(10)}
|
||||||
|
>
|
||||||
|
<Icon name="swiper-r-arr" class={styles.icon} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class={styles.holder}>
|
<div class={styles.holder}>
|
||||||
<swiper-container
|
<swiper-container
|
||||||
ref={(el) => (mainSwipeRef.current = el)}
|
ref={(el) => (mainSwipeRef.current = el)}
|
||||||
slides-per-view={1}
|
slides-per-view={1}
|
||||||
thumbs-swiper={'.thumbSwiper'}
|
thumbs-swiper={'.thumbSwiper'}
|
||||||
observer={true}
|
observer={true}
|
||||||
onSlideChange={handleSlideChange}
|
// slide-change={handleSlideChange}
|
||||||
space-between={isMobileView() ? 20 : 10}
|
space-between={isMobileView() ? 20 : 10}
|
||||||
>
|
>
|
||||||
<For each={props.images}>
|
<For each={props.images}>
|
||||||
|
@ -137,50 +177,6 @@ export const ImageSwiper = (props: Props) => {
|
||||||
{slideIndex() + 1} / {props.images.length}
|
{slideIndex() + 1} / {props.images.length}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class={clsx(styles.holder, styles.thumbsHolder)}>
|
|
||||||
<div class={styles.thumbs}>
|
|
||||||
<swiper-container
|
|
||||||
class={'thumbSwiper'}
|
|
||||||
ref={(el) => (thumbSwipeRef.current = el)}
|
|
||||||
slides-per-view={'auto'}
|
|
||||||
space-between={isMobileView() ? 20 : 10}
|
|
||||||
auto-scroll-offset={1}
|
|
||||||
watch-overflow={true}
|
|
||||||
watch-slides-visibility={true}
|
|
||||||
>
|
|
||||||
<For each={props.images}>
|
|
||||||
{(slide, index) => (
|
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
||||||
// @ts-ignore
|
|
||||||
<swiper-slide virtual-index={index()} style={{ width: 'auto', height: 'auto' }}>
|
|
||||||
<div
|
|
||||||
class={clsx(styles.imageThumb)}
|
|
||||||
style={{
|
|
||||||
'background-image': `url(${getImageUrl(slide.url, { width: 110, height: 75 })})`,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</swiper-slide>
|
|
||||||
)}
|
|
||||||
</For>
|
|
||||||
</swiper-container>
|
|
||||||
<div
|
|
||||||
class={clsx(styles.navigation, styles.thumbsNav, styles.prev, {
|
|
||||||
[styles.disabled]: slideIndex() === 0,
|
|
||||||
})}
|
|
||||||
onClick={() => thumbSwipeRef.current.swiper.slidePrev()}
|
|
||||||
>
|
|
||||||
<Icon name="swiper-l-arr" class={styles.icon} />
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class={clsx(styles.navigation, styles.thumbsNav, styles.next, {
|
|
||||||
[styles.disabled]: slideIndex() + 1 === props.images.length,
|
|
||||||
})}
|
|
||||||
onClick={() => thumbSwipeRef.current.swiper.slideNext()}
|
|
||||||
>
|
|
||||||
<Icon name="swiper-r-arr" class={styles.icon} />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Show>
|
</Show>
|
||||||
</div>
|
</div>
|
||||||
<div class={styles.slideDescription}>
|
<div class={styles.slideDescription}>
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
background: var(--background-color-invert);
|
background: var(--background-color-invert);
|
||||||
color: var(--default-color-invert);
|
color: var(--default-color-invert);
|
||||||
display: flex;
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
|
||||||
|
@ -40,47 +41,37 @@
|
||||||
.container {
|
.container {
|
||||||
margin: auto;
|
margin: auto;
|
||||||
position: relative;
|
position: relative;
|
||||||
padding: 24px 0;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
gap: 20px;
|
gap: 20px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
||||||
.thumbsHolder {
|
.thumbsHolder {
|
||||||
min-width: 110px;
|
|
||||||
width: auto;
|
width: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.thumbs {
|
.thumbs {
|
||||||
padding: 52px 0;
|
|
||||||
width: 110px;
|
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
height: calc(var(--slide-height) + 40px);
|
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
.thumbsNav {
|
.thumbsNav {
|
||||||
height: 52px;
|
height: 52px;
|
||||||
padding: 14px 0;
|
overflow: hidden;
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
width: 110px;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
|
|
||||||
.icon {
|
|
||||||
transform: rotate(90deg);
|
|
||||||
}
|
|
||||||
|
|
||||||
&.prev {
|
&.prev {
|
||||||
top: 0;
|
top: 50%;
|
||||||
|
left: 0;
|
||||||
|
transform: translateY(-50%);
|
||||||
}
|
}
|
||||||
|
|
||||||
&.next {
|
&.next {
|
||||||
top: auto;
|
top: 50%;
|
||||||
bottom: 0;
|
right: 0;
|
||||||
|
left: unset;
|
||||||
|
transform: translateY(-50%);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -88,43 +79,12 @@
|
||||||
|
|
||||||
&.mobileView {
|
&.mobileView {
|
||||||
.container {
|
.container {
|
||||||
flex-direction: column-reverse;
|
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
|
||||||
.thumbsHolder {
|
|
||||||
min-width: unset;
|
|
||||||
}
|
|
||||||
|
|
||||||
.thumbs {
|
.thumbs {
|
||||||
width: 100%;
|
|
||||||
height: 80px;
|
|
||||||
padding: 0;
|
|
||||||
|
|
||||||
& swiper-slide {
|
& swiper-slide {
|
||||||
// bind to html element <swiper-slide/>
|
// bind to html element <swiper-slide/>
|
||||||
width: unset !important;
|
width: unset !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.thumbsNav {
|
|
||||||
height: 100%;
|
|
||||||
padding: 0;
|
|
||||||
width: 40px;
|
|
||||||
|
|
||||||
.icon {
|
|
||||||
transform: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.prev {
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.next {
|
|
||||||
top: 0;
|
|
||||||
right: 0;
|
|
||||||
left: unset;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -260,6 +220,10 @@
|
||||||
|
|
||||||
margin-top: 24px;
|
margin-top: 24px;
|
||||||
|
|
||||||
|
* {
|
||||||
|
color: var(--default-color-invert) !important; //Force fix migration errors with inline styles
|
||||||
|
}
|
||||||
|
|
||||||
@include media-breakpoint-up(md) {
|
@include media-breakpoint-up(md) {
|
||||||
// margin-left: calc((100% + 130px) * 0.15);
|
// margin-left: calc((100% + 130px) * 0.15);
|
||||||
margin-left: calc(15% + 24px);
|
margin-left: calc(15% + 24px);
|
||||||
|
@ -398,4 +362,9 @@
|
||||||
display: flex !important;
|
display: flex !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.swiper-button-prev,
|
||||||
|
.swiper-rtl .swiper-button-next {
|
||||||
|
top: 200px !important;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,10 +37,16 @@ declare module 'solid-js' {
|
||||||
onSlideChange?: () => void
|
onSlideChange?: () => void
|
||||||
onBeforeSlideChangeStart?: () => void
|
onBeforeSlideChangeStart?: () => void
|
||||||
class?: string
|
class?: string
|
||||||
|
observer?: boolean
|
||||||
|
loop?: boolean
|
||||||
|
speed?: number
|
||||||
|
slidesPerGroupAuto?: boolean
|
||||||
|
navigation?: boolean
|
||||||
breakpoints?: {
|
breakpoints?: {
|
||||||
[width: number]: SwiperOptions
|
[width: number]: SwiperOptions
|
||||||
[ratio: string]: SwiperOptions
|
[ratio: string]: SwiperOptions
|
||||||
}
|
}
|
||||||
|
direction?: 'horizontal' | 'vertical'
|
||||||
autoplay?: AutoplayOptions | boolean
|
autoplay?: AutoplayOptions | boolean
|
||||||
}
|
}
|
||||||
// eslint-disable-next-line @typescript-eslint/no-empty-interface
|
// eslint-disable-next-line @typescript-eslint/no-empty-interface
|
||||||
|
|
Loading…
Reference in New Issue
Block a user