Compare commits

18 Commits
dev ... main

Author SHA1 Message Date
cbd1062d82 refactor: use SASS @use over @import 2024-11-13 23:16:35 +01:00
ac3070b0b7 fix: exceeded effect on Photos page? 2024-11-12 15:12:06 +01:00
54682c6886 fix: move pages animation to onMount 2024-11-12 15:10:18 +01:00
d9708c5bfe fix: bring back updated data on Photos page 2024-11-12 15:03:18 +01:00
efd4a558af fix: replace stamp icon 2024-11-12 14:20:21 +01:00
d3a82f6cf5 fix: rename page stylesheets 2024-11-12 14:12:43 +01:00
9e46d79ba7 fix: SASS deprecated functions 2024-11-12 14:06:17 +01:00
9ed4f1dbd9 refactor: import using style src over @import 2024-11-12 14:05:59 +01:00
396eed0bcd chore: update deps 2024-11-12 14:05:11 +01:00
15364316e3 chore: update deps 2024-09-04 10:47:14 +02:00
79f58b5062 chore: update deps 2024-08-09 17:41:48 +02:00
3219cff2b9 fix: sort Credits locations alphabetically 2024-08-08 11:58:26 +02:00
a98bec7801 chore: update deps 2024-08-08 11:58:08 +02:00
8e5978e95f chore: update deps + Directus v11 2024-08-07 13:36:31 +02:00
77193c2920 chore: update deps 2024-08-05 23:27:54 +02:00
89fa888616 chore: add state and undefined to bindings 2024-08-05 23:27:46 +02:00
d3d7193663 fix: parallax values on About photos grid 2024-08-05 16:41:13 +02:00
d3482ceb54 Merge branch 'dev' 2024-08-05 16:28:18 +02:00
83 changed files with 279 additions and 319 deletions

View File

@@ -17,6 +17,6 @@
"dev": "directus-extension build -w --no-minify" "dev": "directus-extension build -w --no-minify"
}, },
"devDependencies": { "devDependencies": {
"@directus/extensions-sdk": "11.0.9" "@directus/extensions-sdk": "12.1.2"
} }
} }

View File

@@ -9,7 +9,7 @@
"start": "directus start" "start": "directus start"
}, },
"dependencies": { "dependencies": {
"directus": "^10.13.1", "directus": "^11.2.1",
"mysql": "^2.18.1" "mysql": "^2.18.1"
} }
} }

View File

@@ -15,42 +15,42 @@
"lint": "eslint ." "lint": "eslint ."
}, },
"dependencies": { "dependencies": {
"classix": "^2.1.38", "classix": "^2.2.0",
"dayjs": "^1.11.12", "dayjs": "^1.11.13",
"embla-carousel": "^8.1.8", "embla-carousel": "^8.3.1",
"focus-visible": "^5.2.0", "focus-visible": "^5.2.1",
"lenis": "^1.1.9", "lenis": "^1.1.16",
"motion": "^10.18.0", "motion": "^10",
"ogl": "^1.0.8", "ogl": "^1.0.9",
"sanitize.css": "^13.0.0", "sanitize.css": "^13.0.0",
"swell-js": "^4.2.2", "swell-js": "^4.2.4",
"tweakpane": "^4.0.4", "tweakpane": "^4.0.5",
"utils": "workspace:*" "utils": "workspace:*"
}, },
"devDependencies": { "devDependencies": {
"@sveltejs/adapter-auto": "^3.2.2", "@sveltejs/adapter-auto": "^3.3.1",
"@sveltejs/adapter-cloudflare": "^4.7.0", "@sveltejs/adapter-cloudflare": "^4.7.4",
"@sveltejs/kit": "^2.5.20", "@sveltejs/kit": "^2.8.1",
"@typescript-eslint/eslint-plugin": "^8.0.0", "@typescript-eslint/eslint-plugin": "^8.14.0",
"@typescript-eslint/parser": "^8.0.0", "@typescript-eslint/parser": "^8.14.0",
"base-64": "^1.0.0", "base-64": "^1.0.0",
"browserslist": "^4.23.3", "browserslist": "^4.24.2",
"config": "workspace:*", "config": "workspace:*",
"cssnano": "^7.0.4", "cssnano": "^7.0.6",
"eslint": "^9.8.0", "eslint": "^9.14.0",
"eslint-plugin-svelte": "^2.43.0", "eslint-plugin-svelte": "^2.46.0",
"postcss": "^8.4.40", "postcss": "^8.4.49",
"postcss-focus-visible": "^9.0.1", "postcss-focus-visible": "^10.0.1",
"postcss-normalize": "^10.0.1", "postcss-normalize": "^13.0.1",
"postcss-preset-env": "^9.6.0", "postcss-preset-env": "^10.1.0",
"postcss-sort-media-queries": "^5.2.0", "postcss-sort-media-queries": "^5.2.0",
"sass": "^1.77.8", "sass": "^1.80.7",
"svelte": "^5.0.0-next.208", "svelte": "^5.1.16",
"svelte-check": "^3.8.5", "svelte-check": "^4.0.7",
"svelte-preprocess": "^6.0.2", "svelte-preprocess": "^6.0.3",
"tslib": "^2.6.3", "tslib": "^2.8.1",
"typescript": "^5.5.4", "typescript": "^5.6.3",
"vite": "5.3.5" "vite": "5.4.11"
}, },
"type": "module", "type": "module",
"browserslist": [ "browserslist": [

View File

@@ -1,6 +1,4 @@
<style lang="scss"> <style lang="scss" src="./BoxCTA.scss"></style>
@import "./BoxCTA";
</style>
<script lang="ts"> <script lang="ts">
import Icon from '$components/atoms/Icon.svelte' import Icon from '$components/atoms/Icon.svelte'

View File

@@ -1,3 +1,5 @@
@use "sass:color";
.button { .button {
display: inline-flex; display: inline-flex;
align-items: center; align-items: center;
@@ -116,7 +118,7 @@
// Hover // Hover
&:not([disabled]):hover { &:not([disabled]):hover {
color: $color-text; color: $color-text;
background-color: darken($color-secondary, 7); background-color: color.adjust($color-secondary, $lightness: -7%);
} }
} }
@@ -128,7 +130,7 @@
&[disabled] { &[disabled] {
background: none; background: none;
border: 2px solid darken($color-button, 2); border: 2px solid color.adjust($color-button, $lightness: -2%);
} }
// Hover // Hover
@@ -138,7 +140,7 @@
} }
} }
&:not([disabled]):hover { &:not([disabled]):hover {
background: darken($color-button, 2.5); background: color.adjust($color-button, $lightness: -2.5%);
} }
} }

