pronoun picker tool
This commit is contained in:
parent
d71064ef43
commit
baf693b6da
|
@ -5,7 +5,7 @@
|
|||
"dependencies": {
|
||||
"@fortawesome/fontawesome-free": "^5.15.4",
|
||||
"@lingdocs/lingdocs-main": "^0.2.0",
|
||||
"@lingdocs/pashto-inflector": "^1.3.9",
|
||||
"@lingdocs/pashto-inflector": "^1.4.4",
|
||||
"@testing-library/jest-dom": "^5.11.4",
|
||||
"@testing-library/react": "^11.1.0",
|
||||
"@testing-library/user-event": "^12.1.10",
|
||||
|
|
|
@ -0,0 +1,137 @@
|
|||
import {
|
||||
Types as T,
|
||||
ButtonSelect,
|
||||
} from "@lingdocs/pashto-inflector";
|
||||
import useStickyState from "../../useStickyState";
|
||||
|
||||
const gColors = {
|
||||
masc: "LightSkyBlue",
|
||||
fem: "pink",
|
||||
};
|
||||
|
||||
const labels = {
|
||||
persons: [
|
||||
["1st", "1st pl."],
|
||||
["2nd", "2nd pl."],
|
||||
["3rd", "3rd pl."],
|
||||
],
|
||||
e: [
|
||||
["I", "We"],
|
||||
["You", "You pl."],
|
||||
[{ masc: "He/It", fem: "She/It"}, "They"],
|
||||
],
|
||||
p: {
|
||||
far: [
|
||||
["زه", "مونږ"],
|
||||
["ته", "تاسو"],
|
||||
["هغه", "هغوي"],
|
||||
],
|
||||
near: [
|
||||
["زه", "مونږ"],
|
||||
["ته", "تاسو"],
|
||||
[{ masc: "دی", fem: "دا" }, "دوي"],
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
type PickerState = { row: number, col: number, gender: T.Gender };
|
||||
|
||||
function personToPickerState(person: T.Person): PickerState {
|
||||
const col = person > 5 ? 1 : 0;
|
||||
const row = Math.floor((person > 5 ? (person - 6) : person) / 2);
|
||||
const gender: T.Gender = (person % 2) ? "fem" : "masc";
|
||||
return { col, row, gender };
|
||||
}
|
||||
|
||||
function pickerStateToPerson(s: PickerState): T.Person {
|
||||
return (s.row * 2)
|
||||
+ (s.gender === "masc" ? 0 : 1)
|
||||
+ (6 * s.col);
|
||||
}
|
||||
|
||||
function PronounPicker({ onChange, pronoun }: { pronoun: Pronoun, onChange: (p: Pronoun) => void }) {
|
||||
const [display, setDisplay] = useStickyState<"persons" | "p" | "e">("persons", "prounoun-picker-display");
|
||||
|
||||
const p = personToPickerState(pronoun.person);
|
||||
function handleClick(row: number, col: number) {
|
||||
onChange({
|
||||
...pronoun,
|
||||
person: pickerStateToPerson({
|
||||
...p,
|
||||
row,
|
||||
col,
|
||||
}),
|
||||
});
|
||||
}
|
||||
function handleGenderChange(gender: T.Gender) {
|
||||
onChange({
|
||||
...pronoun,
|
||||
person: pickerStateToPerson({
|
||||
...p,
|
||||
gender,
|
||||
}),
|
||||
});
|
||||
}
|
||||
function handlePronounTypeChange(pronounType: "far" | "near") {
|
||||
onChange({
|
||||
...pronoun,
|
||||
pronounType,
|
||||
});
|
||||
}
|
||||
function handleDisplayChange() {
|
||||
const newPerson = display === "persons"
|
||||
? "p"
|
||||
: display === "p"
|
||||
? "e"
|
||||
: "persons";
|
||||
setDisplay(newPerson);
|
||||
}
|
||||
const prs = labels[display];
|
||||
const pSpec = "near" in prs ? prs[pronoun.pronounType] : prs;
|
||||
return <div>
|
||||
<div className="d-flex flex-row justify-content-around mb-3">
|
||||
<ButtonSelect
|
||||
xSmall
|
||||
options={[
|
||||
{ label: "Far", value: "far" },
|
||||
{ label: "Near", value: "near" },
|
||||
]}
|
||||
value={pronoun.pronounType}
|
||||
handleChange={(g) => handlePronounTypeChange(g as "far" | "near")}
|
||||
/>
|
||||
<button className="btn btn-sm btn-outline" onClick={handleDisplayChange}>{display === "persons" ? "#" : display === "p" ? "PS" : "EN"}</button>
|
||||
</div>
|
||||
<table className="table table-bordered" style={{ textAlign: "center", minWidth: "200px", tableLayout: "fixed" }}>
|
||||
<tbody>
|
||||
{pSpec.map((rw, i) => (
|
||||
<tr>
|
||||
{rw.map((r, j) => {
|
||||
const active = (p.row === i && p.col === j)
|
||||
return <td
|
||||
onClick={() => handleClick(i, j)}
|
||||
className={active ? "table-active" : ""}
|
||||
style={active ? { backgroundColor: gColors[p.gender] } : {}}
|
||||
>
|
||||
{typeof r === "string" ? r : r[p.gender]}
|
||||
</td>;
|
||||
})}
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
<div className="text-center">
|
||||
<ButtonSelect
|
||||
options={[
|
||||
{ label: "Masc.", value: "masc", color: gColors.masc },
|
||||
{ label: "Fem.", value: "fem", color: gColors.fem },
|
||||
]}
|
||||
value={p.gender}
|
||||
handleChange={(g) => handleGenderChange(g as T.Gender)}
|
||||
/>
|
||||
</div>
|
||||
</div>;
|
||||
};
|
||||
|
||||
export default PronounPicker;
|
||||
|
|
@ -3,6 +3,18 @@ title: Equative Explorer 🌎
|
|||
---
|
||||
|
||||
import EquativeExplorer from "../../components/equative-explorer/EquativeExplorer";
|
||||
import PronounPicker from "../../components/np-picker/PronounPicker";
|
||||
import { useState } from "react";
|
||||
|
||||
export function PDem() {
|
||||
const [pronoun, setPronoun] = useState({ type: "pronoun", pronounType: "far", person: 11 });
|
||||
return <div style={{ maxWidth: "200px" }}>
|
||||
<PronounPicker pronoun={pronoun} onChange={setPronoun} />
|
||||
<pre>{JSON.stringify(pronoun, null, " ")}</pre>
|
||||
</div>
|
||||
}
|
||||
|
||||
<PDem />
|
||||
|
||||
You can use this tool to explore how to make different equative sentences. Everything that comes out of this will be **gramatically correct**, but the sentences might not always make sense! 🤪
|
||||
|
||||
|
|
|
@ -78,6 +78,9 @@ import * as typingIssues from "!babel-loader!@lingdocs/mdx-loader!./writing/typi
|
|||
// @ts-ignore
|
||||
import * as games from "!babel-loader!@lingdocs/mdx-loader!./games.mdx";
|
||||
|
||||
// @ts-ignore
|
||||
import * as pronounPicker from "!babel-loader!@lingdocs/mdx-loader!./practice-tools/pronoun-picker.mdx";
|
||||
|
||||
const contentTree = [
|
||||
{
|
||||
import: intro,
|
||||
|
@ -245,6 +248,16 @@ const contentTree = [
|
|||
import: games,
|
||||
slug: "games",
|
||||
},
|
||||
{
|
||||
heading: "Practice Tools 🔧",
|
||||
subdirectory: "practice-tools",
|
||||
chapters: [
|
||||
{
|
||||
import: pronounPicker,
|
||||
slug: "pronoun-picker",
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
export const content = contentTree.map((item) => {
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
---
|
||||
title: Pronoun Picker
|
||||
---
|
||||
|
||||
import PronounPicker from "../../components/np-picker/PronounPicker";
|
||||
import {
|
||||
defaultTextOptions as opts,
|
||||
InlinePs,
|
||||
} from "@lingdocs/pashto-inflector";
|
||||
import { useState } from "react";
|
||||
|
||||
export function randomP(p) {
|
||||
let newP = 0;
|
||||
do {
|
||||
newP = Math.floor(Math.random() * 12);
|
||||
} while (newP === p);
|
||||
return newP;
|
||||
}
|
||||
|
||||
export function RPicker() {
|
||||
const [pronoun, setPronoun] = useState({ type: "pronoun", pronounType: "far", person: randomP() });
|
||||
function handleRandom() {
|
||||
const person = randomP(pronoun.person);
|
||||
setPronoun({
|
||||
...pronoun,
|
||||
person,
|
||||
});
|
||||
}
|
||||
return <div className="text-center">
|
||||
<div className="my-4" style={{ maxWidth: "375px", margin: "0 auto" }}>
|
||||
<PronounPicker pronoun={pronoun} onChange={setPronoun} />
|
||||
</div>
|
||||
<button className="btn btn-lg btn-primary mt-2">
|
||||
<i class="fas fa-random" onClick={handleRandom} />
|
||||
</button>
|
||||
</div>;
|
||||
}
|
||||
|
||||
Use this pronoun picker to help you drill different sentences. Choose different pronouns to drill a friend, or press the <i class="fas fa-random"></i> button to get a random selection.
|
||||
|
||||
<div className="mt-4">
|
||||
<RPicker />
|
||||
</div>
|
||||
|
||||
<details className="mt-4">
|
||||
<summary>Show Second Picker</summary>
|
||||
<RPicker />
|
||||
</details>
|
|
@ -45,6 +45,7 @@ type Compliment = {
|
|||
type Participle = {
|
||||
type: "participle",
|
||||
entry: VerbEntry,
|
||||
np?: NounPhrase,
|
||||
}
|
||||
|
||||
type Pronoun = {
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
import { useEffect, useState } from "react";
|
||||
|
||||
export default function useStickyState<T>(defaultValue: T, key: string): {
|
||||
export default function useStickyState<T>(defaultValue: T, key: string): [
|
||||
value: T,
|
||||
setValue: React.Dispatch<React.SetStateAction<T>>,
|
||||
} {
|
||||
|
||||
] {
|
||||
const [value, setValue] = useState<T>(() => {
|
||||
const stickyValue = window.localStorage.getItem(key);
|
||||
if (stickyValue === null) return defaultValue;
|
||||
|
@ -20,5 +19,5 @@ export default function useStickyState<T>(defaultValue: T, key: string): {
|
|||
window.localStorage.setItem(key, JSON.stringify(value));
|
||||
}, [key, value]);
|
||||
|
||||
return {value, setValue};
|
||||
return [value, setValue];
|
||||
}
|
|
@ -19,7 +19,7 @@ const UserContext = createContext<
|
|||
|
||||
// TODO: persisting user in local state
|
||||
function UserProvider({ children }: any) {
|
||||
const {value, setValue} = useStickyState<AT.LingdocsUser | undefined>(
|
||||
const [value, setValue] = useStickyState<AT.LingdocsUser | undefined>(
|
||||
undefined,
|
||||
"saved-user",
|
||||
);
|
||||
|
|
|
@ -1684,10 +1684,10 @@
|
|||
pbf "^3.2.1"
|
||||
rambda "^6.7.0"
|
||||
|
||||
"@lingdocs/pashto-inflector@^1.3.5":
|
||||
version "1.3.5"
|
||||
resolved "https://npm.lingdocs.com/@lingdocs%2fpashto-inflector/-/pashto-inflector-1.3.5.tgz#cfc311462c686e5591f12ee68b333a2ec479f428"
|
||||
integrity sha512-Asxu773Z9+0Gxi8wkSD6x3JYcSeJmXqgoHQu1Hvph1oOAac3t8Bn0uXC/OGO5p1leilEHePJT+hkMFmURTArcw==
|
||||
"@lingdocs/pashto-inflector@^1.4.4":
|
||||
version "1.4.4"
|
||||
resolved "https://npm.lingdocs.com/@lingdocs%2fpashto-inflector/-/pashto-inflector-1.4.4.tgz#5015bf1e4abd913bdb2cbcc08a89ab64a7194d9e"
|
||||
integrity sha512-RGf3AZFpy4JWzjWLeeGNLvy1PsDljRcDF4mQIqMPrFeakkuT4h3/exbGAANehNWGt9hm6LbPvXyXQmxe7SWaXg==
|
||||
dependencies:
|
||||
classnames "^2.2.6"
|
||||
pbf "^3.2.1"
|
||||
|
|
Loading…
Reference in New Issue