WIP Add basic photo gallery
This commit is contained in:
@@ -1,8 +1,10 @@
|
|||||||
import Component from '@glimmer/component';
|
import Component from '@glimmer/component';
|
||||||
import { tracked } from '@glimmer/tracking';
|
import { tracked } from '@glimmer/tracking';
|
||||||
import { action } from '@ember/object';
|
import { action } from '@ember/object';
|
||||||
|
import { fn } from '@ember/helper';
|
||||||
import Blurhash from './blurhash';
|
import Blurhash from './blurhash';
|
||||||
import Icon from './icon';
|
import Icon from './icon';
|
||||||
|
import PhotoGallery from './photo-gallery';
|
||||||
import fadeInImage from '../modifiers/fade-in-image';
|
import fadeInImage from '../modifiers/fade-in-image';
|
||||||
import { on } from '@ember/modifier';
|
import { on } from '@ember/modifier';
|
||||||
import { modifier } from 'ember-modifier';
|
import { modifier } from 'ember-modifier';
|
||||||
@@ -10,6 +12,8 @@ import { modifier } from 'ember-modifier';
|
|||||||
export default class PlacePhotosCarousel extends Component {
|
export default class PlacePhotosCarousel extends Component {
|
||||||
@tracked canScrollLeft = false;
|
@tracked canScrollLeft = false;
|
||||||
@tracked canScrollRight = false;
|
@tracked canScrollRight = false;
|
||||||
|
@tracked isGalleryOpen = false;
|
||||||
|
@tracked selectedPhoto = null;
|
||||||
|
|
||||||
carouselElement = null;
|
carouselElement = null;
|
||||||
|
|
||||||
@@ -103,6 +107,18 @@ export default class PlacePhotosCarousel extends Component {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@action
|
||||||
|
openGallery(photo) {
|
||||||
|
this.selectedPhoto = photo;
|
||||||
|
this.isGalleryOpen = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@action
|
||||||
|
closeGallery() {
|
||||||
|
this.isGalleryOpen = false;
|
||||||
|
this.selectedPhoto = null;
|
||||||
|
}
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
{{#if this.photos.length}}
|
{{#if this.photos.length}}
|
||||||
<div class="place-photos-carousel-wrapper">
|
<div class="place-photos-carousel-wrapper">
|
||||||
@@ -114,12 +130,13 @@ export default class PlacePhotosCarousel extends Component {
|
|||||||
{{on "scroll" this.updateScrollState}}
|
{{on "scroll" this.updateScrollState}}
|
||||||
>
|
>
|
||||||
{{#each this.photos as |photo|}}
|
{{#each this.photos as |photo|}}
|
||||||
{{! template-lint-disable no-inline-styles }}
|
{{! template-lint-disable no-inline-styles no-invalid-interactive }}
|
||||||
<div
|
<div
|
||||||
class="carousel-slide
|
class="carousel-slide
|
||||||
{{if photo.isLandscape 'landscape' 'portrait'}}"
|
{{if photo.isLandscape 'landscape' 'portrait'}}"
|
||||||
style={{photo.style}}
|
style={{photo.style}}
|
||||||
data-event-id={{photo.eventId}}
|
data-event-id={{photo.eventId}}
|
||||||
|
{{on "click" (fn this.openGallery photo)}}
|
||||||
>
|
>
|
||||||
{{#if photo.blurhash}}
|
{{#if photo.blurhash}}
|
||||||
<Blurhash
|
<Blurhash
|
||||||
@@ -185,5 +202,14 @@ export default class PlacePhotosCarousel extends Component {
|
|||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
|
{{#if this.isGalleryOpen}}
|
||||||
|
<PhotoGallery
|
||||||
|
@photos={{this.photos}}
|
||||||
|
@selectedPhoto={{this.selectedPhoto}}
|
||||||
|
@placeName={{@name}}
|
||||||
|
@onClose={{this.closeGallery}}
|
||||||
|
/>
|
||||||
|
{{/if}}
|
||||||
</template>
|
</template>
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -909,6 +909,7 @@ abbr[title] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.carousel-slide {
|
.carousel-slide {
|
||||||
|
cursor: pointer;
|
||||||
position: relative;
|
position: relative;
|
||||||
flex: 0 0 100%;
|
flex: 0 0 100%;
|
||||||
scroll-snap-align: start;
|
scroll-snap-align: start;
|
||||||
@@ -1866,3 +1867,80 @@ button.create-place {
|
|||||||
.btn-link:hover {
|
.btn-link:hover {
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Photo Gallery */
|
||||||
|
.photo-gallery-overlay {
|
||||||
|
position: fixed;
|
||||||
|
inset: 0;
|
||||||
|
background: rgb(0 0 0 / 80%);
|
||||||
|
z-index: 9999;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.photo-gallery-overlay .photo-gallery-content {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.photo-gallery-overlay .close-btn {
|
||||||
|
position: absolute;
|
||||||
|
top: 0.5rem;
|
||||||
|
right: 1rem;
|
||||||
|
width: 48px;
|
||||||
|
height: 48px;
|
||||||
|
z-index: 10;
|
||||||
|
color: white;
|
||||||
|
background: transparent;
|
||||||
|
border-radius: 50%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
transition: background-color 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (width <= 768px) {
|
||||||
|
.photo-gallery-overlay .close-btn {
|
||||||
|
right: 0.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.photo-gallery-overlay .main-photo-container {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 2rem;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.photo-gallery-overlay .main-photo-container img {
|
||||||
|
max-width: 100%;
|
||||||
|
max-height: 100%;
|
||||||
|
object-fit: contain;
|
||||||
|
}
|
||||||
|
|
||||||
|
.photo-gallery-overlay .thumbnail-strip {
|
||||||
|
height: 100px;
|
||||||
|
display: flex;
|
||||||
|
gap: 0.5rem;
|
||||||
|
padding: 1rem;
|
||||||
|
overflow-x: auto;
|
||||||
|
background: rgb(0 0 0 / 50%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.photo-gallery-overlay .thumbnail-strip .thumbnail {
|
||||||
|
height: 100%;
|
||||||
|
flex-shrink: 0;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.photo-gallery-overlay .thumbnail-strip img {
|
||||||
|
height: 100%;
|
||||||
|
width: auto;
|
||||||
|
object-fit: cover;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user