View File

@@ -1,6 +1,4 @@
<style lang="scss"> <style lang="scss" src="./Button.scss"></style>
@import "./Button";
</style>
<script lang="ts"> <script lang="ts">
import { cx } from 'classix' import { cx } from 'classix'

View File

@@ -1,6 +1,4 @@
<style lang="scss"> <style lang="scss" src="./ButtonCart.scss"></style>
@import "./ButtonCart";
</style>
<script lang="ts"> <script lang="ts">
import { scale } from 'svelte/transition' import { scale } from 'svelte/transition'

View File

@@ -1,3 +1,5 @@
@use "sass:color";
.button-circle { .button-circle {
position: relative; position: relative;
overflow: hidden; overflow: hidden;
@@ -97,7 +99,7 @@
background: $color-secondary; background: $color-secondary;
&:hover { &:hover {
background: darken($color-secondary, 7); background: color.adjust($color-secondary, $lightness: -7%);
} }
} }

View File

@@ -1,6 +1,4 @@
<style lang="scss"> <style lang="scss" src="./ButtonCircle.scss"></style>
@import "./ButtonCircle";
</style>
<script lang="ts"> <script lang="ts">
import { cx } from 'classix' import { cx } from 'classix'

View File

@@ -35,7 +35,7 @@
let scrollY = $state<number>() let scrollY = $state<number>()
let innerWidth = $state<number>() let innerWidth = $state<number>()
let innerHeight = $state<number>() let innerHeight = $state<number>()
let titleEl: HTMLElement let titleEl = $state<HTMLElement>(undefined)
// Check if title is larger than viewport to translate it // Check if title is larger than viewport to translate it
const isLarger = $derived<boolean>(titleEl && titleEl.offsetWidth >= innerWidth) const isLarger = $derived<boolean>(titleEl && titleEl.offsetWidth >= innerWidth)

View File

@@ -1,6 +1,4 @@
<style lang="scss"> <style lang="scss" src="./SiteTitle.scss"></style>
@import "./SiteTitle";
</style>
<script lang="ts"> <script lang="ts">
import SplitText from '$components/SplitText.svelte' import SplitText from '$components/SplitText.svelte'

View File

@@ -1,6 +1,4 @@
<style lang="scss"> <style lang="scss" src="./PosterLayout.scss"></style>
@import "./PosterLayout";
</style>
<script lang="ts"> <script lang="ts">
import { addToCart } from '$utils/functions/shop' import { addToCart } from '$utils/functions/shop'

View File

@@ -1,6 +1,4 @@
<style lang="scss"> <style lang="scss" src="./CartItem.scss"></style>
@import "./CartItem";
</style>
<script lang="ts"> <script lang="ts">
import ButtonCircle from '$components/atoms/ButtonCircle/ButtonCircle.svelte' import ButtonCircle from '$components/atoms/ButtonCircle/ButtonCircle.svelte'

View File

@@ -1,6 +1,4 @@
<style lang="scss"> <style lang="scss" src="./EmailForm.scss"></style>
@import "./EmailForm";
</style>
<script lang="ts"> <script lang="ts">
import { fly } from 'svelte/transition' import { fly } from 'svelte/transition'

View File

@@ -1,6 +1,4 @@
<style lang="scss"> <style lang="scss" src="./Heading.scss"></style>
@import "./Heading";
</style>
<script lang="ts"> <script lang="ts">
import SiteTitle from '$components/atoms/SiteTitle/SiteTitle.svelte' import SiteTitle from '$components/atoms/SiteTitle/SiteTitle.svelte'

View File

@@ -1,6 +1,4 @@
<style lang="scss"> <style lang="scss" src="./House.scss"></style>
@import "./House";
</style>
<script lang="ts"> <script lang="ts">
import dayjs from 'dayjs' import dayjs from 'dayjs'

View File

@@ -1,6 +1,4 @@
<style lang="scss"> <style lang="scss" src="./Location.scss"></style>
@import "./Location";
</style>
<script lang="ts"> <script lang="ts">
import { PUBLIC_PREVIEW_COUNT } from '$env/static/public' import { PUBLIC_PREVIEW_COUNT } from '$env/static/public'
@@ -24,7 +22,7 @@
const { settings }: any = getContext('global') const { settings }: any = getContext('global')
let locationEl: HTMLElement let locationEl = $state<HTMLElement>(undefined)
let photoIndex = $state(0) let photoIndex = $state(0)
// Location date limit // Location date limit

View File

@@ -1,6 +1,4 @@
<style lang="scss"> <style lang="scss" src="./NewsletterIssue.scss"></style>
@import "./NewsletterIssue";
</style>
<script lang="ts"> <script lang="ts">
import dayjs from 'dayjs' import dayjs from 'dayjs'

