Refactor Collapsible and add comments

This commit is contained in:
Matthias Metelka 2022-09-09 18:29:35 +02:00
parent 654b1db54e
commit fb26010dd7

View file

@ -3,40 +3,39 @@ Copyright: Ankitects Pty Ltd and contributors
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
--> -->
<script lang="ts"> <script lang="ts">
import { tick } from "svelte";
import { cubicIn, cubicOut } from "svelte/easing"; import { cubicIn, cubicOut } from "svelte/easing";
import { tweened } from "svelte/motion"; import { tweened } from "svelte/motion";
export let duration = 200;
export let animated = true;
function dynamicDuration(height: number, factor: number): number {
return 100 + Math.pow(height, 1 / 4) * factor;
}
export let collapse = false; export let collapse = false;
export let animated = true;
export let duration = 200;
let collapsed = false; let collapsed = false;
let expandHeight: number; let contentHeight = 0;
function dynamicDuration(height: number): number {
return 100 + Math.pow(height, 1 / 4) * 25;
}
$: duration = dynamicDuration(contentHeight);
const size = tweened<number>(undefined); const size = tweened<number>(undefined);
async function doCollapse(collapse: boolean): Promise<void> { async function transition(collapse: boolean): Promise<void> {
if (collapse) { if (collapse) {
expandHeight = collapsibleElement.clientHeight; contentHeight = collapsibleElement.clientHeight;
size.set(0, { size.set(0, {
duration: duration || dynamicDuration(expandHeight, 25), duration: duration,
easing: cubicOut, easing: cubicOut,
}); });
} else { } else {
/* Tell content to show and await response */
collapsed = false; collapsed = false;
await tick();
/* Measure height to tween to */ /* Measure content height to tween to */
await new Promise(requestAnimationFrame); contentHeight = collapsibleElement.clientHeight;
await new Promise(requestAnimationFrame);
expandHeight = collapsibleElement.clientHeight;
transitioning = true;
size.set(1, { size.set(1, {
duration: duration || dynamicDuration(expandHeight, 25), duration: duration,
easing: cubicIn, easing: cubicIn,
}); });
} }
@ -44,7 +43,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
$: if (collapsibleElement) { $: if (collapsibleElement) {
if (animated) { if (animated) {
doCollapse(collapse); transition(collapse);
} else { } else {
collapsed = collapse; collapsed = collapse;
} }
@ -54,27 +53,26 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
$: collapsed = $size === 0; $: collapsed = $size === 0;
$: expanded = $size === 1; $: expanded = $size === 1;
$: height = $size * contentHeight;
$: transitioning = $size > 0 && !(collapsed || expanded); $: transitioning = $size > 0 && !(collapsed || expanded);
$: height = $size * expandHeight;
$: measuring = !(collapsed || transitioning || expanded); $: measuring = !(collapsed || transitioning || expanded);
</script> </script>
<div <div
bind:this={collapsibleElement} bind:this={collapsibleElement}
class="collapsible" class="collapsible"
class:measuring
class:animated class:animated
class:transitioning
class:expanded class:expanded
class:measuring
class:transitioning
style:--height="{height}px" style:--height="{height}px"
> >
<slot {collapsed} /> <slot {collapsed} />
</div> </div>
{#if measuring} {#if measuring}
<!-- Placeholder while element is absolutely positioned during measurement --> <!-- Maintain document flow while collapsible height is measured -->
<div class="dummy" /> <div class="collapsible-placeholder" />
{/if} {/if}
<style lang="scss"> <style lang="scss">