diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ad74656..ce8bf90 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -44,6 +44,9 @@ importers: react-icons: specifier: ^5.5.0 version: 5.5.0(react@19.2.4) + wanakana: + specifier: ^5.3.1 + version: 5.3.1 zustand: specifier: ^5.0.11 version: 5.0.11(@types/react@19.2.14)(react@19.2.4) @@ -1195,6 +1198,10 @@ packages: yaml: optional: true + wanakana@5.3.1: + resolution: {integrity: sha512-OSDqupzTlzl2LGyqTdhcXcl6ezMiFhcUwLBP8YKaBIbMYW1wAwDvupw2T9G9oVaKT9RmaSpyTXjxddFPUcFFIw==} + engines: {node: '>=12'} + yallist@3.1.1: resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} @@ -2618,6 +2625,8 @@ snapshots: '@types/node': 24.10.13 fsevents: 2.3.3 + wanakana@5.3.1: {} + yallist@3.1.1: {} yaml@1.10.2: {} diff --git a/src-react/package.json b/src-react/package.json index b7fa93d..1a4e20e 100644 --- a/src-react/package.json +++ b/src-react/package.json @@ -19,6 +19,7 @@ "react": "^19.1.0", "react-dom": "^19.1.0", "react-icons": "^5.5.0", + "wanakana": "^5.3.1", "zustand": "^5.0.11" }, "devDependencies": { diff --git a/src-react/src/pages/SearchPage.tsx b/src-react/src/pages/SearchPage.tsx index d733d9b..d1cdb21 100644 --- a/src-react/src/pages/SearchPage.tsx +++ b/src-react/src/pages/SearchPage.tsx @@ -1,6 +1,16 @@ import { CompositionEventHandler, useEffect, useRef, useState } from "react"; +import { toHiragana } from "wanakana"; -import { Box, Button, Card, Group, Input, Stack } from "@chakra-ui/react"; +import { + Box, + Card, + CloseButton, + Group, + Input, + InputGroup, + Stack, + Switch, +} from "@chakra-ui/react"; import { invoke } from "@tauri-apps/api/core"; import Glossary from "../components/Glossary"; @@ -22,7 +32,10 @@ function SearchPage() { const [entries, setEntries] = useState([]); const [searchTimeout, setSearchTimeout] = useState(0); const [furigana, setFurigana] = useState(""); + const [isAutoKana, set_isAutoKana] = useState(true); + const nSearch = useRef(0); + const searchboxRef = useRef(null); const lang = "ja-JP"; @@ -89,6 +102,14 @@ function SearchPage() { ); } + function onSearchboxChange(q: string) { + if (isAutoKana) { + q = toHiragana(q, { useObsoleteKana: true, IMEMode: true }); + } + + setQ(q); + } + const FURIGANA_REGEX = /^[\p{scx=Hiragana}\p{scx=Katakana}]+$/u; const KANJI_REGEX = /([\p{sc=Han}\p{N}々〆ヵヶ]+)/u; @@ -134,6 +155,17 @@ function SearchPage() { : k; } + const clearButton = q.trim() ? ( + { + setQ(""); + searchboxRef.current ? searchboxRef.current.focus() : null; + }} + /> + ) : null; + return (
- setQ(e.currentTarget.value)} - onCompositionUpdate={updateFurigana} - onCompositionEnd={addFurigana} - autoComplete="off" - spellCheck={false} - placeholder="Search..." - /> - + + onSearchboxChange(e.currentTarget.value)} + onCompositionUpdate={updateFurigana} + onCompositionEnd={addFurigana} + autoComplete="off" + spellCheck={false} + placeholder="Search..." + /> + + {/* */} +
+ set_isAutoKana(d.checked)} + > + + + Auto-convert Kana + +
{entries.map(