View File

@@ -1,6 +1,4 @@
<style lang="scss"> <style lang="scss" src="./NotificationCart.scss"></style>
@import "./NotificationCart";
</style>
<script lang="ts"> <script lang="ts">
import { fly } from 'svelte/transition' import { fly } from 'svelte/transition'

View File

@@ -1,6 +1,4 @@
<style lang="scss"> <style lang="scss" src="./Pagination.scss"></style>
@import "./Pagination";
</style>
<script lang="ts"> <script lang="ts">
let { let {

View File

@@ -1,6 +1,4 @@
<style lang="scss"> <style lang="scss" src="./PhotoCard.scss"></style>
@import "./PhotoCard";
</style>
<script lang="ts"> <script lang="ts">
import Image from '$components/atoms/Image.svelte' import Image from '$components/atoms/Image.svelte'

View File

@@ -1,6 +1,4 @@
<style lang="scss"> <style lang="scss" src="./PostCard.scss"></style>
@import "./PostCard";
</style>
<script lang="ts"> <script lang="ts">
import { cx } from 'classix' import { cx } from 'classix'

View File

@@ -1,3 +1,5 @@
@use "sass:color";
.poster { .poster {
position: relative; position: relative;
border-radius: 6px; border-radius: 6px;
@@ -93,7 +95,7 @@
&:hover { &:hover {
@include bp (md) { @include bp (md) {
background-color: darken($color-secondary, 7); background-color: color.adjust($color-secondary, $lightness: -7%);
} }
} }
} }

View File

@@ -1,6 +1,4 @@
<style lang="scss"> <style lang="scss" src="./Poster.scss"></style>
@import "./Poster";
</style>
<script lang="ts"> <script lang="ts">
import { addToCart } from '$utils/functions/shop' import { addToCart } from '$utils/functions/shop'

View File

@@ -1,6 +1,4 @@
<style lang="scss"> <style lang="scss" src="./ProcessStep.scss"></style>
@import "./ProcessStep";
</style>
<script lang="ts"> <script lang="ts">
import { scale } from 'svelte/transition' import { scale } from 'svelte/transition'

View File

@@ -1,6 +1,4 @@
<style lang="scss"> <style lang="scss" src="./ShopLocationSwitcher.scss"></style>
@import "./ShopLocationSwitcher";
</style>
<script lang="ts"> <script lang="ts">
import { goto } from '$app/navigation' import { goto } from '$app/navigation'

View File

@@ -1,6 +1,4 @@
<style lang="scss"> <style lang="scss" src="./Switcher.scss"></style>
@import "./Switcher";
</style>
<script lang="ts"> <script lang="ts">
import { page } from '$app/stores' import { page } from '$app/stores'
@@ -12,7 +10,7 @@
const { settings: { switcher_links } }: any = getContext('global') const { settings: { switcher_links } }: any = getContext('global')
let switcherEl: HTMLElement let switcherEl = $state<HTMLElement>(undefined)
let isOpen = $state(false) let isOpen = $state(false)

View File

@@ -1,6 +1,4 @@
<style lang="scss"> <style lang="scss" src="./Toast.scss"></style>
@import "./Toast";
</style>
<script lang="ts"> <script lang="ts">
import { fade, fly } from 'svelte/transition' import { fade, fly } from 'svelte/transition'

View File

@@ -1,6 +1,4 @@
<style lang="scss"> <style lang="scss" src="./Banner.scss"></style>
@import "./Banner";
</style>
<script lang="ts"> <script lang="ts">
// Components // Components

View File

@@ -1,6 +1,4 @@
<style lang="scss"> <style lang="scss" src="./Carousel.scss"></style>
@import "./Carousel";
</style>
<script lang="ts"> <script lang="ts">
import { writable } from 'svelte/store' import { writable } from 'svelte/store'
@@ -17,7 +15,7 @@
class?: string class?: string
} = $props() } = $props()
let carouselEl = $state<HTMLElement>() let carouselEl = $state<HTMLElement>(undefined)
let carousel: EmblaCarouselType let carousel: EmblaCarouselType
let currentSlide = $state(0) let currentSlide = $state(0)
let arrowDirection = $state<'next' | 'prev'>() let arrowDirection = $state<'next' | 'prev'>()

View File

@@ -1,6 +1,4 @@
<style lang="scss"> <style lang="scss" src="./Cart.scss"></style>
@import "./Cart";
</style>
<script lang="ts"> <script lang="ts">
import { fade, fly } from 'svelte/transition' import { fade, fly } from 'svelte/transition'

View File

@@ -1,6 +1,4 @@
<style lang="scss"> <style lang="scss" src="./Collage.scss"></style>
@import "./Collage";
</style>
<script lang="ts"> <script lang="ts">
import PhotoCard from '$components/molecules/PhotoCard/PhotoCard.svelte' import PhotoCard from '$components/molecules/PhotoCard/PhotoCard.svelte'

View File

@@ -1,6 +1,4 @@
<style lang="scss"> <style lang="scss" src="./Footer.scss"></style>
@import "./Footer";
</style>
<script lang="ts"> <script lang="ts">
import { getContext } from 'svelte' import { getContext } from 'svelte'

View File

@@ -1,6 +1,4 @@
<style lang="scss"> <style lang="scss" src="./InteractiveGlobe.scss"></style>
@import "./InteractiveGlobe";
</style>
<script lang="ts"> <script lang="ts">
import { dev } from '$app/environment' import { dev } from '$app/environment'
@@ -33,8 +31,8 @@
} = $props() } = $props()
let innerWidth = $state<number>() let innerWidth = $state<number>()
let globeParentEl: HTMLElement let globeParentEl = $state<HTMLElement>(undefined)
let globeEl: HTMLElement let globeEl = $state<HTMLElement>(undefined)
let globe = $state<any>() let globe = $state<any>()
let observer: IntersectionObserver let observer: IntersectionObserver
let animation = $state<number>() let animation = $state<number>()

