+ {/* 設定・カテゴリ選択パネル */}
+
+
+ {/* カテゴリ選択 */}
+
+
+ カテゴリ:
+
+
+
+ {tables.map((t) => (
+
+ ))}
+
+
+
+ {/* 空欄割合選択 */}
+
+
+ 空欄の割合:
+
+
+ {[
+ { label: "25%", value: "25" },
+ { label: "50%", value: "50" },
+ { label: "75%", value: "75" },
+ { label: "100%", value: "100" },
+ ].map((opt) => (
+
+ ))}
+
+
+
+
+
+ {/* 特殊文字ボタンパレット */}
+
+
+ 特殊文字入力パレット (選択中セルへ挿入)
+
+
+ {SPECIAL_KEYS.map((char) => (
+
+ ))}
+
+
+ 💡 入力セルで ↑ / ↓ 矢印キー を押してもアクセント記号(á, é, í, ó, ú, ñ
+ など)へ切り替えられます。
+
+
+
+ {/* 文法表完成グリッド */}
+
+ {filteredTables.map((table, tIdx) => (
+
+
+ 【{table.categoryTitle}】
+
+
+
+ ))}
+
+
+ {/* スコア・結果表示バッジ & 操作ボタンエリア */}
+
+ {isChecked && (
+
+
+ 答え合わせ結果:{" "}
+
+ {correctCount}
+ {" "}
+ / {totalBlankCells} 空欄正解 (
+ {totalBlankCells > 0 ? Math.round((correctCount / totalBlankCells) * 100) : 0}%)
+
+
+ )}
+
+
+ {!isChecked ? (
+
+ ) : (
+
+ )}
+
+
+
+
+ );
+}
diff --git a/components/spanish/SpanishTablePracticeLoader.tsx b/components/spanish/SpanishTablePracticeLoader.tsx
new file mode 100644
index 0000000..46ce81a
--- /dev/null
+++ b/components/spanish/SpanishTablePracticeLoader.tsx
@@ -0,0 +1,104 @@
+import fs from "node:fs/promises";
+import path from "node:path";
+import SpanishTablePractice, {
+ type GrammarTableCell,
+ type GrammarTableData,
+ type GrammarTableRow,
+} from "./SpanishTablePractice";
+
+function mergeAdjacentCells(cells: string[]): GrammarTableCell[] {
+ const mergedCells: GrammarTableCell[] = [];
+
+ for (const value of cells) {
+ const previousCell = mergedCells.at(-1);
+ if (previousCell?.value === value) {
+ previousCell.colSpan += 1;
+ } else {
+ mergedCells.push({ value, colSpan: 1 });
+ }
+ }
+
+ return mergedCells;
+}
+
+/**
+ * MDX教材ファイル(app/learn/spanish/03/page.mdx)から
+ * 人称代名詞・冠詞・指示詞の各文法表データを動的に抽出する関数。
+ * データのベタ打ちを排除し、教材ファイルを唯一のデータソースとして使用する。
+ */
+async function getGrammarTablesFromMdx(): Promise