Implement the 029-on-demand-bestiary feature that replaces the bundled XMM bestiary JSON with a compact search index (~350KB) and on-demand source loading, where users explicitly provide a URL or upload a JSON file to fetch full stat block data per source, which is then normalized and cached in IndexedDB (with in-memory fallback) so creature stat blocks load instantly on subsequent visits while keeping the app bundle small and never auto-fetching copyrighted content
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,4 +1,3 @@
|
||||
import type { Creature } from "@initiative/domain";
|
||||
import { Search, X } from "lucide-react";
|
||||
import {
|
||||
type KeyboardEvent,
|
||||
@@ -7,12 +6,13 @@ import {
|
||||
useRef,
|
||||
useState,
|
||||
} from "react";
|
||||
import type { SearchResult } from "../hooks/use-bestiary.js";
|
||||
import { Input } from "./ui/input.js";
|
||||
|
||||
interface BestiarySearchProps {
|
||||
onSelectCreature: (creature: Creature) => void;
|
||||
onSelectCreature: (result: SearchResult) => void;
|
||||
onClose: () => void;
|
||||
searchFn: (query: string) => Creature[];
|
||||
searchFn: (query: string) => SearchResult[];
|
||||
}
|
||||
|
||||
export function BestiarySearch({
|
||||
@@ -101,8 +101,8 @@ export function BestiarySearch({
|
||||
</div>
|
||||
) : (
|
||||
<ul className="max-h-60 overflow-y-auto py-1">
|
||||
{results.map((creature, i) => (
|
||||
<li key={creature.id}>
|
||||
{results.map((result, i) => (
|
||||
<li key={`${result.source}:${result.name}`}>
|
||||
<button
|
||||
type="button"
|
||||
className={`flex w-full items-center justify-between px-3 py-1.5 text-left text-sm ${
|
||||
@@ -110,12 +110,12 @@ export function BestiarySearch({
|
||||
? "bg-accent/20 text-foreground"
|
||||
: "text-foreground hover:bg-hover-neutral-bg"
|
||||
}`}
|
||||
onClick={() => onSelectCreature(creature)}
|
||||
onClick={() => onSelectCreature(result)}
|
||||
onMouseEnter={() => setHighlightIndex(i)}
|
||||
>
|
||||
<span>{creature.name}</span>
|
||||
<span>{result.name}</span>
|
||||
<span className="text-xs text-muted-foreground">
|
||||
{creature.sourceDisplayName}
|
||||
{result.sourceDisplayName}
|
||||
</span>
|
||||
</button>
|
||||
</li>
|
||||
|
||||
Reference in New Issue
Block a user