# Conflicts:
#	src/routes/photos.svelte
This commit is contained in:
2021-10-05 16:44:02 +02:00
10 changed files with 146 additions and 114 deletions

View File

@@ -18,7 +18,6 @@
"dependencies": { "dependencies": {
"dayjs": "^1.10.7", "dayjs": "^1.10.7",
"focus-visible": "^5.2.0", "focus-visible": "^5.2.0",
"motion": "^10.1.3",
"sanitize.css": "^12.0.1" "sanitize.css": "^12.0.1"
}, },
"devDependencies": { "devDependencies": {
@@ -32,7 +31,7 @@
"sass": "^1.42.1", "sass": "^1.42.1",
"svelte": "^3.43.1", "svelte": "^3.43.1",
"svelte-check": "^2.2.6", "svelte-check": "^2.2.6",
"svelte-preprocess": "^4.9.7", "svelte-preprocess": "^4.9.8",
"tslib": "^2.3.1", "tslib": "^2.3.1",
"typescript": "^4.4.3" "typescript": "^4.4.3"
}, },

82
pnpm-lock.yaml generated
View File

@@ -10,19 +10,17 @@ specifiers:
eslint: ^7.32.0 eslint: ^7.32.0
eslint-plugin-svelte3: ^3.2.1 eslint-plugin-svelte3: ^3.2.1
focus-visible: ^5.2.0 focus-visible: ^5.2.0
motion: ^10.1.3
sanitize.css: ^12.0.1 sanitize.css: ^12.0.1
sass: ^1.42.1 sass: ^1.42.1
svelte: ^3.43.1 svelte: ^3.43.1
svelte-check: ^2.2.6 svelte-check: ^2.2.6
svelte-preprocess: ^4.9.7 svelte-preprocess: ^4.9.8
tslib: ^2.3.1 tslib: ^2.3.1
typescript: ^4.4.3 typescript: ^4.4.3
dependencies: dependencies:
dayjs: 1.10.7 dayjs: 1.10.7
focus-visible: 5.2.0 focus-visible: 5.2.0
motion: 10.1.3
sanitize.css: 12.0.1 sanitize.css: 12.0.1
devDependencies: devDependencies:
@@ -36,7 +34,7 @@ devDependencies:
sass: 1.42.1 sass: 1.42.1
svelte: 3.43.1 svelte: 3.43.1
svelte-check: 2.2.6_sass@1.42.1+svelte@3.43.1 svelte-check: 2.2.6_sass@1.42.1+svelte@3.43.1
svelte-preprocess: 4.9.7_e4d174f1a3c6f6c9a7413fc1fdd258af svelte-preprocess: 4.9.8_e4d174f1a3c6f6c9a7413fc1fdd258af
tslib: 2.3.1 tslib: 2.3.1
typescript: 4.4.3 typescript: 4.4.3
@@ -62,19 +60,6 @@ packages:
js-tokens: 4.0.0 js-tokens: 4.0.0
dev: true dev: true
/@emotion/is-prop-valid/0.8.8:
resolution: {integrity: sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA==}
requiresBuild: true
dependencies:
'@emotion/memoize': 0.7.4
dev: false
optional: true
/@emotion/memoize/0.7.4:
resolution: {integrity: sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw==}
dev: false
optional: true
/@eslint/eslintrc/0.4.3: /@eslint/eslintrc/0.4.3:
resolution: {integrity: sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw==} resolution: {integrity: sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw==}
engines: {node: ^10.12.0 || >=12.0.0} engines: {node: ^10.12.0 || >=12.0.0}
@@ -900,27 +885,6 @@ packages:
resolution: {integrity: sha512-Rwix9pBtC1Nuy5wysTmKy+UjbDJpIfg8eHjw0rjZ1mX4GNLz1Bmd16uDpI3Gk1i70Fgcs8Csg2lPm8HULFg9DQ==} resolution: {integrity: sha512-Rwix9pBtC1Nuy5wysTmKy+UjbDJpIfg8eHjw0rjZ1mX4GNLz1Bmd16uDpI3Gk1i70Fgcs8Csg2lPm8HULFg9DQ==}
dev: false dev: false
/framer-motion/4.1.17:
resolution: {integrity: sha512-thx1wvKzblzbs0XaK2X0G1JuwIdARcoNOW7VVwjO8BUltzXPyONGAElLu6CiCScsOQRI7FIk/45YTFtJw5Yozw==}
peerDependencies:
react: '>=16.8 || ^17.0.0'
react-dom: '>=16.8 || ^17.0.0'
dependencies:
framesync: 5.3.0
hey-listen: 1.0.8
popmotion: 9.3.6
style-value-types: 4.1.4
tslib: 2.3.1
optionalDependencies:
'@emotion/is-prop-valid': 0.8.8
dev: false
/framesync/5.3.0:
resolution: {integrity: sha512-oc5m68HDO/tuK2blj7ZcdEBRx3p1PjrgHazL8GYEpvULhrtGIFbQArN6cQS2QhW8mitffaB+VYzMjDqBxxQeoA==}
dependencies:
tslib: 2.3.1
dev: false
/fs.realpath/1.0.0: /fs.realpath/1.0.0:
resolution: {integrity: sha1-FQStJSMVjKpA20onh8sBQRmU6k8=} resolution: {integrity: sha1-FQStJSMVjKpA20onh8sBQRmU6k8=}
dev: true dev: true
@@ -1007,10 +971,6 @@ packages:
function-bind: 1.1.1 function-bind: 1.1.1
dev: true dev: true
/hey-listen/1.0.8:
resolution: {integrity: sha512-COpmrF2NOg4TBWUJ5UVyaCU2A88wEMkUPK4hNqyCkqHbxT92BbvfjoSozkAIIm6XhicGlJHhFdullInrdhwU8Q==}
dev: false
/ignore/4.0.6: /ignore/4.0.6:
resolution: {integrity: sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==} resolution: {integrity: sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==}
engines: {node: '>= 4'} engines: {node: '>= 4'}
@@ -1181,21 +1141,6 @@ packages:
minimist: 1.2.5 minimist: 1.2.5
dev: true dev: true
/motion/10.1.3:
resolution: {integrity: sha512-/Ipnj+77iYbEs/KIFMWc+ApzoPNuxWfLw1tSET+2iIjoGtCCwWpW9zbZ3/vPyCG02P2w0rrjctFswg6/ly32Ow==}
peerDependencies:
react: ^17.0.2
react-dom: ^17.0.2
peerDependenciesMeta:
react:
optional: true
react-dom:
optional: true
dependencies:
framer-motion: 4.1.17
tslib: 2.3.1
dev: false
/mri/1.2.0: /mri/1.2.0:
resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==} resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==}
engines: {node: '>=4'} engines: {node: '>=4'}
@@ -1273,15 +1218,6 @@ packages:
engines: {node: '>=8.6'} engines: {node: '>=8.6'}
dev: true dev: true
/popmotion/9.3.6:
resolution: {integrity: sha512-ZTbXiu6zIggXzIliMi8LGxXBF5ST+wkpXGEjeTUDUOCdSQ356hij/xjeUdv0F8zCQNeqB1+PR5/BB+gC+QLAPw==}
dependencies:
framesync: 5.3.0
hey-listen: 1.0.8
style-value-types: 4.1.4
tslib: 2.3.1
dev: false
/postcss/8.3.8: /postcss/8.3.8:
resolution: {integrity: sha512-GT5bTjjZnwDifajzczOC+r3FI3Cu+PgPvrsjhQdRqa2kTJ4968/X9CUce9xttIB0xOs5c6xf0TCWZo/y9lF6bA==} resolution: {integrity: sha512-GT5bTjjZnwDifajzczOC+r3FI3Cu+PgPvrsjhQdRqa2kTJ4968/X9CUce9xttIB0xOs5c6xf0TCWZo/y9lF6bA==}
engines: {node: ^10 || ^12 || >=14} engines: {node: ^10 || ^12 || >=14}
@@ -1494,13 +1430,6 @@ packages:
engines: {node: '>=8'} engines: {node: '>=8'}
dev: true dev: true
/style-value-types/4.1.4:
resolution: {integrity: sha512-LCJL6tB+vPSUoxgUBt9juXIlNJHtBMy8jkXzUJSBzeHWdBu6lhzHqCvLVkXFGsFIlNa2ln1sQHya/gzaFmB2Lg==}
dependencies:
hey-listen: 1.0.8
tslib: 2.3.1
dev: false
/supports-color/5.5.0: /supports-color/5.5.0:
resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==}
engines: {node: '>=4'} engines: {node: '>=4'}
@@ -1529,7 +1458,7 @@ packages:
sade: 1.7.4 sade: 1.7.4
source-map: 0.7.3 source-map: 0.7.3
svelte: 3.43.1 svelte: 3.43.1
svelte-preprocess: 4.9.7_e4d174f1a3c6f6c9a7413fc1fdd258af svelte-preprocess: 4.9.8_e4d174f1a3c6f6c9a7413fc1fdd258af
typescript: 4.4.3 typescript: 4.4.3
transitivePeerDependencies: transitivePeerDependencies:
- '@babel/core' - '@babel/core'
@@ -1552,8 +1481,8 @@ packages:
svelte: 3.43.1 svelte: 3.43.1
dev: true dev: true
/svelte-preprocess/4.9.7_e4d174f1a3c6f6c9a7413fc1fdd258af: /svelte-preprocess/4.9.8_e4d174f1a3c6f6c9a7413fc1fdd258af:
resolution: {integrity: sha512-jPiizMqGTp4X3Hv00qTPbGH2r5khuqNazzlqSXZNJKo44nLVQYMyDYM1rOq3MRrzCs5Xk3J48k67u8c6fGBsvQ==} resolution: {integrity: sha512-EQS/oRZzMtYdAprppZxY3HcysKh11w54MgA63ybtL+TAZ4hVqYOnhw41JVJjWN9dhPnNjjLzvbZ2tMhTsla1Og==}
engines: {node: '>= 9.11.2'} engines: {node: '>= 9.11.2'}
requiresBuild: true requiresBuild: true
peerDependencies: peerDependencies:
@@ -1645,6 +1574,7 @@ packages:
/tslib/2.3.1: /tslib/2.3.1:
resolution: {integrity: sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==} resolution: {integrity: sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==}
dev: true
/tsutils/3.21.0_typescript@4.4.3: /tsutils/3.21.0_typescript@4.4.3:
resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==} resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==}

