| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104 |
- <script lang="ts">
- import { Input } from "$lib/components/ui/input";
- import { Button } from "$lib/components/ui/button";
- import { Check, X } from "@lucide/svelte";
- import { state as _state } from "$lib/state.svelte";
- import { tick } from "svelte";
- let {
- value = $bindable(),
- onSave,
- // Displayed when not editing
- display,
- }: {
- value: string;
- onSave: (val: string) => void;
- display: any;
- } = $props();
- let editing = $state(false);
- let inputRef: HTMLInputElement;
- let lastValue = "";
- // Start editing
- function startEdit() {
- lastValue = value;
- editing = true;
- // Focus input after next tick
- tick().then(() => {
- console.log("inputref", inputRef);
- inputRef!!.focus();
- inputRef!!.select();
- });
- }
- // Save changes
- function save() {
- if (value.trim()) {
- value = value.trim();
- try {
- onSave(value);
- } catch (e) {
- console.error("error while updating editable", e);
- value = lastValue;
- }
- }
- editing = false;
- }
- // Cancel editing
- function cancel() {
- value = lastValue;
- editing = false;
- }
- function clickOutsideCancel(node: HTMLElement) {
- const onPointerDown = (event: PointerEvent) => {
- if (!node.contains(event.target as Node)) {
- // Only blur if this element currently has focus
- if (
- node === document.activeElement ||
- node.contains(document.activeElement)
- ) {
- if (editing) {
- cancel();
- }
- }
- }
- };
- document.addEventListener("pointerdown", onPointerDown, true);
- return {
- destroy() {
- document.removeEventListener("pointerdown", onPointerDown, true);
- },
- };
- }
- </script>
- <div class="flex items-center">
- {#if editing}
- <input
- use:clickOutsideCancel
- bind:this={inputRef}
- bind:value
- size={Math.max(value.length, 1)}
- onkeydown={(e) => {
- if (e.key === "Enter") save();
- if (e.key === "Escape") cancel();
- }}
- />
- <Button variant="ghost" size="icon" onclick={save}>
- <Check class="w-4 h-4" />
- </Button>
- <Button variant="ghost" size="icon" onclick={cancel}>
- <X class="w-4 h-4" />
- </Button>
- {:else}
- {@render display({ value, startEdit })}
- {/if}
- </div>
|