phonograph/svelte/src/field-header.svelte

91 lines
2.7 KiB
Svelte
Raw Normal View History

2025-08-13 18:52:37 -07:00
<script lang="ts">
import { type FieldInfo } from "./field.svelte";
2025-09-08 15:56:57 -07:00
import FieldDetails from "./field-details.svelte";
2025-08-13 18:52:37 -07:00
type Props = {
field: FieldInfo;
index: number;
};
2025-09-08 15:56:57 -07:00
let { field = $bindable(), index }: Props = $props();
const original_label_value = field.field.table_label;
2025-09-08 15:56:57 -07:00
let type_indicator_element = $state<HTMLButtonElement | undefined>();
let popover_element = $state<HTMLDivElement | undefined>();
let name_value = $state(field.field.name);
let label_value = $state(field.field.table_label ?? "");
// Hacky workaround because as of September 2025 implicit anchor association
// is still pretty broken, at least in Firefox.
let anchor_name = $state(`--anchor-${Math.floor(Math.random() * 1000000)}`);
2025-09-08 15:56:57 -07:00
$effect(() => {
field.field.table_label = label_value === "" ? undefined : label_value;
2025-09-08 15:56:57 -07:00
});
$effect(() => {
popover_element?.addEventListener("toggle", handle_popover_toggle);
return () => {
popover_element?.removeEventListener("toggle", handle_popover_toggle);
};
});
function handle_type_indicator_element_click() {
popover_element?.togglePopover();
}
function handle_popover_toggle(ev: ToggleEvent) {
if (ev.newState === "closed") {
type_indicator_element?.focus();
field.field.table_label = original_label_value;
2025-09-08 15:56:57 -07:00
label_value = original_label_value ?? "";
}
}
2025-08-13 18:52:37 -07:00
</script>
<div
aria-colindex={index}
2025-09-08 15:56:57 -07:00
class="field-header__container"
2025-08-13 18:52:37 -07:00
role="columnheader"
style:width={`${field.field.table_width_px}px`}
2025-08-13 18:52:37 -07:00
>
2025-09-08 15:56:57 -07:00
<div class="field-header__label">
{field.field.table_label ?? field.field.name}
2025-09-08 15:56:57 -07:00
</div>
<div class="field-header__menu-container">
<button
bind:this={type_indicator_element}
class="field-header__type-indicator"
onclick={handle_type_indicator_element_click}
style:anchor-name={anchor_name}
2025-09-08 15:56:57 -07:00
>
{#if field.field.presentation.t === "Dropdown"}
2025-10-24 18:21:40 +00:00
<i class="ti ti-pointer"></i>
{:else if field.field.presentation.t === "Text"}
2025-10-24 18:21:40 +00:00
<i class="ti ti-file-text"></i>
2025-09-08 15:56:57 -07:00
{:else if field.field.presentation.t === "Timestamp"}
2025-10-24 18:21:40 +00:00
<i class="ti ti-calendar"></i>
2025-09-08 15:56:57 -07:00
{:else if field.field.presentation.t === "Uuid"}
2025-10-24 18:21:40 +00:00
<i class="ti ti-id"></i>
2025-09-08 15:56:57 -07:00
{/if}
</button>
<div
bind:this={popover_element}
class="field-header__popover"
popover="auto"
style:position-anchor={anchor_name}
2025-09-08 15:56:57 -07:00
>
<form method="post" action="update-field">
2025-10-14 05:17:41 +00:00
<FieldDetails
bind:name_value
bind:label_value
name_input_disabled
presentation={field.field.presentation}
/>
<input type="hidden" name="field_id" value={field.field.id} />
<button class="button--primary" type="submit">Save</button>
</form>
2025-09-08 15:56:57 -07:00
</div>
</div>
2025-08-13 18:52:37 -07:00
</div>