anki/ts/components/VerticalResizer.svelte

102 lines
2.7 KiB
Svelte
Raw Normal View History

Make tags editor resizable using Henrik's components (#2046) * Make tags editor resizable using Henrik's components All credit for the components goes to Henrik. I just tweaked the design a bit and implemented them in NoteEditor. Co-Authored-By: Henrik Giesel <hengiesel@gmail.com> * Remove PaneContent padding Co-Authored-By: Henrik Giesel <hengiesel@gmail.com> * Add responsive box-shadows on scroll/resize only shown when content overflows in the respective direction. * Remove comment * Fix overflow calculations and shadow mix-up This happened when I switched from using scrolledToX to overflowX booleans. * Simplify overflow calculations * Make drag handles 0 height/width The remaining height requirement comes from a margin set on NoteEditor. * Run eslint on components * Split editor into three panes: Toolbar, Fields, Tags * Remove upper split for now to unblock 2.1.55 beta * Move panes.scss to sass folder * Use single type for resizable panes * Implement collapsed state toggled with click on resizer * Add button to uncollapse tags pane and focus input * Add indicator for # of tags * Use dbclick to prevent interference with resize state * Add utility functions for expand/collapse * Meddle around with types and formatting * Fix collapsed state being forgotten on second browser open (dae) * Fix typecheck (dae) Our tooling generates .d.ts files from the Svelte files, but it doesn't expect variables to be exported. By changing them into functions, they get included in .bazel/bin/ts/components/Pane.svelte.d.ts * Remove an unnecessary bridgeCommand (dae) * Fix the bottom of tags getting cut off (dae) Not sure why offsetHeight is inaccurate in this case. * Add missing header (dae) Co-authored-by: Henrik Giesel <hengiesel@gmail.com>
2022-09-28 06:02:32 +02:00
<!--
Copyright: Ankitects Pty Ltd and contributors
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
-->
<script lang="ts">
import { on } from "../lib/events";
import { Callback, singleCallback } from "../lib/typing";
import IconConstrain from "./IconConstrain.svelte";
import { verticalHandle } from "./icons";
import type { ResizablePane } from "./types";
export let components: ResizablePane[];
export let index = 0;
export let clientWidth: number;
let destroy: Callback;
let before: ResizablePane;
let after: ResizablePane;
function onMove(this: Window, { movementX }: PointerEvent): void {
if (movementX < 0) {
const resized = before.resizable.getWidthResizer().resize(movementX);
after.resizable.getWidthResizer().resize(-resized);
} else if (movementX > 0) {
const resized = after.resizable.getWidthResizer().resize(-movementX);
before.resizable.getWidthResizer().resize(-resized);
}
}
let minWidth: number;
function releasePointer(this: Window): void {
destroy();
document.exitPointerLock();
const resizerAmount = components.length - 1;
const componentsWidth = clientWidth - minWidth * resizerAmount;
for (const component of components) {
component.resizable
.getWidthResizer()
.stop(componentsWidth, components.length);
}
}
function lockPointer(this: HTMLHRElement) {
this.requestPointerLock();
before = components[index];
after = components[index + 1];
for (const component of components) {
component.resizable.getWidthResizer().start();
}
destroy = singleCallback(
on(window, "pointermove", onMove),
on(window, "pointerup", releasePointer),
);
}
</script>
<div
bind:clientWidth={minWidth}
class="vertical-resizer"
on:pointerdown|preventDefault={lockPointer}
>
<div class="drag-handle">
<IconConstrain iconSize={80}>{@html verticalHandle}</IconConstrain>
</div>
</div>
<style lang="scss">
.vertical-resizer {
height: 100%;
cursor: col-resize;
position: relative;
z-index: 20;
.drag-handle {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
opacity: 0.4;
}
&::before {
content: "";
position: absolute;
width: 10px;
left: -5px;
top: 0;
height: 100%;
}
&:hover .drag-handle {
opacity: 0.8;
}
}
</style>