インベントリに戻る
vanilla-autokana デモ
📦
vanilla-autokana デモ
2024レア
vanilla-autokanaライブラリを使ったふりがな自動入力デモ。setIntervalポーリング+value基盤のひらがなフィルタリング方式。
使用技術
ReactTypeScriptvanilla-autokana
デモ
性(せい)
名(めい)
ふりがな結果
ふりがな結果
useState: {"lastName":"","firstName":"","lastNameFurigana":"","firstNameFurigana":""}
ソースコード
1"use client";23import { useState, useEffect, useRef, useCallback } from "react";4import { useLanguage } from "@/context/LanguageContext";56interface AutoKanaInstance {7 getFurigana: () => string;8 start: () => void;9 stop: () => void;10}1112interface FormState {13 lastName: string;14 firstName: string;15 lastNameFurigana: string;16 firstNameFurigana: string;17}1819const initialState: FormState = {20 lastName: "",21 firstName: "",22 lastNameFurigana: "",23 firstNameFurigana: "",24};2526export function AutoKanaDemo() {27 const { t } = useLanguage();28 const [katakana, setKatakana] = useState(false);29 const [form, setForm] = useState<FormState>(initialState);30 const lastNameRef = useRef<AutoKanaInstance | null>(null);31 const firstNameRef = useRef<AutoKanaInstance | null>(null);32 const timerRef = useRef<ReturnType<typeof setInterval> | null>(null);3334 useEffect(() => {35 let cancelled = false;3637 async function init() {38 const mod = await import("vanilla-autokana");39 const bind = mod.bind || mod.default?.bind;40 if (cancelled || !bind) return;4142 lastNameRef.current = bind(43 "#autokana-lastname",44 "#autokana-lastname-furigana",45 { katakana }46 );47 firstNameRef.current = bind(48 "#autokana-firstname",49 "#autokana-firstname-furigana",50 { katakana }51 );5253 timerRef.current = setInterval(() => {54 const lastFuri = lastNameRef.current?.getFurigana() ?? "";55 const firstFuri = firstNameRef.current?.getFurigana() ?? "";56 setForm((prev) => {57 if (58 prev.lastNameFurigana === lastFuri &&59 prev.firstNameFurigana === firstFuri60 ) {61 return prev;62 }63 return {64 ...prev,65 lastNameFurigana: lastFuri,66 firstNameFurigana: firstFuri,67 };68 });69 }, 50);70 }7172 init();7374 return () => {75 cancelled = true;76 if (timerRef.current) clearInterval(timerRef.current);77 lastNameRef.current = null;78 firstNameRef.current = null;79 };80 }, [katakana]);8182 const handleReset = useCallback(() => {83 setForm(initialState);84 const els = [85 "autokana-lastname", "autokana-firstname",86 "autokana-lastname-furigana", "autokana-firstname-furigana",87 ];88 for (const id of els) {89 const el = document.getElementById(id) as HTMLInputElement | null;90 if (el) el.value = "";91 }92 }, []);9394 const handleKatakanaToggle = useCallback(() => {95 setKatakana((prev) => !prev);96 handleReset();97 }, [handleReset]);9899 return (100 <div className="space-y-4">101 <div className="grid grid-cols-2 gap-3">102 <div className="space-y-1">103 <span>{t.inventory.lastName}</span>104 <input id="autokana-lastname" type="text" value={form.lastName}105 onChange={(e) => setForm((prev) => ({ ...prev, lastName: e.target.value }))} />106 </div>107 <div className="space-y-1">108 <span>{t.inventory.firstName}</span>109 <input id="autokana-firstname" type="text" value={form.firstName}110 onChange={(e) => setForm((prev) => ({ ...prev, firstName: e.target.value }))} />111 </div>112 </div>113 <div className="grid grid-cols-2 gap-3">114 <input id="autokana-lastname-furigana" type="text" value={form.lastNameFurigana}115 onChange={(e) => setForm((prev) => ({ ...prev, lastNameFurigana: e.target.value }))} />116 <input id="autokana-firstname-furigana" type="text" value={form.firstNameFurigana}117 onChange={(e) => setForm((prev) => ({ ...prev, firstNameFurigana: e.target.value }))} />118 </div>119 <div>{JSON.stringify(form)}</div>120 <div>121 <button onClick={handleKatakanaToggle}>{t.inventory.katakanaMode}</button>122 <button onClick={handleReset}>{t.inventory.reset}</button>123 </div>124 </div>125 );126}