View File

@@ -1,6 +1,4 @@
<style lang="scss"> <style lang="scss" src="./Locations.scss"></style>
@import "./Locations";
</style>
<script lang="ts"> <script lang="ts">
import { getContext } from 'svelte' import { getContext } from 'svelte'

View File

@@ -1,6 +1,4 @@
<style lang="scss"> <style lang="scss" src="./NewsletterModule.scss"></style>
@import "./NewsletterModule";
</style>
<script lang="ts"> <script lang="ts">
import { getContext } from 'svelte' import { getContext } from 'svelte'

View File

@@ -1,6 +1,4 @@
<style lang="scss"> <style lang="scss" src="./PostersGrid.scss"></style>
@import "./PostersGrid";
</style>
<script lang="ts"> <script lang="ts">
import { getContext } from 'svelte' import { getContext } from 'svelte'
@@ -16,7 +14,7 @@
} = $props() } = $props()
let innerWidth = $state<number>() let innerWidth = $state<number>()
let carouselEl = $state<HTMLElement>() let carouselEl = $state<HTMLElement>(undefined)
let carousel = $state<EmblaCarouselType>() let carousel = $state<EmblaCarouselType>()
let currentSlide = $state(0) let currentSlide = $state(0)
let carouselDots = $state([]) let carouselDots = $state([])

View File

@@ -1,10 +1,8 @@
<style lang="scss"> <style lang="scss" src="./ShopBanner.scss"></style>
@import "./ShopBanner";
</style>
<script lang="ts"> <script lang="ts">
import { navigating } from '$app/stores' import { navigating } from '$app/stores'
import { getContext } from 'svelte' import { getContext, onMount } from 'svelte'
import { stagger, timeline } from 'motion' import { stagger, timeline } from 'motion'
import { smoothScroll } from '$utils/stores' import { smoothScroll } from '$utils/stores'
import { cartOpen } from '$utils/stores/shop' import { cartOpen } from '$utils/stores/shop'
@@ -21,8 +19,8 @@
let innerWidth = $state<number>() let innerWidth = $state<number>()
let navObserver: IntersectionObserver let navObserver: IntersectionObserver
let introEl: HTMLElement let introEl = $state<HTMLElement>(undefined)
let navChooseEl: HTMLElement let navChooseEl = $state<HTMLElement>(undefined)
let scrolledPastIntro = $state(false) let scrolledPastIntro = $state(false)
@@ -46,7 +44,14 @@
navChooseEl.scrollLeft = offsetLeft navChooseEl.scrollLeft = offsetLeft
} }
// Destroy
return () => {
navObserver && navObserver.disconnect()
}
})
onMount(() => {
/** /**
* Animations * Animations
*/ */
@@ -97,12 +102,6 @@
// Run animation // Run animation
requestAnimationFrame(animation.play) requestAnimationFrame(animation.play)
// Destroy
return () => {
navObserver && navObserver.disconnect()
}
}) })
</script> </script>

View File

@@ -1,6 +1,4 @@
<style lang="scss"> <style lang="scss" src="./ShopModule.scss"></style>
@import "./ShopModule";
</style>
<script lang="ts"> <script lang="ts">
import { getContext } from 'svelte' import { getContext } from 'svelte'

View File

@@ -1,6 +1,4 @@
<style lang="scss"> <style lang="scss" src="../../../style/pages/shop.scss"></style>
@import "../../../style/pages/shop";
</style>
<script lang="ts"> <script lang="ts">
import { setContext } from 'svelte' import { setContext } from 'svelte'

View File

@@ -1,10 +1,9 @@
<style lang="scss"> <style lang="scss" src="../../../../style/pages/location.scss"></style>
@import "../../../../style/pages/location";
</style>
<script lang="ts"> <script lang="ts">
import { PUBLIC_LIST_INCREMENT } from '$env/static/public' import { PUBLIC_LIST_INCREMENT } from '$env/static/public'
import { page, navigating } from '$app/stores' import { page, navigating } from '$app/stores'
import { onMount } from 'svelte'
import { scroll, stagger, timeline } from 'motion' import { scroll, stagger, timeline } from 'motion'
import dayjs from 'dayjs' import dayjs from 'dayjs'
import relativeTime from 'dayjs/plugin/relativeTime' import relativeTime from 'dayjs/plugin/relativeTime'
@@ -35,8 +34,8 @@
dayjs.extend(relativeTime) dayjs.extend(relativeTime)
let introEl: HTMLElement let introEl = $state<HTMLElement>(undefined)
let photosListEl = $state<HTMLElement>() let photosListEl = $state<HTMLElement>(undefined)
let observerPhotos: IntersectionObserver let observerPhotos: IntersectionObserver
let mutationPhotos: MutationObserver let mutationPhotos: MutationObserver
let currentPage = $state(1) let currentPage = $state(1)
@@ -146,6 +145,15 @@
}) })
// Destroy
return () => {
observerPhotos && observerPhotos.disconnect()
mutationPhotos && mutationPhotos.disconnect()
}
})
onMount(() => {
/** /**
* Animations * Animations
*/ */
@@ -194,13 +202,6 @@
// Run animation // Run animation
requestAnimationFrame(animation.play) requestAnimationFrame(animation.play)
// Destroy
return () => {
observerPhotos && observerPhotos.disconnect()
mutationPhotos && mutationPhotos.disconnect()
}
}) })
</script> </script>

