mirror of
https://github.com/patarapolw/cjdic2.git
synced 2026-11-09 17:39:35 +00:00
(feat) auto-Kana with wanakana 🐊
This commit is contained in:
1 parent
641f23538b
commit
e3ccd517a8
3 files changed
+58
-3
No files matched your search
Generated
+9
@@ -44,6 +44,9 @@ importers:
|
|||||||
react-icons:
|
react-icons:
|
||||||
specifier: ^5.5.0
|
specifier: ^5.5.0
|
||||||
version: 5.5.0(react@19.2.4)
|
version: 5.5.0(react@19.2.4)
|
||||||
|
wanakana:
|
||||||
|
specifier: ^5.3.1
|
||||||
|
version: 5.3.1
|
||||||
zustand:
|
zustand:
|
||||||
specifier: ^5.0.11
|
specifier: ^5.0.11
|
||||||
version: 5.0.11(@types/react@19.2.14)(react@19.2.4)
|
version: 5.0.11(@types/react@19.2.14)(react@19.2.4)
|
||||||
@@ -1195,6 +1198,10 @@ packages:
|
|||||||
yaml:
|
yaml:
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
wanakana@5.3.1:
|
||||||
|
resolution: {integrity: sha512-OSDqupzTlzl2LGyqTdhcXcl6ezMiFhcUwLBP8YKaBIbMYW1wAwDvupw2T9G9oVaKT9RmaSpyTXjxddFPUcFFIw==}
|
||||||
|
engines: {node: '>=12'}
|
||||||
|
|
||||||
yallist@3.1.1:
|
yallist@3.1.1:
|
||||||
resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==}
|
resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==}
|
||||||
|
|
||||||
@@ -2618,6 +2625,8 @@ snapshots:
|
|||||||
'@types/node': 24.10.13
|
'@types/node': 24.10.13
|
||||||
fsevents: 2.3.3
|
fsevents: 2.3.3
|
||||||
|
|
||||||
|
wanakana@5.3.1: {}
|
||||||
|
|
||||||
yallist@3.1.1: {}
|
yallist@3.1.1: {}
|
||||||
|
|
||||||
yaml@1.10.2: {}
|
yaml@1.10.2: {}
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
"react": "^19.1.0",
|
"react": "^19.1.0",
|
||||||
"react-dom": "^19.1.0",
|
"react-dom": "^19.1.0",
|
||||||
"react-icons": "^5.5.0",
|
"react-icons": "^5.5.0",
|
||||||
|
"wanakana": "^5.3.1",
|
||||||
"zustand": "^5.0.11"
|
"zustand": "^5.0.11"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|||||||
@@ -1,6 +1,16 @@
|
|||||||
import { CompositionEventHandler, useEffect, useRef, useState } from "react";
|
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 { invoke } from "@tauri-apps/api/core";
|
||||||
|
|
||||||
import Glossary from "../components/Glossary";
|
import Glossary from "../components/Glossary";
|
||||||
@@ -22,7 +32,10 @@ function SearchPage() {
|
|||||||
const [entries, setEntries] = useState<Entry[]>([]);
|
const [entries, setEntries] = useState<Entry[]>([]);
|
||||||
const [searchTimeout, setSearchTimeout] = useState(0);
|
const [searchTimeout, setSearchTimeout] = useState(0);
|
||||||
const [furigana, setFurigana] = useState("");
|
const [furigana, setFurigana] = useState("");
|
||||||
|
const [isAutoKana, set_isAutoKana] = useState(true);
|
||||||
|
|
||||||
const nSearch = useRef(0);
|
const nSearch = useRef(0);
|
||||||
|
const searchboxRef = useRef<HTMLInputElement | null>(null);
|
||||||
|
|
||||||
const lang = "ja-JP";
|
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 FURIGANA_REGEX = /^[\p{scx=Hiragana}\p{scx=Katakana}]+$/u;
|
||||||
const KANJI_REGEX = /([\p{sc=Han}\p{N}々〆ヵヶ]+)/u;
|
const KANJI_REGEX = /([\p{sc=Han}\p{N}々〆ヵヶ]+)/u;
|
||||||
|
|
||||||
@@ -134,6 +155,17 @@ function SearchPage() {
|
|||||||
: k;
|
: k;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const clearButton = q.trim() ? (
|
||||||
|
<CloseButton
|
||||||
|
size={"xs"}
|
||||||
|
me={-2}
|
||||||
|
onClick={() => {
|
||||||
|
setQ("");
|
||||||
|
searchboxRef.current ? searchboxRef.current.focus() : null;
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
) : null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Stack maxW={"1000px"} margin={"0.5em auto"}>
|
<Stack maxW={"1000px"} margin={"0.5em auto"}>
|
||||||
<form
|
<form
|
||||||
@@ -143,18 +175,31 @@ function SearchPage() {
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Group attached w="full">
|
<Group attached w="full">
|
||||||
|
<InputGroup endElement={clearButton}>
|
||||||
<Input
|
<Input
|
||||||
id="greet-input"
|
id="greet-input"
|
||||||
|
ref={searchboxRef}
|
||||||
value={q}
|
value={q}
|
||||||
onChange={(e) => setQ(e.currentTarget.value)}
|
onChange={(e) => onSearchboxChange(e.currentTarget.value)}
|
||||||
onCompositionUpdate={updateFurigana}
|
onCompositionUpdate={updateFurigana}
|
||||||
onCompositionEnd={addFurigana}
|
onCompositionEnd={addFurigana}
|
||||||
autoComplete="off"
|
autoComplete="off"
|
||||||
spellCheck={false}
|
spellCheck={false}
|
||||||
placeholder="Search..."
|
placeholder="Search..."
|
||||||
/>
|
/>
|
||||||
<Button type="submit">Search</Button>
|
</InputGroup>
|
||||||
|
{/* <Button type="submit">Search</Button> */}
|
||||||
</Group>
|
</Group>
|
||||||
|
<div style={{ marginTop: "0.5em" }}>
|
||||||
|
<Switch.Root
|
||||||
|
checked={isAutoKana}
|
||||||
|
onCheckedChange={(d) => set_isAutoKana(d.checked)}
|
||||||
|
>
|
||||||
|
<Switch.HiddenInput />
|
||||||
|
<Switch.Control />
|
||||||
|
<Switch.Label>Auto-convert Kana</Switch.Label>
|
||||||
|
</Switch.Root>
|
||||||
|
</div>
|
||||||
</form>
|
</form>
|
||||||
<Box as={"ol"} listStyleType={"number"} style={{ margin: "1em" }}>
|
<Box as={"ol"} listStyleType={"number"} style={{ margin: "1em" }}>
|
||||||
{entries.map(
|
{entries.map(
|
||||||
|
|||||||
Reference in new issue
Block a user