{"release_id":"01a1c502-4ad1-0000-ec62-adc54d3c69aa","chunk_id":"01a1c502-4bf6-7582-82fb-e2cfc0f0362f","file":"Cfwk8ahD.mjs","mappings":"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","names":["items","$.state","$.proxy","editing","editDraft","addDraft","busy","$.user_effect","$$props","$.set","m","push","$.get","startEdit","saveEdit","body","res","r","x","remove","add","div","$.first_child","fragment_1","section","$.sibling","header","$.child","button","div_1","p","root_2","$$render","consequent","$.each","node_2","div_2","root_3","textarea","fragment_2","div_3","button_1","button_2","$.template_effect","$$value","button_3","fragment_3","div_4","span","button_4","$.set_text","text","text_1","consequent_1","alternate","div_5","input","$.remove_input_defaults","button_5","$.reset","$0","$$args","fade","e","$.delegated","fly","expoOut"],"sources":["../../../../../../src/lib/components/roleplay/RpMemoryPanel.svelte"],"sourcesContent":["<script lang=\"ts\">\n\t/**\n\t * What the character remembers about this thread. The auto rows are written\n\t * by the refresher every ~16 messages; touching one locks it as the user's\n\t * wording. User-added rows are born locked. Everything here rides into the\n\t * system prompt on the next reply.\n\t */\n\timport { fade, fly } from 'svelte/transition';\n\timport { expoOut } from 'svelte/easing';\n\n\tinterface Memory {\n\t\tid: string;\n\t\tkind: string;\n\t\tbody: string;\n\t\tlocked: boolean;\n\t}\n\n\tinterface Props {\n\t\topen: boolean;\n\t\t/** API base for this thread's memory collection — `/api/rp/chat/<id>` for a\n\t\t *  1:1 thread, `/api/rp/group/<code>` for a room. Same endpoints either\n\t\t *  side, so one panel serves both. */\n\t\tapiBase: string;\n\t\tmemories: Memory[];\n\t\tonClose: () => void;\n\t\tonChange: (memories: Memory[]) => void;\n\t}\n\n\tlet { open, apiBase, memories, onClose, onChange }: Props = $props();\n\n\tlet items = $state<Memory[]>([]);\n\tlet editing = $state<string | null>(null);\n\tlet editDraft = $state('');\n\tlet addDraft = $state('');\n\tlet busy = $state(false);\n\n\t$effect(() => {\n\t\tif (open) {\n\t\t\titems = memories.map((m) => ({ ...m }));\n\t\t\tediting = null;\n\t\t\taddDraft = '';\n\t\t}\n\t});\n\n\tfunction push() {\n\t\tonChange(items.map((m) => ({ ...m })));\n\t}\n\n\tfunction startEdit(m: Memory) {\n\t\tediting = m.id;\n\t\teditDraft = m.body;\n\t}\n\n\tasync function saveEdit(m: Memory) {\n\t\tconst body = editDraft.trim();\n\t\tif (!body || busy) return;\n\t\tbusy = true;\n\t\ttry {\n\t\t\tconst res = await fetch(`${apiBase}/memory/${m.id}`, {\n\t\t\t\tmethod: 'PATCH',\n\t\t\t\theaders: { 'Content-Type': 'application/json' },\n\t\t\t\tbody: JSON.stringify({ body })\n\t\t\t});\n\t\t\tconst r = await res.json();\n\t\t\tif (res.ok && r?.memory) {\n\t\t\t\titems = items.map((x) => (x.id === m.id ? r.memory : x));\n\t\t\t\tediting = null;\n\t\t\t\tpush();\n\t\t\t}\n\t\t} finally {\n\t\t\tbusy = false;\n\t\t}\n\t}\n\n\tasync function remove(m: Memory) {\n\t\tif (busy) return;\n\t\tbusy = true;\n\t\ttry {\n\t\t\tconst res = await fetch(`${apiBase}/memory/${m.id}`, { method: 'DELETE' });\n\t\t\tif (res.ok) {\n\t\t\t\titems = items.filter((x) => x.id !== m.id);\n\t\t\t\tpush();\n\t\t\t}\n\t\t} finally {\n\t\t\tbusy = false;\n\t\t}\n\t}\n\n\tasync function add() {\n\t\tconst body = addDraft.trim();\n\t\tif (!body || busy) return;\n\t\tbusy = true;\n\t\ttry {\n\t\t\tconst res = await fetch(`${apiBase}/memory`, {\n\t\t\t\tmethod: 'POST',\n\t\t\t\theaders: { 'Content-Type': 'application/json' },\n\t\t\t\tbody: JSON.stringify({ body })\n\t\t\t});\n\t\t\tconst r = await res.json();\n\t\t\tif (res.ok && r?.memory) {\n\t\t\t\t// Keyed by id: a reseed from the page's data mid-request can already\n\t\t\t\t// carry the new row, and a repeat key would crash the panel.\n\t\t\t\titems = [...items.filter((x) => x.id !== r.memory.id), r.memory];\n\t\t\t\taddDraft = '';\n\t\t\t\tpush();\n\t\t\t}\n\t\t} finally {\n\t\t\tbusy = false;\n\t\t}\n\t}\n</script>\n\n{#if open}\n\t<div class=\"scrim\" role=\"presentation\" onclick={onClose} transition:fade={{ duration: 150 }}></div>\n\t<section\n\t\tclass=\"sheet\"\n\t\taria-label=\"character memories\"\n\t\ttransition:fly={{ y: 48, duration: 260, easing: expoOut }}\n\t>\n\t\t<header class=\"head\">\n\t\t\t<h2>memories</h2>\n\t\t\t<button type=\"button\" class=\"x\" onclick={onClose} aria-label=\"close\">✕</button>\n\t\t</header>\n\n\t\t<p class=\"hint\">\n\t\t\twhat the character knows so far. it updates itself as you talk — edit or pin anything and\n\t\t\tthat wording sticks.\n\t\t</p>\n\n\t\t<div class=\"list\">\n\t\t\t{#if items.length === 0}\n\t\t\t\t<p class=\"empty\">nothing yet — it starts remembering after a few messages.</p>\n\t\t\t{/if}\n\t\t\t{#each items as m (m.id)}\n\t\t\t\t<div class=\"item\">\n\t\t\t\t\t{#if editing === m.id}\n\t\t\t\t\t\t<textarea bind:value={editDraft} rows=\"2\" maxlength=\"200\"></textarea>\n\t\t\t\t\t\t<div class=\"row-btns\">\n\t\t\t\t\t\t\t<button type=\"button\" class=\"btn btn--fill\" disabled={busy} onclick={() => saveEdit(m)}>\n\t\t\t\t\t\t\t\tsave\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t<button type=\"button\" class=\"btn\" onclick={() => (editing = null)}>cancel</button>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t{:else}\n\t\t\t\t\t\t<button type=\"button\" class=\"body-line\" onclick={() => startEdit(m)}>{m.body}</button>\n\t\t\t\t\t\t<div class=\"meta\">\n\t\t\t\t\t\t\t<span class=\"badge\">{m.locked ? 'pinned' : 'auto'}</span>\n\t\t\t\t\t\t\t<button type=\"button\" class=\"del\" disabled={busy} onclick={() => remove(m)}>\n\t\t\t\t\t\t\t\tforget\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t{/if}\n\t\t\t\t</div>\n\t\t\t{/each}\n\t\t</div>\n\n\t\t<div class=\"add\">\n\t\t\t<input\n\t\t\t\ttype=\"text\"\n\t\t\t\tbind:value={addDraft}\n\t\t\t\tmaxlength=\"200\"\n\t\t\t\tplaceholder=\"add something they should never forget…\"\n\t\t\t\tonkeydown={(e) => e.key === 'Enter' && add()}\n\t\t\t/>\n\t\t\t<button type=\"button\" class=\"btn btn--fill\" disabled={busy || !addDraft.trim()} onclick={add}>\n\t\t\t\tadd\n\t\t\t</button>\n\t\t</div>\n\t</section>\n{/if}\n\n<style>\n\t.scrim {\n\t\tposition: fixed;\n\t\tinset: 0;\n\t\tbackground: rgb(0 0 0 / 55%);\n\t\tz-index: 60;\n\t}\n\t.sheet {\n\t\tposition: fixed;\n\t\t/* Centered without transform — the fly transition animates the transform\n\t\t   property, so a CSS translateX(-50%) here would be overwritten mid-flight. */\n\t\tleft: 0;\n\t\tright: 0;\n\t\tmargin-inline: auto;\n\t\tbottom: 0;\n\t\twidth: 100%;\n\t\tmax-width: 640px;\n\t\tmax-height: 82dvh;\n\t\toverflow-y: auto;\n\t\tbackground: var(--color-bg);\n\t\tborder: 1px solid var(--color-border);\n\t\tborder-bottom: none;\n\t\tborder-radius: 18px 18px 0 0;\n\t\tz-index: 61;\n\t\tpadding: 0 16px calc(16px + env(safe-area-inset-bottom, 0px));\n\t}\n\t.head {\n\t\tdisplay: flex;\n\t\talign-items: center;\n\t\tjustify-content: space-between;\n\t\tpadding: 14px 0 6px;\n\t}\n\t.head h2 {\n\t\tfont-family: var(--font-display);\n\t\tfont-size: 15px;\n\t\tfont-weight: 700;\n\t\tcolor: var(--color-text);\n\t}\n\t.x {\n\t\tbackground: none;\n\t\tborder: none;\n\t\tcolor: var(--color-muted);\n\t\tfont-size: 15px;\n\t\tcursor: pointer;\n\t\tpadding: 4px 6px;\n\t}\n\t.hint {\n\t\tfont-size: 12px;\n\t\tline-height: 1.45;\n\t\tcolor: var(--color-muted);\n\t\tmargin-bottom: 12px;\n\t}\n\t.list {\n\t\tdisplay: flex;\n\t\tflex-direction: column;\n\t\tgap: 8px;\n\t\tmargin-bottom: 14px;\n\t}\n\t.empty {\n\t\tfont-size: 13px;\n\t\tcolor: var(--color-muted);\n\t\tpadding: 10px 0;\n\t}\n\t.item {\n\t\tdisplay: flex;\n\t\tflex-direction: column;\n\t\tgap: 6px;\n\t\tborder: 1px solid var(--color-border);\n\t\tbackground: var(--color-surface);\n\t\tborder-radius: 12px;\n\t\tpadding: 10px 12px;\n\t}\n\t.body-line {\n\t\ttext-align: left;\n\t\tbackground: none;\n\t\tborder: none;\n\t\tcolor: var(--color-text);\n\t\tfont-size: 13px;\n\t\tline-height: 1.5;\n\t\tcursor: pointer;\n\t\tpadding: 0;\n\t}\n\t.meta {\n\t\tdisplay: flex;\n\t\talign-items: center;\n\t\tjustify-content: space-between;\n\t}\n\t.badge {\n\t\tfont-size: 10px;\n\t\tfont-weight: 700;\n\t\tletter-spacing: 0.06em;\n\t\ttext-transform: uppercase;\n\t\tcolor: var(--color-muted);\n\t}\n\t.del {\n\t\tbackground: none;\n\t\tborder: none;\n\t\tcolor: var(--color-coral);\n\t\tfont-size: 12px;\n\t\tcursor: pointer;\n\t\tpadding: 2px 4px;\n\t}\n\ttextarea,\n\tinput {\n\t\twidth: 100%;\n\t\tresize: none;\n\t\tpadding: 9px 12px;\n\t\tborder-radius: 10px;\n\t\tborder: 1px solid var(--color-border);\n\t\tbackground: var(--color-bg);\n\t\tcolor: var(--color-text);\n\t\tfont-family: inherit;\n\t\tfont-size: 13px;\n\t\tline-height: 1.5;\n\t}\n\ttextarea:focus,\n\tinput:focus {\n\t\toutline: none;\n\t\tborder-color: var(--color-accent);\n\t}\n\t.row-btns {\n\t\tdisplay: flex;\n\t\tgap: 8px;\n\t}\n\t.btn {\n\t\tpadding: 8px 13px;\n\t\tborder-radius: 10px;\n\t\tborder: 1px solid var(--color-border);\n\t\tbackground: var(--color-surface);\n\t\tcolor: var(--color-text);\n\t\tfont-size: 12px;\n\t\tfont-weight: 600;\n\t\tcursor: pointer;\n\t}\n\t.btn--fill {\n\t\tbackground: var(--color-accent);\n\t\tborder-color: transparent;\n\t\tcolor: #fff;\n\t}\n\t.btn:disabled {\n\t\topacity: 0.5;\n\t\tcursor: default;\n\t}\n\t.add {\n\t\tdisplay: flex;\n\t\tgap: 8px;\n\t}\n</style>\n"],"version":3}