chore(export-viewer): rebuild the embedded bundle, and fix the lint ignores
The offline keepsake viewer had the same two filter defects as the app: typed suggestions were capped so a matching tag could be unselectable, and the dropdown used `onmousedown` with a backdrop that swallowed the selection. Rebuilt into `backend/static/export-viewer/index.html`, which `include_dir!` embeds in the binary. The eslint ignores were unanchored, so once the export-viewer's dependencies were installed its nested `.svelte-kit` output was linted as source. Anchored with `**/`. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -57,22 +57,25 @@
|
||||
...allTags.slice(0, 3).map(([t]) => ({ type: 'tag' as const, value: t }))
|
||||
];
|
||||
}
|
||||
// Once the user has TYPED, every match is offered — no `.slice()`. Capping matters
|
||||
// more here than in the live app, for two reasons: this viewer holds the WHOLE event
|
||||
// (the export queries are uncapped), so the tag set is far larger than any one feed
|
||||
// page; and the keepsake is a frozen artifact — a guest opening it years later has no
|
||||
// server to re-query and no "scroll to load more" escape hatch. A silently dropped
|
||||
// match would simply be unreachable forever. The dropdown scrolls instead.
|
||||
if (q.startsWith('#')) {
|
||||
const prefix = q.slice(1).toLowerCase();
|
||||
return allTags
|
||||
.filter(([t]) => t.startsWith(prefix))
|
||||
.slice(0, 8)
|
||||
.map(([t]) => ({ type: 'tag' as const, value: t }));
|
||||
}
|
||||
const lower = q.toLowerCase();
|
||||
return [
|
||||
...allUploaders
|
||||
.filter((u) => u.toLowerCase().includes(lower))
|
||||
.slice(0, 4)
|
||||
.map((u) => ({ type: 'user' as const, value: u })),
|
||||
...allTags
|
||||
.filter(([t]) => t.includes(lower))
|
||||
.slice(0, 4)
|
||||
.map(([t]) => ({ type: 'tag' as const, value: t }))
|
||||
];
|
||||
});
|
||||
@@ -381,13 +384,24 @@
|
||||
|
||||
<!-- Autocomplete dropdown -->
|
||||
{#if showAutocomplete && suggestions.length > 0}
|
||||
<!-- `preventDefault` on mousedown suppresses the input's blur, which would
|
||||
otherwise close this dropdown (see the input's `onblur`) before a click
|
||||
could land. That is what lets the commit live on `onclick` — the LAST
|
||||
event — instead of `onmousedown`. Committing on press meant sliding off
|
||||
a suggestion you didn't mean to hit still applied the filter, and
|
||||
`selectSuggestion` sets `showAutocomplete = false`, so the button
|
||||
destroyed itself on the first event of the click sequence. Ported from
|
||||
the live feed page, which fixed this; the viewer never got it. -->
|
||||
<div
|
||||
class="absolute left-0 right-0 top-full z-50 mt-1 overflow-hidden rounded-xl border border-gray-200 bg-white shadow-lg"
|
||||
class="absolute left-0 right-0 top-full z-50 mt-1 max-h-72 overflow-y-auto overscroll-contain rounded-xl border border-gray-200 bg-white shadow-lg"
|
||||
onmousedown={(e) => e.preventDefault()}
|
||||
role="listbox"
|
||||
tabindex="-1"
|
||||
>
|
||||
{#each suggestions as item (item.type + ':' + item.value)}
|
||||
<button
|
||||
class="flex w-full items-center gap-3 px-4 py-2.5 text-left text-sm hover:bg-gray-50"
|
||||
onmousedown={() => selectSuggestion(item)}
|
||||
onclick={() => selectSuggestion(item)}
|
||||
>
|
||||
{#if item.type === 'user'}
|
||||
<svg
|
||||
|
||||
Reference in New Issue
Block a user