diff --git a/package.json b/package.json index f5058db..634f305 100644 --- a/package.json +++ b/package.json @@ -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", diff --git a/src/components/np-picker/PronounPicker.tsx b/src/components/np-picker/PronounPicker.tsx new file mode 100644 index 0000000..9b24390 --- /dev/null +++ b/src/components/np-picker/PronounPicker.tsx @@ -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
+
+ handlePronounTypeChange(g as "far" | "near")} + /> + +
+ + + {pSpec.map((rw, i) => ( + + {rw.map((r, j) => { + const active = (p.row === i && p.col === j) + return ; + })} + + ))} + +
handleClick(i, j)} + className={active ? "table-active" : ""} + style={active ? { backgroundColor: gColors[p.gender] } : {}} + > + {typeof r === "string" ? r : r[p.gender]} +
+
+ handleGenderChange(g as T.Gender)} + /> +
+
; +}; + +export default PronounPicker; + diff --git a/src/content/equatives/equative-explorer.mdx b/src/content/equatives/equative-explorer.mdx index ec18ed4..ab2c6c3 100644 --- a/src/content/equatives/equative-explorer.mdx +++ b/src/content/equatives/equative-explorer.mdx @@ -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
+ +
{JSON.stringify(pronoun, null, "  ")}
+
+} + + 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! 🤪 diff --git a/src/content/index.ts b/src/content/index.ts index 4acb2e1..89b044f 100644 --- a/src/content/index.ts +++ b/src/content/index.ts @@ -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) => { diff --git a/src/content/practice-tools/pronoun-picker.mdx b/src/content/practice-tools/pronoun-picker.mdx new file mode 100644 index 0000000..895fbaf --- /dev/null +++ b/src/content/practice-tools/pronoun-picker.mdx @@ -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
+
+ +
+ +
; +} + +Use this pronoun picker to help you drill different sentences. Choose different pronouns to drill a friend, or press the button to get a random selection. + +
+ +
+ +
+ Show Second Picker + +
\ No newline at end of file diff --git a/src/types/gramm-types.d.ts b/src/types/gramm-types.d.ts index ec4c62c..967527e 100644 --- a/src/types/gramm-types.d.ts +++ b/src/types/gramm-types.d.ts @@ -45,6 +45,7 @@ type Compliment = { type Participle = { type: "participle", entry: VerbEntry, + np?: NounPhrase, } type Pronoun = { diff --git a/src/useStickyState.ts b/src/useStickyState.ts index 16f98ee..a617ef8 100644 --- a/src/useStickyState.ts +++ b/src/useStickyState.ts @@ -1,10 +1,9 @@ import { useEffect, useState } from "react"; -export default function useStickyState(defaultValue: T, key: string): { +export default function useStickyState(defaultValue: T, key: string): [ value: T, setValue: React.Dispatch>, -} { - +] { const [value, setValue] = useState(() => { const stickyValue = window.localStorage.getItem(key); if (stickyValue === null) return defaultValue; @@ -20,5 +19,5 @@ export default function useStickyState(defaultValue: T, key: string): { window.localStorage.setItem(key, JSON.stringify(value)); }, [key, value]); - return {value, setValue}; + return [value, setValue]; } \ No newline at end of file diff --git a/src/user-context.tsx b/src/user-context.tsx index a9111d0..c42e74f 100644 --- a/src/user-context.tsx +++ b/src/user-context.tsx @@ -19,7 +19,7 @@ const UserContext = createContext< // TODO: persisting user in local state function UserProvider({ children }: any) { - const {value, setValue} = useStickyState( + const [value, setValue] = useStickyState( undefined, "saved-user", ); diff --git a/yarn.lock b/yarn.lock index c05f5a6..510992e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -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"