improve inflection tables

This commit is contained in:
Bill D 2021-04-17 13:40:34 +03:00
parent e64f79e8b3
commit 2615e5f104
6 changed files with 64 additions and 93 deletions

View File

@ -1,6 +1,6 @@
{ {
"name": "@lingdocs/pashto-inflector", "name": "@lingdocs/pashto-inflector",
"version": "0.3.8", "version": "0.3.9",
"author": "lingdocs.com", "author": "lingdocs.com",
"description": "A Pashto inflection and verb conjugation engine, inculding React components for displaying Pashto text, inflections, and conjugations", "description": "A Pashto inflection and verb conjugation engine, inculding React components for displaying Pashto text, inflections, and conjugations",
"homepage": "https://verbs.lingdocs.com", "homepage": "https://verbs.lingdocs.com",

View File

@ -91,10 +91,6 @@ hr {
max-width: 700px; max-width: 700px;
} }
.thin-column {
max-width: 1rem;
}
.word { .word {
margin-bottom: 1.25rem; margin-bottom: 1.25rem;
} }

View File

@ -191,7 +191,7 @@ function App() {
console.log(textOptions); console.log(textOptions);
return <> return <>
<main className="flex-shrink-0 mb-4"> <main className="flex-shrink-0 mb-4">
<div className="container"> <div className="container" style={{ maxWidth: "800px" }}>
<div style={{ position: "absolute", top: "1.5rem", right: "1.5rem", display: "flex", flexDirection: "row" }}> <div style={{ position: "absolute", top: "1.5rem", right: "1.5rem", display: "flex", flexDirection: "row" }}>
<div <div
className="clickable mr-3" className="clickable mr-3"

View File

@ -8,8 +8,8 @@
import { useState } from "react"; import { useState } from "react";
import Pashto from "./Pashto"; import Pashto from "./Pashto";
import Phonetics from "./Phonetics";
import { Modal } from "react-bootstrap"; import { Modal } from "react-bootstrap";
import TableCell from "./TableCell";
import * as T from "../types"; import * as T from "../types";
const explanation = (inf: T.Inflections, textOptions: T.TextOptions) => { const explanation = (inf: T.Inflections, textOptions: T.TextOptions) => {
@ -49,50 +49,20 @@ const InflectionTable = ({ inf, textOptions }: {
<i className={`fa fa-question-circle`}></i> <i className={`fa fa-question-circle`}></i>
</div> </div>
</div> </div>
<table className="table"> <table className="table" style={{ tableLayout: "fixed" }}>
<thead> <thead>
<tr> <tr>
<th></th> <th scope="col" style={{ width: "3.5rem" }}></th>
{"masc" in inf && <th>Masculine</th>} {"masc" in inf && <th scope="col" style={{ maxWidth: "10rem" }}>Masculine</th>}
{"fem" in inf && <th>Feminine</th>} {"fem" in inf && <th scope="col" style={{ maxWidth: "10rem" }}>Feminine</th>}
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{["Plain", "1st", "2nd"].map((title, i) => ( {["Plain", "1st", "2nd"].map((title, i) => (
<tr key={title}> <tr key={title}>
<th scope="row" className="thin-column">{title}</th> <th scope="row">{title}</th>
{"masc" in inf && <td> {"masc" in inf && <TableCell item={inf.masc[i]} textOptions={textOptions} />}
{inf.masc[i].map((w, j) => ( {"fem" in inf && <TableCell item={inf.fem[i]} textOptions={textOptions} />}
<div key={`${i}-${j}-inflection-result`}>
<div>
<Pashto opts={textOptions}>
{w}
</Pashto>
</div>
<div>
<Phonetics opts={textOptions}>
{w}
</Phonetics>
</div>
</div>
))}
</td>}
{"fem" in inf && <td>
{inf.fem[i].map((w, j) => (
<div key={`${i}-${j}-inflection-result`}>
<div>
<Pashto opts={textOptions}>
{w}
</Pashto>
</div>
<div>
<Phonetics opts={textOptions}>
{w}
</Phonetics>
</div>
</div>
))}
</td>}
</tr> </tr>
))} ))}
</tbody> </tbody>

View File

@ -0,0 +1,50 @@
import { useState, useEffect } from "react";
import * as T from "../types";
import Pashto from "./Pashto";
import Phonetics from "./Phonetics";
const arrowDown = <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor" className="bi bi-caret-down" viewBox="0 0 20 20">
<path fillRule="evenodd" d="M3.204 5L8 10.481 12.796 5H3.204zm-.753.659l4.796 5.48a1 1 0 0 0 1.506 0l4.796-5.48c.566-.647.106-1.659-.753-1.659H3.204a1 1 0 0 0-.753 1.659z"/>
</svg>;
function TableCell({ item, textOptions, center, noBorder }: {
item: T.ArrayOneOrMore<T.PsString>,
textOptions: T.TextOptions,
center?: boolean,
noBorder?: boolean,
}) {
const [version, setVersion] = useState(0);
useEffect(() => setVersion(0), [item]);
function advanceVersion() {
setVersion((version + 1) % item.length);
}
const w = item[version] || item[0];
return (
<td style={{ ...noBorder ? { border: "none" } : {} }}>
<div style={{
display: "flex",
flexDirection: "row",
flexWrap: "wrap",
justifyContent: center ? "center" : "space-between",
alignItems: "center",
}}>
<div>
<div>
<Pashto opts={textOptions}>{w}</Pashto>
</div>
<div>
<Phonetics opts={textOptions}>{w}</Phonetics>
</div>
{w.e && <div className="text-muted">{w.e}</div>}
</div>
{item.length > 1 &&
<button className="btn btn-sm btn-light mx-2 my-2" onClick={advanceVersion}>
ver. {version + 1}/{item.length} {arrowDown}
</button>
}
</div>
</td>
);
}
export default TableCell;

View File

@ -6,9 +6,7 @@
* *
*/ */
import { useState, useEffect } from "react"; import TableCell from "./TableCell";
import Pashto from "./Pashto";
import Phonetics from "./Phonetics";
import { import {
psStringEquals, psStringEquals,
isAllOne, isAllOne,
@ -17,9 +15,6 @@ import {
import { isSentenceForm } from "../lib/misc-helpers"; import { isSentenceForm } from "../lib/misc-helpers";
import * as T from "../types"; import * as T from "../types";
const arrowDown = <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor" className="bi bi-caret-down" viewBox="0 0 20 20">
<path fillRule="evenodd" d="M3.204 5L8 10.481 12.796 5H3.204zm-.753.659l4.796 5.48a1 1 0 0 0 1.506 0l4.796-5.48c.566-.647.106-1.659-.753-1.659H3.204a1 1 0 0 0-.753 1.659z"/>
</svg>;
const genderAbbrev = (gender: "masc" | "fem" | undefined): " m." | " f." | "" => ( const genderAbbrev = (gender: "masc" | "fem" | undefined): " m." | " f." | "" => (
gender === "masc" gender === "masc"
@ -54,46 +49,6 @@ const minifyTableGender = (block: T.VerbBlock | T.ImperativeBlock): Array<T.Pers
}, []); }, []);
}; };
function Cell({ item, textOptions, center, noBorder }: {
item: T.ArrayOneOrMore<T.PsString>,
textOptions: T.TextOptions,
center?: boolean,
noBorder?: boolean,
}) {
const [version, setVersion] = useState(0);
useEffect(() => setVersion(0), [item]);
function advanceVersion() {
setVersion((version + 1) % item.length);
}
const w = item[version] || item[0];
return (
<td style={noBorder ? { border: "none" } : {}}>
<div style={{
display: "flex",
flexDirection: "row",
flexWrap: "wrap",
justifyContent: center ? "center" : "space-between",
alignItems: "center",
}}>
<div>
<div>
<Pashto opts={textOptions}>{w}</Pashto>
</div>
<div>
<Phonetics opts={textOptions}>{w}</Phonetics>
</div>
{w.e && <div className="text-muted">{w.e}</div>}
</div>
{item.length > 1 &&
<button className="btn btn-sm btn-light mx-2" onClick={advanceVersion}>
ver. {version + 1}/{item.length} {arrowDown}
</button>
}
</div>
</td>
);
}
function VerbTable({ block, textOptions, english }: { function VerbTable({ block, textOptions, english }: {
block: T.VerbBlock | T.ImperativeBlock | T.ArrayOneOrMore<T.PsString>, block: T.VerbBlock | T.ImperativeBlock | T.ArrayOneOrMore<T.PsString>,
english?: T.EnglishBlock | string, english?: T.EnglishBlock | string,
@ -110,7 +65,7 @@ function VerbTable({ block, textOptions, english }: {
return <table className="table text-center"> return <table className="table text-center">
<tbody> <tbody>
<tr> <tr>
<Cell item={item} textOptions={textOptions} center noBorder /> <TableCell item={item} textOptions={textOptions} center noBorder />
</tr> </tr>
</tbody> </tbody>
</table> </table>
@ -139,8 +94,8 @@ function VerbTable({ block, textOptions, english }: {
return ( return (
<tr key={`${i}${gender}`}> <tr key={`${i}${gender}`}>
<th scope="row" style={{ color }}>{rowLabel}</th> <th scope="row" style={{ color }}>{rowLabel}</th>
<Cell item={line[0]} textOptions={textOptions} /> <TableCell item={line[0]} textOptions={textOptions} />
<Cell item={line[1]} textOptions={textOptions} /> <TableCell item={line[1]} textOptions={textOptions} />
</tr> </tr>
); );
} }