You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
109 lines
2.0 KiB
109 lines
2.0 KiB
2 years ago
|
<script>
|
||
|
import Icon from '$/client/components/Icon.svelte';
|
||
|
import { createEventDispatcher } from "svelte";
|
||
|
|
||
|
export let panels = [];
|
||
|
export let selected = {};
|
||
|
const dispatch = createEventDispatcher();
|
||
|
|
||
|
/* So dumb, but gotta do it. */
|
||
|
const current_index = () => {
|
||
|
for(let i = 0; i < panels.length; i++) {
|
||
|
if(panels[i].active) return i;
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
const activate = (index) => {
|
||
|
panels = panels.map((x, i) => {
|
||
|
x.active = i == index;
|
||
|
if(x.active) selected = x;
|
||
|
return x;
|
||
|
});
|
||
|
|
||
|
dispatch("select", {index, selected});
|
||
|
}
|
||
|
|
||
|
const next = () => {
|
||
|
let i = current_index();
|
||
|
activate((i + 1) % panels.length);
|
||
|
}
|
||
|
|
||
|
const prev = () => {
|
||
|
let i = current_index();
|
||
|
activate((i - 1) < 0 ? panels.length -1 : i - 1);
|
||
|
}
|
||
|
</script>
|
||
|
|
||
|
<style>
|
||
|
carousel {
|
||
|
position: relative;
|
||
|
display: flex;
|
||
|
flex-direction: column;
|
||
|
flex: flex-grow;
|
||
|
}
|
||
|
|
||
|
carousel panel {
|
||
|
display: none;
|
||
|
}
|
||
|
|
||
|
carousel panel.active {
|
||
|
display: flex;
|
||
|
position: relative;
|
||
|
flex-direction: column;
|
||
|
}
|
||
|
|
||
|
carousel panel caption {
|
||
|
position: absolute;
|
||
|
bottom: 0;
|
||
|
left: 0;
|
||
|
width: 100%;
|
||
|
text-align: center;
|
||
|
font-size: 2em;
|
||
|
background: var(--color-bg-secondary);
|
||
|
opacity: 0%;
|
||
|
}
|
||
|
|
||
|
carousel caption:hover {
|
||
|
opacity: 90%;
|
||
|
}
|
||
|
|
||
|
carousel next,
|
||
|
carousel prev {
|
||
|
position: absolute;
|
||
|
top: 0;
|
||
|
bottom: 0;
|
||
|
opacity: 60%;
|
||
|
display: flex;
|
||
|
flex-direction: column;
|
||
|
align-content: center;
|
||
|
justify-content: center;
|
||
|
}
|
||
|
|
||
|
carousel next {
|
||
|
right: 0;
|
||
|
}
|
||
|
|
||
|
carousel prev {
|
||
|
left: 0;
|
||
|
}
|
||
|
|
||
|
carousel next:hover,prev:hover {
|
||
|
opacity: 60%;
|
||
|
background-color: var(--color-bg);
|
||
|
}
|
||
|
</style>
|
||
|
|
||
|
<carousel>
|
||
|
{#each panels as panel}
|
||
|
<panel class:active={ panel.active }>
|
||
|
<svelte:component this={panel.component} {...panel.props} />
|
||
|
<caption>{ panel.caption }</caption>
|
||
|
</panel>
|
||
|
{/each}
|
||
|
|
||
|
<prev on:click={ prev }><Icon name="arrow-left" size="48" /></prev>
|
||
|
<next on:click={ next }><Icon name="arrow-right" size="48" /></next>
|
||
|
</carousel>
|