View File

@@ -0,0 +1,11 @@
<script lang="ts">
import { getContext } from 'svelte'
const { count }: any = getContext('global')
</script>
<p class="discover">
Discover <strong>{count.photos} homes</strong><br>
from <strong>{count.locations} cities</strong>
of <strong>{count.countries} countries</strong>
</p>

View File

@@ -0,0 +1,46 @@
<script lang="ts">
import { createEventDispatcher } from 'svelte';
interface Option {
value: string
name: string
}
export let id: string
export let name: string
export let base: Option
export let options: Option[]
const dispatch = createEventDispatcher()
let current: number = 0
let currentOptionEl: HTMLElement
$: currentOption = options[current]
/**
* When changing select value
*/
const handleChange = ({ target: { value }}: any) => {
current = options.findIndex(option => option.value === value)
// Dispatch event to parent
dispatch('change', options[current].value)
}
</script>
<div class="select">
<slot />
<span bind:this={currentOptionEl}>
{currentOption.name}
</span>
<select {name} {id} on:change={handleChange}>
{#each options as { value, name }}
<option {value}>
{name}
</option>
{/each}
</select>
</div>

View File

@@ -1,4 +1,3 @@
// @ts-nocheck
import { Renderer } from './beam' import { Renderer } from './beam'
import { Camera } from './beam' import { Camera } from './beam'
import { vec2, vec3, mat4 } from './beam' import { vec2, vec3, mat4 } from './beam'

View File

@@ -28,7 +28,7 @@
export async function load ({ page, session, fetch, context }) { export async function load ({ page, session, fetch, context }) {
const res = await fetchAPI(` const res = await fetchAPI(`
query { query {
location { location (filter: { status: { _eq: "published" }}) {
name name
slug slug
coordinates coordinates
@@ -48,7 +48,7 @@
} }
} }
country { country (filter: { status: { _eq: "published" }}) {
name name
slug slug
flag { flag {

View File

@@ -5,6 +5,7 @@
import Metas from '$components/Metas.svelte' import Metas from '$components/Metas.svelte'
import Button from '$components/atoms/Button.svelte' import Button from '$components/atoms/Button.svelte'
import BoxCTA from '$components/atoms/BoxCTA.svelte' import BoxCTA from '$components/atoms/BoxCTA.svelte'
import DiscoverText from '$components/atoms/DiscoverText.svelte'
import PhotoCard from '$components/molecules/PhotoCard.svelte' import PhotoCard from '$components/molecules/PhotoCard.svelte'
import InteractiveGlobe from '$components/organisms/InteractiveGlobe.svelte' import InteractiveGlobe from '$components/organisms/InteractiveGlobe.svelte'
import Locations from '$components/organisms/Locations.svelte' import Locations from '$components/organisms/Locations.svelte'
@@ -13,7 +14,7 @@
export let photos: any export let photos: any
const { settings, location, count }: any = getContext('global') const { settings, location }: any = getContext('global')
const { path } = $page const { path } = $page
</script> </script>
@@ -43,11 +44,7 @@
</section> </section>
<div class="homepage__ctas" id="ctas"> <div class="homepage__ctas" id="ctas">
<p class="discover"> <DiscoverText />
Discover <strong>{count.photos} homes</strong><br>
from <strong>{count.locations} cities</strong>
of <strong>{count.countries} countries</strong>
</p>
<div class="cards"> <div class="cards">
<BoxCTA <BoxCTA

View File

@@ -1,6 +1,5 @@
<script lang="ts"> <script lang="ts">
import { getContext } from 'svelte' import { getContext } from 'svelte'
import { page } from '$app/stores'
// Components // Components
import Metas from '$components/Metas.svelte' import Metas from '$components/Metas.svelte'
import Button from '$components/atoms/Button.svelte' import Button from '$components/atoms/Button.svelte'
@@ -11,8 +10,25 @@
export let photos: any export let photos: any
const { settings, location, count }: any = getContext('global') const { country: countries }: any = getContext('global')
const { path } = $page
let filtered: boolean = false
let buttonReset: HTMLElement
let buttonShuffle: HTMLElement
/**
* Select change events
*/
// Location select
const handleLocationChange = ({ detail: value }) => {
console.log(value)
}
// Sort select
const handleSortChange = ({ detail: value }) => {
console.log(value)
}
</script> </script>
<Metas <Metas
@@ -24,11 +40,8 @@
<main class="photos"> <main class="photos">
<section class="photos__intro"> <section class="photos__intro">
<h1 class="title-huge">Houses</h1> <h1 class="title-huge">Houses</h1>
<p class="discover">
Discover <strong>{count.photos} homes</strong><br> <DiscoverText />
from <strong>{count.locations} cities</strong>
of <strong>{count.countries} countries</strong>
</p>
<div class="filter"> <div class="filter">
<span class="text-label filter__label">Filter photos</span> <span class="text-label filter__label">Filter photos</span>
@@ -36,29 +49,44 @@
<div class="filter__bar"> <div class="filter__bar">
<ul> <ul>
<li> <li>
<div class="select"> <Select
name="location" id="filter_location"
base={{ value: 'all', name: 'Worldwide' }}
options={[
{ value: 'all', name: 'Worldwide' },
...countries.map(({ slug, name }) => ({
value: slug,
name
}))
]}
on:change={handleLocationChange}
>
<img src="/images/icons/earth.svg" alt="Earth"> <img src="/images/icons/earth.svg" alt="Earth">
<span>Worldwide</span> </Select>
<select name="location" id="filter_location">
<option value="worldwide">Worldwide</option>
</select>
</div>
</li> </li>
<li> <li>
<div class="select"> <Select
name="sort" id="filter_sort"
base={{ value: 'all', name: 'Worldwide' }}
options={[
{ value: 'latest', name: 'Latest photos' },
{ value: 'oldest', name: 'Oldest photos' },
]}
on:change={handleSortChange}
>
<img src="/images/icons/sort.svg" alt="Sort"> <img src="/images/icons/sort.svg" alt="Sort">
<span>Worldwide</span> </Select>
<select name="location" id="filter_location">
<option value="worldwide">Worldwide</option>
</select>
</div>
</li> </li>
</ul> </ul>
</div> </div>
<div class="filter__actions"> <div class="filter__actions">
<a href="#">Reset</a> {#if filtered}
<button class="shuffle"> <button class="reset button-link" bind:this={buttonReset}>
Reset
</button>
{/if}
<button class="shuffle" bind:this={buttonShuffle}>
<img src="/images/icons/shuffle.svg" alt=""> <img src="/images/icons/shuffle.svg" alt="">
</button> </button>
</div> </div>

View File

@@ -44,7 +44,7 @@
@include bp (sm) { @include bp (sm) {
position: absolute; position: absolute;
left: 64px; left: 64px;
top: 50%; top: 52%;
transform: translateY(-50%); transform: translateY(-50%);
margin-bottom: 0; margin-bottom: 0;
} }
@@ -54,8 +54,9 @@
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
height: 72px;
margin: 20px 0; margin: 20px 0;
padding: 20px 22px; padding: 0 22px;
background: $color-primary-darker; background: $color-primary-darker;
border-radius: 50vh; border-radius: 50vh;
@@ -76,7 +77,7 @@
color: #fff; color: #fff;
@include bp (sm) { @include bp (sm) {
margin: 0 16px; margin: 0 2px;
} }
} }
img { img {
@@ -90,7 +91,12 @@
.select { .select {
position: relative; position: relative;
display: flex;
align-items: center;
padding: 8px 16px;
font-weight: 900; font-weight: 900;
border-radius: 100vh;
transition: background-color 0.2s;
select { select {
opacity: 0; opacity: 0;
@@ -101,6 +107,10 @@
height: 100%; height: 100%;
cursor: pointer; cursor: pointer;
} }
&:hover {
background-color: $color-primary-tertiary20;
}
} }
} }
@@ -112,8 +122,8 @@
@include bp (sm) { @include bp (sm) {
position: absolute; position: absolute;
right: 64px;
top: 50%; top: 50%;
right: 56px;
transform: translateY(-50%); transform: translateY(-50%);
} }
@@ -129,6 +139,17 @@
display: block; display: block;
} }
} }
// Reset link
.reset {
transition: color 0.3s;
&:hover {
color: $color-tertiary;
}
}
// Shuffle button
.shuffle { .shuffle {
display: flex; display: flex;
align-items: center; align-items: center;

View File

@@ -29,5 +29,6 @@
"$modules/*": ["src/modules/*"] "$modules/*": ["src/modules/*"]
} }
}, },
"include": ["src/**/*.d.ts", "src/**/*.js", "src/**/*.ts", "src/**/*.svelte"] "include": ["src/**/*.d.ts", "src/**/*.js", "src/**/*.ts", "src/**/*.svelte"],
"exclude": ["src/modules/globe/**/*.js"]
} }