68fa661b53
* Move up MathjaxOverlay to be initialized only once * Move ImageOverlay to NoteEditor root * Move Symbols Overlay to NoteEditor root * Refactor image overlay to not require second mutation observer * Use elevation + overflow:hidden in Editorfield * Make it possible to show input next to each other again * Set handle background color to code bg * Make Collapsible unmount the component * Simplify how decorated elements are mounted * Set RichTextInput background to frame-bg again * Strip out FocusTrap code * Revert "Make Collapsible unmount the component" This reverts commit 52722065ea199fa57ae750fa34bf47ee1c5aab3c. * Allow clicking on label container to unfocus field * Fix mathjax overlay resetting too its api too soon * Allow scrolling on overlays * Set focus-border border-color in focused field * Fix background color of fields * Add back grid-gap removed it during merge to see if margin-top would behave any differently - which is not the case. * Fix double border issue within Collapsible.svelte * Format * Edit appearance of focused fields a bit * Remove unused properties * Include elevation in button_mixins_lib * Give label-container a background color Co-authored-by: Henrik Giesel <hengiesel@gmail.com>
105 lines
2.6 KiB
Svelte
105 lines
2.6 KiB
Svelte
<!--
|
|
Copyright: Ankitects Pty Ltd and contributors
|
|
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|
-->
|
|
<script lang="ts">
|
|
import { tick } from "svelte";
|
|
import { cubicIn, cubicOut } from "svelte/easing";
|
|
import { tweened } from "svelte/motion";
|
|
|
|
export let collapse = false;
|
|
export let toggleDisplay = false;
|
|
export let animated = !document.body.classList.contains("reduced-motion");
|
|
|
|
let collapsed = false;
|
|
let contentHeight = 0;
|
|
|
|
function dynamicDuration(height: number): number {
|
|
return 100 + Math.pow(height, 1 / 4) * 25;
|
|
}
|
|
$: duration = dynamicDuration(contentHeight);
|
|
|
|
const size = tweened<number>(undefined);
|
|
|
|
async function transition(collapse: boolean): Promise<void> {
|
|
if (collapse) {
|
|
contentHeight = collapsibleElement.clientHeight;
|
|
size.set(0, {
|
|
duration: duration,
|
|
easing: cubicOut,
|
|
});
|
|
} else {
|
|
/* Tell content to show and await response */
|
|
collapsed = false;
|
|
await tick();
|
|
/* Measure content height to tween to */
|
|
contentHeight = collapsibleElement.clientHeight;
|
|
size.set(1, {
|
|
duration: duration,
|
|
easing: cubicIn,
|
|
});
|
|
}
|
|
}
|
|
|
|
$: if (collapsibleElement) {
|
|
if (animated) {
|
|
transition(collapse);
|
|
} else {
|
|
collapsed = collapse;
|
|
}
|
|
}
|
|
|
|
let collapsibleElement: HTMLElement;
|
|
|
|
$: collapsed = $size === 0;
|
|
$: expanded = $size === 1;
|
|
$: height = $size * contentHeight;
|
|
$: transitioning = $size > 0 && !(collapsed || expanded);
|
|
$: measuring = !(collapsed || transitioning || expanded);
|
|
</script>
|
|
|
|
<div
|
|
bind:this={collapsibleElement}
|
|
class="collapsible"
|
|
class:animated
|
|
class:expanded
|
|
class:full-hide={toggleDisplay}
|
|
class:collapsed={!expanded}
|
|
class:measuring
|
|
class:transitioning
|
|
style:--height="{height}px"
|
|
>
|
|
<slot {collapsed} />
|
|
</div>
|
|
|
|
{#if measuring}
|
|
<!-- Maintain document flow while collapsible height is measured -->
|
|
<div class="collapsible-placeholder" />
|
|
{/if}
|
|
|
|
<style lang="scss">
|
|
.collapsible.full-hide {
|
|
&.collapsed {
|
|
display: none;
|
|
}
|
|
&.transitioning {
|
|
display: initial;
|
|
}
|
|
}
|
|
|
|
.collapsible.animated {
|
|
&.measuring {
|
|
display: unset;
|
|
position: absolute;
|
|
opacity: 0;
|
|
}
|
|
&.transitioning {
|
|
overflow: hidden;
|
|
height: var(--height);
|
|
&.expanded {
|
|
overflow: visible;
|
|
}
|
|
}
|
|
}
|
|
</style>
|