View File

@@ -1,11 +1,9 @@
<style lang="scss"> <style lang="scss" src="../../../../../style/pages/viewer.scss"></style>
@import "../../../../../style/pages/viewer";
</style>
<script lang="ts"> <script lang="ts">
import { page, navigating } from '$app/stores' import { page, navigating } from '$app/stores'
import { goto } from '$app/navigation' import { goto } from '$app/navigation'
import { tick } from 'svelte' import { onMount, tick } from 'svelte'
import { fade, scale } from 'svelte/transition' import { fade, scale } from 'svelte/transition'
import { quartOut } from 'svelte/easing' import { quartOut } from 'svelte/easing'
import dayjs from 'dayjs' import dayjs from 'dayjs'
@@ -32,7 +30,7 @@
enum directions { PREV, NEXT } enum directions { PREV, NEXT }
let innerWidth = $state<number>() let innerWidth = $state<number>()
let fullscreenEl = $state<HTMLElement>() let fullscreenEl = $state<HTMLElement>(undefined)
let globalOffset = $state(data.offset) let globalOffset = $state(data.offset)
let isLoading = $state(false) let isLoading = $state(false)
let isFullscreen = $state(false) let isFullscreen = $state(false)
@@ -218,7 +216,7 @@
} }
$effect(() => { onMount(() => {
/** /**
* Animations * Animations
*/ */

View File

@@ -1,6 +1,4 @@
<style lang="scss"> <style lang="scss" src="../../../style/pages/about.scss"></style>
@import "../../../style/pages/about";
</style>
<script lang="ts"> <script lang="ts">
import { navigating } from '$app/stores' import { navigating } from '$app/stores'
@@ -20,11 +18,12 @@
import AboutGridPhoto from '$components/atoms/AboutGridPhoto.svelte' import AboutGridPhoto from '$components/atoms/AboutGridPhoto.svelte'
import ProcessStep from '$components/molecules/ProcessStep/ProcessStep.svelte' import ProcessStep from '$components/molecules/ProcessStep/ProcessStep.svelte'
import Banner from '$components/organisms/Banner/Banner.svelte' import Banner from '$components/organisms/Banner/Banner.svelte'
import { onMount } from 'svelte';
let { data } = $props() let { data } = $props()
let innerWidth = $state<number>() let innerWidth = $state<number>()
let photosGridEl: HTMLElement let photosGridEl = $state<HTMLElement>(undefined)
let photosGridParallax = $state<number>() let photosGridParallax = $state<number>()
let currentStepIndex = $state(0) let currentStepIndex = $state(0)
const currentStep = $derived(data.about.process_steps[currentStepIndex]) const currentStep = $derived(data.about.process_steps[currentStepIndex])
@@ -40,71 +39,11 @@
$effect(() => { $effect(() => {
// Add parallax to photos grid // Add parallax to photos grid
scroll(({ y }) => photosGridParallax = lerp(-15, 10, y.progress), { scroll(({ y }) => photosGridParallax = lerp(-10, 20, y.progress), {
target: photosGridEl, target: photosGridEl,
offset: ['start end', 'end start'] offset: ['start end', 'end start']
}) })
/**
* Animations
*/
const animation = timeline([
// Banner
['.banner picture', {
scale: [1.06, 1],
opacity: [0, 1],
z: 0,
}, {
at: 0.4,
duration: 2.4,
}],
['.banner h1', {
y: [32, 0],
opacity: [0, 1],
}, {
at: 0.5,
}],
['.banner__top > *', {
y: [-100, 0],
opacity: [0, 1],
}, {
at: 0.4,
delay: stagger(0.25),
}],
// Intro elements
['.about__introduction .container > *', {
y: ['20%', 0],
opacity: [0, 1],
z: 0,
}, {
at: 0.75,
delay: stagger(0.25),
}],
['.first-photo', {
y: ['10%', 0],
opacity: [0, 1],
z: 0,
}, {
at: 1.2,
}],
['.first-photo img', {
scale: [1.06, 1],
opacity: [0, 1],
z: 0,
}, {
at: 1.5,
duration: 2.4,
}],
], {
delay: $navigating ? DELAY.PAGE_LOADING / 1000 : 0,
defaultOptions: {
duration: 1.6,
easing: quartOut,
},
})
animation.stop()
// Sections // Sections
inView('[data-reveal]', ({ target }) => { inView('[data-reveal]', ({ target }) => {
animate(target, { animate(target, {
@@ -165,6 +104,69 @@
}, { }, {
amount: 0.35, amount: 0.35,
}) })
})
onMount(() => {
/**
* Animations
*/
const animation = timeline([
// Banner
['.banner picture', {
scale: [1.06, 1],
opacity: [0, 1],
z: 0,
}, {
at: 0.4,
duration: 2.4,
}],
['.banner h1', {
y: [32, 0],
opacity: [0, 1],
}, {
at: 0.5,
}],
['.banner__top > *', {
y: [-100, 0],
opacity: [0, 1],
}, {
at: 0.4,
delay: stagger(0.25),
}],
// Intro elements
['.about__introduction .container > *', {
y: ['20%', 0],
opacity: [0, 1],
z: 0,
}, {
at: 0.75,
delay: stagger(0.25),
}],
['.first-photo', {
y: ['10%', 0],
opacity: [0, 1],
z: 0,
}, {
at: 1.2,
}],
['.first-photo img', {
scale: [1.06, 1],
opacity: [0, 1],
z: 0,
}, {
at: 1.5,
duration: 2.4,
}],
], {
delay: $navigating ? DELAY.PAGE_LOADING / 1000 : 0,
defaultOptions: {
duration: 1.6,
easing: quartOut,
},
})
animation.stop()
// Run animation // Run animation
requestAnimationFrame(animation.play) requestAnimationFrame(animation.play)

View File

@@ -13,8 +13,8 @@ export const load = async ({ setHeaders }) => {
credit (filter: { status: { _eq: "published" }}) { credit (filter: { status: { _eq: "published" }}) {
name name
website website
location { location (sort: "location_id.slug") {
location_id (filter: { status: { _eq: "published" }}) { location_id (filter: { status: { _eq: "published" }}, sort: ["slug"]) {
name name
slug slug
country { country {

View File

@@ -1,9 +1,8 @@
<style lang="scss"> <style lang="scss" src="../../../style/pages/credits.scss"></style>
@import "../../../style/pages/credits";
</style>
<script lang="ts"> <script lang="ts">
import { navigating } from '$app/stores' import { navigating } from '$app/stores'
import { onMount } from 'svelte'
import { stagger, timeline } from 'motion' import { stagger, timeline } from 'motion'
import { DELAY } from '$utils/constants' import { DELAY } from '$utils/constants'
import { quartOut } from 'svelte/easing' import { quartOut } from 'svelte/easing'
@@ -17,7 +16,7 @@
const { credit } = data const { credit } = data
$effect(() => { onMount(() => {
/** /**
* Animations * Animations
*/ */

View File

@@ -1,6 +1,4 @@
<style lang="scss"> <style lang="scss" src="../../../style/pages/explore.scss"></style>
@import "../../../style/pages/explore";
</style>
<script lang="ts"> <script lang="ts">
import { getContext } from 'svelte' import { getContext } from 'svelte'

View File

@@ -1,12 +1,10 @@
<style lang="scss"> <style lang="scss" src="../../../style/pages/photos.scss"></style>
@import "../../../style/pages/photos";
</style>
<script lang="ts"> <script lang="ts">
import { PUBLIC_FILTERS_DEFAULT_COUNTRY, PUBLIC_FILTERS_DEFAULT_SORT, PUBLIC_GRID_INCREMENT } from '$env/static/public' import { PUBLIC_FILTERS_DEFAULT_COUNTRY, PUBLIC_FILTERS_DEFAULT_SORT, PUBLIC_GRID_INCREMENT } from '$env/static/public'
import { page, navigating } from '$app/stores' import { page, navigating } from '$app/stores'
import { goto } from '$app/navigation' import { goto } from '$app/navigation'
import { getContext } from 'svelte' import { getContext, onMount } from 'svelte'
import { fly } from 'svelte/transition' import { fly } from 'svelte/transition'
import { quartOut as quartOutSvelte } from 'svelte/easing' import { quartOut as quartOutSvelte } from 'svelte/easing'
import dayjs from 'dayjs' import dayjs from 'dayjs'
@@ -31,14 +29,14 @@
let { data } = $props() let { data } = $props()
let photos = $state<any[]>(data.photos) let photos = $state<any[]>([...data.photos])
const totalPhotos = $derived<number>(data.totalPhotos) const totalPhotos = $derived<number>(data.totalPhotos)
const { filteredCountryExists, settings }: { filteredCountryExists: boolean, settings: any } = data const { filteredCountryExists, settings }: { filteredCountryExists: boolean, settings: any } = data
const { countries, locations }: any = getContext('global') const { countries, locations }: any = getContext('global')
dayjs.extend(relativeTime) dayjs.extend(relativeTime)
let photosGridEl = $state<HTMLElement>() let photosGridEl = $state<HTMLElement>(undefined)
let observerPhotos: IntersectionObserver let observerPhotos: IntersectionObserver
let mutationPhotos: MutationObserver let mutationPhotos: MutationObserver
let scrollY = $state<number>() let scrollY = $state<number>()
@@ -75,15 +73,13 @@
/** /**
* Handle URL query params * Handle URL query params
*/ */
const countryFlagId = $derived(currentCountry ? currentCountry.flag.id : undefined)
// Update URL filtering params from filter values // Update URL filtering params from filter values
const applyFilters = () => { const applyFilters = () => {
urlFiltersParams.set('country', filterCountry) urlFiltersParams.set('country', filterCountry)
urlFiltersParams.set('sort', filterSort) urlFiltersParams.set('sort', filterSort)
let path = `${$page.url.pathname}?${urlFiltersParams.toString()}` const path = `${$page.url.pathname}?${urlFiltersParams.toString()}`
goto(path, { replaceState: true, keepFocus: true, noScroll: true }) goto(path, { keepFocus: true, replaceState: true, noScroll: true })
} }
@@ -111,14 +107,14 @@
* Filters change events * Filters change events
*/ */
/** Country select */ /** Country select */
const handleCountryChange = ({ detail: value }) => { const handleCountryChange = (value: string) => {
filterCountry = value === defaultCountry ? defaultCountry : value filterCountry = value === defaultCountry ? defaultCountry : value
currentPage = 1 currentPage = 1
applyFilters() applyFilters()
} }
/** Sort select */ /** Sort select */
const handleSortChange = ({ detail: value }) => { const handleSortChange = (value: string) => {
filterSort = value === defaultSort ? defaultSort : value filterSort = value === defaultSort ? defaultSort : value
currentPage = 1 currentPage = 1
applyFilters() applyFilters()
@@ -199,7 +195,15 @@
} }
// Workaround: Reactive photos based on data
$effect(() => { $effect(() => {
if (data.photos) {
photos = data.photos
}
})
onMount(() => {
/** /**
* Observers * Observers
*/ */
@@ -234,7 +238,6 @@
const existingPhotos = photosGridEl.querySelectorAll('.photo') const existingPhotos = photosGridEl.querySelectorAll('.photo')
existingPhotos.forEach(el => observerPhotos.observe(el)) existingPhotos.forEach(el => observerPhotos.observe(el))
/** /**
* Animations * Animations
*/ */
@@ -259,7 +262,6 @@
// Run animation // Run animation
requestAnimationFrame(animation.play) requestAnimationFrame(animation.play)
// Destroy // Destroy
return () => { return () => {
// Disconnect observers // Disconnect observers
@@ -309,10 +311,10 @@
onchange={handleCountryChange} onchange={handleCountryChange}
value={filterCountry} value={filterCountry}
> >
{#if countryFlagId} {#if currentCountry?.flag?.id}
<Image <Image
class="icon" class="icon"
id={countryFlagId} id={currentCountry?.flag?.id}
sizeKey="square-small" sizeKey="square-small"
width={26} height={26} width={26} height={26}
alt="{filterCountry} flag" alt="{filterCountry} flag"

View File

@@ -1,9 +1,8 @@
<style lang="scss"> <style lang="scss" src="../../../style/pages/subscribe.scss"></style>
@import "../../../style/pages/subscribe";
</style>
<script lang="ts"> <script lang="ts">
import { navigating } from '$app/stores' import { navigating } from '$app/stores'
import { onMount } from 'svelte'
import { stagger, timeline } from 'motion' import { stagger, timeline } from 'motion'
import { DELAY } from '$utils/constants' import { DELAY } from '$utils/constants'
import { quartOut } from '$animations/easings' import { quartOut } from '$animations/easings'
@@ -19,7 +18,7 @@
const latestIssue = $derived(data.issues[0]) const latestIssue = $derived(data.issues[0])
$effect(() => { onMount(() => {
/** /**
* Animations * Animations
*/ */

View File

@@ -1,6 +1,4 @@
<style lang="scss"> <style lang="scss" src="../../../style/pages/terms.scss"></style>
@import "../../../style/pages/terms";
</style>
<script lang="ts"> <script lang="ts">
import dayjs from 'dayjs' import dayjs from 'dayjs'

View File

@@ -1,6 +1,4 @@
<style lang="scss"> <style lang="scss" src="../style/pages/error.scss"></style>
@import "../style/pages/error";
</style>
<script lang="ts"> <script lang="ts">
import { getContext } from 'svelte' import { getContext } from 'svelte'

View File

@@ -15,6 +15,7 @@
</style> </style>
<script lang="ts"> <script lang="ts">
import 'sanitize.css'
import '../style/global.scss' import '../style/global.scss'
import { PUBLIC_ANALYTICS_DOMAIN } from '$env/static/public' import { PUBLIC_ANALYTICS_DOMAIN } from '$env/static/public'
@@ -94,7 +95,7 @@
<svelte:window bind:innerHeight /> <svelte:window bind:innerHeight />
<svelte:head> <svelte:head>
<link rel="canonical" href={$page.url.href} /> <link rel="canonical" href={$page.url.href.split('#')[0]} />
{#each fonts as font} {#each fonts as font}
<link rel="preload" href="/fonts/{font}.woff2" as="font" type="font/woff2" crossorigin="anonymous"> <link rel="preload" href="/fonts/{font}.woff2" as="font" type="font/woff2" crossorigin="anonymous">

View File

@@ -1,10 +1,8 @@
<style lang="scss"> <style lang="scss" src="../style/pages/homepage.scss"></style>
@import "../style/pages/homepage";
</style>
<script lang="ts"> <script lang="ts">
import { navigating } from '$app/stores' import { navigating } from '$app/stores'
import { getContext } from 'svelte' import { getContext, onMount } from 'svelte'
import { timeline, stagger } from 'motion' import { timeline, stagger } from 'motion'
import { DELAY } from '$utils/constants' import { DELAY } from '$utils/constants'
import { smoothScroll } from '$utils/stores' import { smoothScroll } from '$utils/stores'
@@ -34,7 +32,7 @@
let innerHeight = $state<number>() let innerHeight = $state<number>()
$effect(() => { onMount(() => {
/** /**
* Animations * Animations
*/ */

View File

@@ -1,3 +1,6 @@
@use "imports" as *;
/* /*
** Earth icon ** Earth icon
*/ */

View File

@@ -1,3 +1,6 @@
@use "../imports" as *;
.photo { .photo {
overflow: hidden; overflow: hidden;
background: $color-primary-tertiary20; background: $color-primary-tertiary20;

View File

@@ -1,3 +1,6 @@
@use "imports" as *;
html { html {
font: #{$base-font-size}/1.2 $font-sans; font: #{$base-font-size}/1.2 $font-sans;
font-weight: 400; font-weight: 400;

View File

@@ -1,3 +1,6 @@
@use "imports" as *;
/* /*
** Box shadows ** Box shadows
*/ */

View File

@@ -1,3 +1,5 @@
@use "imports" as *;
/* Fonts list /* Fonts list
========================================================================== */ ========================================================================== */
@include font-face("Garnett", "G-Light", 200); @include font-face("Garnett", "G-Light", 200);
@@ -5,4 +7,4 @@
@include font-face("Garnett", "G-Medium", 500); @include font-face("Garnett", "G-Medium", 500);
@include font-face("Garnett", "G-Semibold", 600); @include font-face("Garnett", "G-Semibold", 600);
@include font-face("Jazmin", "J-Extralight", 200); @include font-face("Jazmin", "J-Extralight", 200);
@include font-face("Jazmin", "J-Light", 300); @include font-face("Jazmin", "J-Light", 300);

View File

@@ -1,25 +1,22 @@
@charset "UTF-8"; @charset "UTF-8";
// Dependencies
@import "sanitize.css/sanitize";
// Tools // Tools
@import "tools/helpers"; @forward "tools/helpers";
// Base // Base
@import "variables-css"; @forward "variables-css";
@import "base"; @forward "base";
@import "fonts"; @forward "fonts";
@import "typography"; @forward "typography";
@import "effects";
// Layout // Layout
@import "layout/grid"; @forward "layout/grid";
@import "layout/modules"; @forward "layout/modules";
// Misc // Misc
@import "animations"; @forward "animations";
@forward "effects";
// Components (Atomic Design System) // Components (Atomic Design System)
// Atoms // Atoms
@import "atoms/photo"; @forward "atoms/photo";

View File

@@ -1,4 +1,3 @@
// Tools @forward "variables";
@import "variables"; @forward "tools/mixins";
@import "tools/mixins"; @forward "tools/functions";
@import "tools/functions";

View File

@@ -1,3 +1,6 @@
@use "../imports" as *;
/* /*
** Grid ** Grid
*/ */

View File

@@ -1,3 +1,6 @@
@use "../imports" as *;
.grid-modules { .grid-modules {
padding-bottom: 40px; padding-bottom: 40px;

View File

@@ -1,4 +1,7 @@
@use "sass:math"; @use "sass:math";
@use "sass:color";
@use "../variables" as *;
/* PX to REM /* PX to REM
========================================================================== */ ========================================================================== */
@@ -39,5 +42,5 @@
/* HEX color to RGB /* HEX color to RGB
========================================================================== */ ========================================================================== */
@function hexToRGB($color) { @function hexToRGB($color) {
@return red($color), green($color), blue($color); @return color.channel($color, "red", $space: rgb), color.channel($color, "green", $space: rgb), color.channel($color, "blue", $space: rgb);
} }

View File

@@ -1,3 +1,6 @@
@use "../imports" as *;
/* Classes /* Classes
========================================================================== */ ========================================================================== */
.clear { .clear {

View File

@@ -1,4 +1,7 @@
@use "sass:math"; @use "sass:math";
@use "sass:map";
@use "../variables" as *;
// Hide text // Hide text
%hide-text { %hide-text {
@@ -51,8 +54,8 @@
// Based on Width // Based on Width
@mixin bp ($size, $to: min, $sizes: $breakpoints) { @mixin bp ($size, $to: min, $sizes: $breakpoints) {
// Size is in map // Size is in map
@if map-has-key($sizes, $size) { @if map.has-key($sizes, $size) {
$size: map-get($sizes, $size); $size: map.get($sizes, $size);
@if ($to == max) { @if ($to == max) {
@media (max-width: #{$size}) { @media (max-width: #{$size}) {

View File

@@ -1,3 +1,6 @@
@use "imports" as *;
/* ========================================================================== /* ==========================================================================
TITLES TITLES
========================================================================== */ ========================================================================== */

View File

@@ -1,3 +1,6 @@
@use "imports" as *;
:root { :root {
// Sizes // Sizes
--container-width: #{$container-width}; --container-width: #{$container-width};

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 5.9 KiB

View File

@@ -1,18 +1,16 @@
import { sveltePreprocess } from 'svelte-preprocess'
import adapter from '@sveltejs/adapter-cloudflare'
import { fileURLToPath } from 'url' import { fileURLToPath } from 'url'
import { dirname } from 'path' import { dirname } from 'path'
import { sveltePreprocess } from 'svelte-preprocess'
import adapter from '@sveltejs/adapter-cloudflare'
const stylePath = `${dirname(fileURLToPath(import.meta.url))}/src/style` export const globalStyles = `@use "${dirname(fileURLToPath(import.meta.url))}/src/style/imports" as *;`
export const scssImports = `@use "${stylePath}/imports.scss" as *;`
/** @type {import('@sveltejs/kit').Config} */ /** @type {import('@sveltejs/kit').Config} */
const config = { const config = {
// Preprocessors docs: https://github.com/sveltejs/svelte-preprocess // Preprocessors docs: https://github.com/sveltejs/svelte-preprocess
preprocess: sveltePreprocess({ preprocess: sveltePreprocess({
scss: { scss: {
prependData: scssImports, prependData: globalStyles,
renderSync: true,
} }
}), }),

View File

@@ -1,15 +1,16 @@
import type { UserConfig } from 'vite' import { defineConfig } from 'vite'
import { sveltekit } from '@sveltejs/kit/vite' import { sveltekit } from '@sveltejs/kit/vite'
import { scssImports } from './svelte.config' import { globalStyles } from './svelte.config'
const config: UserConfig = { export default defineConfig({
plugins: [ plugins: [
sveltekit() sveltekit()
], ],
css: { css: {
preprocessorOptions: { preprocessorOptions: {
scss: { scss: {
additionalData: scssImports, additionalData: globalStyles,
api: 'modern',
} }
} }
}, },
@@ -18,6 +19,4 @@ const config: UserConfig = {
transformMixedEsModules: true, transformMixedEsModules: true,
} }
}, },
} })
export default config

BIN
bun.lockb

Binary file not shown.

View File

@@ -13,11 +13,11 @@
}, },
"devDependencies": { "devDependencies": {
"prettier": "^3.3.3", "prettier": "^3.3.3",
"turbo": "^2.0.11" "turbo": "^2.2.3"
}, },
"type": "module", "type": "module",
"engines": { "engines": {
"node": ">=20.0.0" "node": ">=20.0.0"
}, },
"packageManager": "bun@1.1.21" "packageManager": "bun@1.1.34"
} }