123 lines
6.0 KiB
Svelte
123 lines
6.0 KiB
Svelte
<script lang="ts">
|
|
import { X } from "lucide-svelte";
|
|
import { manager } from "./page.svelte";
|
|
import { slide } from "svelte/transition";
|
|
</script>
|
|
|
|
<details class="group">
|
|
<summary class="flex items-center justify-between p-3 cursor-pointer hover:bg-neutral-800">
|
|
<span class="font-medium">Frontmatter</span>
|
|
<svg class="w-4 h-4 transition-transform group-open:rotate-180" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"></path>
|
|
</svg>
|
|
</summary>
|
|
<div class="p-3 border-t bg-neutral-900">
|
|
{#each Object.entries(manager.selectedPage?.frontmatter || {}) as [key, value]}
|
|
<div class="flex flex-col gap-2 mb-3 p-2 border rounded bg-neutral-800">
|
|
<div class="flex items-center gap-2">
|
|
<input
|
|
type="text"
|
|
value={key}
|
|
onchange={(e) => {
|
|
const newKey = (e.target as HTMLInputElement).value;
|
|
if (newKey !== key) {
|
|
manager.selectedPage!.frontmatter[newKey] = manager.selectedPage!.frontmatter[key];
|
|
delete manager.selectedPage?.frontmatter[key];
|
|
manager.selectedPage!.dirty = true;
|
|
}
|
|
}}
|
|
class="px-2 py-1 border rounded text-sm flex-shrink-0 w-32 bg-neutral-900"
|
|
placeholder="Key"
|
|
/>
|
|
<span>:</span>
|
|
{#if Array.isArray(value)}
|
|
<span class="text-xs text-muted-foreground">Array ({value.length} items)</span>
|
|
{:else if value instanceof Date || key === "created"}
|
|
<input
|
|
type="date"
|
|
value={value instanceof Date ? value.toISOString().split("T")[0] : typeof value === "string" ? value : ""}
|
|
onchange={(e) => {
|
|
const dateValue = (e.target as HTMLInputElement).value;
|
|
manager.selectedPage!.frontmatter[key] = dateValue ? new Date(dateValue) : "";
|
|
manager.selectedPage!.dirty = true;
|
|
}}
|
|
class="px-2 py-1 border rounded text-sm flex-1 bg-neutral-900"
|
|
/>
|
|
{:else}
|
|
<input
|
|
type="text"
|
|
bind:value={manager.selectedPage!.frontmatter[key]}
|
|
onchange={() => (manager.selectedPage!.dirty = true)}
|
|
class="px-2 py-1 border rounded text-sm flex-1 bg-neutral-900"
|
|
placeholder="Value"
|
|
/>
|
|
{/if}
|
|
<button
|
|
onclick={() => {
|
|
delete manager.selectedPage!.frontmatter[key];
|
|
manager.selectedPage!.dirty = true;
|
|
}}
|
|
class="text-red-500 hover:text-red-700 p-1"
|
|
>
|
|
<X class="w-4 h-4" />
|
|
</button>
|
|
</div>
|
|
{#if Array.isArray(value)}
|
|
<div class="ml-4 space-y-1">
|
|
{#each value as item, index}
|
|
<div class="flex items-center gap-2">
|
|
<span class="text-xs text-muted-foreground w-6">[{index}]</span>
|
|
<input
|
|
type="text"
|
|
bind:value={manager.selectedPage!.frontmatter[key][index]}
|
|
onchange={() => (manager.selectedPage!.dirty = true)}
|
|
class="px-2 py-1 border rounded text-sm flex-1 bg-neutral-900"
|
|
placeholder="Array item"
|
|
/>
|
|
<button
|
|
onclick={() => {
|
|
manager.selectedPage!.frontmatter[key].splice(index, 1);
|
|
manager.selectedPage!.dirty = true;
|
|
}}
|
|
class="text-red-500 hover:text-red-700 p-1"
|
|
>
|
|
<X class="w-3 h-3" />
|
|
</button>
|
|
</div>
|
|
{/each}
|
|
<button
|
|
onclick={() => {
|
|
manager.selectedPage!.frontmatter[key].push("");
|
|
manager.selectedPage!.dirty = true;
|
|
}}
|
|
class="text-xs text-blue-500 hover:text-blue-700 ml-8"
|
|
>
|
|
+ Add item
|
|
</button>
|
|
</div>
|
|
{/if}
|
|
</div>
|
|
{/each}
|
|
<div class="flex gap-2">
|
|
<button
|
|
onclick={() => {
|
|
manager.selectedPage!.frontmatter[`new_key_${Object.keys(manager.selectedPage!.frontmatter).length}`] = "";
|
|
manager.selectedPage!.dirty = true;
|
|
}}
|
|
class="text-sm text-blue-500 hover:text-blue-700"
|
|
>
|
|
+ Add field
|
|
</button>
|
|
<button
|
|
onclick={() => {
|
|
manager.selectedPage!.frontmatter[`new_array_${Object.keys(manager.selectedPage!.frontmatter).length}`] = [];
|
|
manager.selectedPage!.dirty = true;
|
|
}}
|
|
class="text-sm text-green-500 hover:text-green-700"
|
|
>
|
|
+ Add array
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</details>
|