charts added in verb explorer
This commit is contained in:
parent
b9cab6efa4
commit
1bc735d809
|
@ -14,6 +14,7 @@ function EntrySelect<E extends T.DictionaryEntry | VerbEntry>(props: {
|
||||||
onChange: (value: E | undefined) => void,
|
onChange: (value: E | undefined) => void,
|
||||||
name: string | undefined,
|
name: string | undefined,
|
||||||
isVerbSelect?: boolean,
|
isVerbSelect?: boolean,
|
||||||
|
opts: T.TextOptions,
|
||||||
}) {
|
}) {
|
||||||
const options = props.entries
|
const options = props.entries
|
||||||
.sort((a, b) => {
|
.sort((a, b) => {
|
||||||
|
@ -24,11 +25,11 @@ function EntrySelect<E extends T.DictionaryEntry | VerbEntry>(props: {
|
||||||
})
|
})
|
||||||
.map((e) => {
|
.map((e) => {
|
||||||
if ("entry" in e) {
|
if ("entry" in e) {
|
||||||
return (props.isVerbSelect ? makeVerbSelectOption : makeSelectOption)(e);
|
return (props.isVerbSelect ? makeVerbSelectOption : makeSelectOption)(e, props.opts);
|
||||||
}
|
}
|
||||||
return makeSelectOption(e);
|
return makeSelectOption(e, props.opts);
|
||||||
});
|
});
|
||||||
function onSelect(v: { label: string, value: string } | null) {
|
function onSelect(v: { label: string | JSX.Element, value: string } | null) {
|
||||||
if (!v) {
|
if (!v) {
|
||||||
props.onChange(undefined);
|
props.onChange(undefined);
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import {
|
import {
|
||||||
ButtonSelect,
|
ButtonSelect,
|
||||||
|
Types as T,
|
||||||
} from "@lingdocs/pashto-inflector";
|
} from "@lingdocs/pashto-inflector";
|
||||||
import {
|
import {
|
||||||
makeVerbSelection,
|
makeVerbSelection,
|
||||||
|
@ -8,12 +9,13 @@ import EntrySelect from "./EntrySelect";
|
||||||
|
|
||||||
// TODO: dark on past tense selecitons
|
// TODO: dark on past tense selecitons
|
||||||
|
|
||||||
function VerbPicker({ onChange, subject, changeSubject, verb, verbs }: {
|
function VerbPicker({ onChange, subject, changeSubject, verb, verbs, opts }: {
|
||||||
verbs: VerbEntry[],
|
verbs: VerbEntry[],
|
||||||
verb: VerbSelection | undefined,
|
verb: VerbSelection | undefined,
|
||||||
subject: NPSelection | undefined,
|
subject: NPSelection | undefined,
|
||||||
onChange: (p: VerbSelection | undefined) => void,
|
onChange: (p: VerbSelection | undefined) => void,
|
||||||
changeSubject: (p: NPSelection | undefined) => void,
|
changeSubject: (p: NPSelection | undefined) => void,
|
||||||
|
opts: T.TextOptions,
|
||||||
}) {
|
}) {
|
||||||
// const [filters, useFilters] = useState<Filters>({
|
// const [filters, useFilters] = useState<Filters>({
|
||||||
// stative: true,
|
// stative: true,
|
||||||
|
@ -62,6 +64,7 @@ function VerbPicker({ onChange, subject, changeSubject, verb, verbs }: {
|
||||||
onChange={onVerbSelect}
|
onChange={onVerbSelect}
|
||||||
name="Verb"
|
name="Verb"
|
||||||
isVerbSelect
|
isVerbSelect
|
||||||
|
opts={opts}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="d-flex flex-row justify-content-around flex-wrap" style={{ maxWidth: "400px", margin: "0 auto" }}>
|
<div className="d-flex flex-row justify-content-around flex-wrap" style={{ maxWidth: "400px", margin: "0 auto" }}>
|
||||||
|
|
|
@ -1,179 +0,0 @@
|
||||||
import Select from "react-select";
|
|
||||||
import {
|
|
||||||
zIndexProps,
|
|
||||||
} from "./np-picker/picker-tools";
|
|
||||||
import {
|
|
||||||
ButtonSelect,
|
|
||||||
} from "@lingdocs/pashto-inflector";
|
|
||||||
import { isPerfectTense } from "../lib/phrase-building/vp-tools";
|
|
||||||
|
|
||||||
const tenseOptions: { label: string | JSX.Element, value: VerbTense }[] = [{
|
|
||||||
label: <div><i className="fas fa-video mr-2" />present</div>,
|
|
||||||
value: "presentVerb",
|
|
||||||
}, {
|
|
||||||
label: <div><i className="fas fa-camera mr-2" />subjunctive</div>,
|
|
||||||
value: "subjunctiveVerb",
|
|
||||||
}, {
|
|
||||||
label: <div><i className="fas fa-video mr-2" />imperf. future</div>,
|
|
||||||
value: "imperfectiveFuture",
|
|
||||||
}, {
|
|
||||||
label: <div><i className="fas fa-camera mr-2" />perf. future</div>,
|
|
||||||
value: "perfectiveFuture",
|
|
||||||
}, {
|
|
||||||
label: <div><i className="fas fa-video mr-2" />continuous past</div>,
|
|
||||||
value: "imperfectivePast",
|
|
||||||
}, {
|
|
||||||
label: <div><i className="fas fa-camera mr-2" />simple past</div>,
|
|
||||||
value: "perfectivePast",
|
|
||||||
}, {
|
|
||||||
label: <div><i className="fas fa-video mr-2" />habitual cont. past.</div>,
|
|
||||||
value: "habitualImperfectivePast",
|
|
||||||
}, {
|
|
||||||
label: <div><i className="fas fa-camera mr-2" />habitual simp. past.</div>,
|
|
||||||
value: "habitualPerfectivePast",
|
|
||||||
}];
|
|
||||||
|
|
||||||
const perfectTenseOptions: { label: string | JSX.Element, value: PerfectTense }[] = [{
|
|
||||||
label: "Present Perfect",
|
|
||||||
value: "present perfect",
|
|
||||||
}, {
|
|
||||||
label: "Habitual Perfect",
|
|
||||||
value: "habitual perfect",
|
|
||||||
}, {
|
|
||||||
label: "Subjunctive Perfect",
|
|
||||||
value: "subjunctive perfect",
|
|
||||||
}, {
|
|
||||||
label: "Future Perfect",
|
|
||||||
value: "future perfect",
|
|
||||||
}, {
|
|
||||||
label: "Past Perfect",
|
|
||||||
value: "past perfect",
|
|
||||||
}, {
|
|
||||||
label: `"Would Be" Perfect`,
|
|
||||||
value: "wouldBe perfect",
|
|
||||||
}, {
|
|
||||||
label: "Past Subjunctive Perfect",
|
|
||||||
value: "pastSubjunctive perfect",
|
|
||||||
}];
|
|
||||||
|
|
||||||
function VerbPickerBelow({ onChange, verb }: {
|
|
||||||
verbs: VerbEntry[],
|
|
||||||
verb: VerbSelection | undefined,
|
|
||||||
onChange: (p: VerbSelection | undefined) => void,
|
|
||||||
}) {
|
|
||||||
function onTenseSelect(o: { value: VerbTense | PerfectTense } | null) {
|
|
||||||
const value = o?.value ? o.value : undefined;
|
|
||||||
if (verb && value) {
|
|
||||||
if (isPerfectTense(value)) {
|
|
||||||
onChange({
|
|
||||||
...verb,
|
|
||||||
tense: value,
|
|
||||||
tenseCategory: "perfect",
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
onChange({
|
|
||||||
...verb,
|
|
||||||
tense: value,
|
|
||||||
tenseCategory: verb.tenseCategory === "perfect" ? "basic" : verb.tenseCategory,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
function moveTense(dir: "forward" | "back") {
|
|
||||||
if (!verb) return;
|
|
||||||
return () => {
|
|
||||||
const tenses = verb.tenseCategory === "perfect" ? perfectTenseOptions : tenseOptions;
|
|
||||||
const currIndex = tenses.findIndex(tn => tn.value === verb.tense)
|
|
||||||
if (currIndex === -1) {
|
|
||||||
console.error("error moving tense", dir);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const newIndex = dir === "forward"
|
|
||||||
? ((currIndex + 1) % tenses.length)
|
|
||||||
: (currIndex === 0 ? (tenses.length - 1) : (currIndex - 1))
|
|
||||||
const newTense = tenses[newIndex];
|
|
||||||
onTenseSelect(newTense);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
function onPosNegSelect(value: string) {
|
|
||||||
if (verb) {
|
|
||||||
onChange({
|
|
||||||
...verb,
|
|
||||||
negative: value === "true",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
function onTenseCategorySelect(value: "basic" | "modal" | "perfect") {
|
|
||||||
if (verb) {
|
|
||||||
if (value === "perfect") {
|
|
||||||
onChange({
|
|
||||||
...verb,
|
|
||||||
tenseCategory: value,
|
|
||||||
tense: isPerfectTense(verb.tense) ? verb.tense : "present perfect",
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
onChange({
|
|
||||||
...verb,
|
|
||||||
tenseCategory: value,
|
|
||||||
tense: isPerfectTense(verb.tense) ? "presentVerb" : verb.tense,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const tOptions = (verb?.tenseCategory === "perfect") ? perfectTenseOptions : tenseOptions;
|
|
||||||
return <div className="mb-0 mt-3">
|
|
||||||
<div style={{ maxWidth: "300px", minWidth: "250px", margin: "0 auto" }}>
|
|
||||||
<div className="d-flex flex-row justify-content-between align-items-center">
|
|
||||||
<div className="h5">Tense:</div>
|
|
||||||
{verb && <div className="mb-2">
|
|
||||||
<ButtonSelect
|
|
||||||
small
|
|
||||||
value={verb.tenseCategory}
|
|
||||||
options={[{
|
|
||||||
label: "Basic",
|
|
||||||
value: "basic",
|
|
||||||
}, {
|
|
||||||
label: "Perfect",
|
|
||||||
value: "perfect",
|
|
||||||
}, {
|
|
||||||
label: "Modal",
|
|
||||||
value: "modal",
|
|
||||||
}]}
|
|
||||||
handleChange={onTenseCategorySelect}
|
|
||||||
/>
|
|
||||||
</div>}
|
|
||||||
</div>
|
|
||||||
<Select
|
|
||||||
isSearchable={false}
|
|
||||||
// for some reason can't use tOptions with find here;
|
|
||||||
value={verb && ([...tenseOptions, ...perfectTenseOptions].find(o => o.value === verb.tense))}
|
|
||||||
onChange={onTenseSelect}
|
|
||||||
className="mb-2"
|
|
||||||
options={tOptions}
|
|
||||||
{...zIndexProps}
|
|
||||||
/>
|
|
||||||
{verb && <div className="d-flex flex-row justify-content-between align-items-center mt-3 mb-1" style={{ width: "100%" }}>
|
|
||||||
<div onClick={moveTense("back")} className="clickable">
|
|
||||||
<i className="fas fa-chevron-left" />
|
|
||||||
</div>
|
|
||||||
<ButtonSelect
|
|
||||||
small
|
|
||||||
value={verb.negative.toString()}
|
|
||||||
options={[{
|
|
||||||
label: "Pos.",
|
|
||||||
value: "false",
|
|
||||||
}, {
|
|
||||||
label: "Neg.",
|
|
||||||
value: "true",
|
|
||||||
}]}
|
|
||||||
handleChange={onPosNegSelect}
|
|
||||||
/>
|
|
||||||
<div onClick={moveTense("forward")} className="clickable">
|
|
||||||
<i className="fas fa-chevron-right" />
|
|
||||||
</div>
|
|
||||||
</div>}
|
|
||||||
</div>
|
|
||||||
</div>;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default VerbPickerBelow;
|
|
|
@ -4,7 +4,7 @@ import {
|
||||||
import {
|
import {
|
||||||
ButtonSelect,
|
ButtonSelect,
|
||||||
InlinePs,
|
InlinePs,
|
||||||
defaultTextOptions as opts,
|
Types as T,
|
||||||
} from "@lingdocs/pashto-inflector";
|
} from "@lingdocs/pashto-inflector";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { isFemNounEntry, isPattern1Entry, isPattern2Entry, isPattern3Entry, isPattern4Entry, isPattern5Entry, isPattern6FemEntry } from "../../lib/type-predicates";
|
import { isFemNounEntry, isPattern1Entry, isPattern2Entry, isPattern3Entry, isPattern4Entry, isPattern5Entry, isPattern6FemEntry } from "../../lib/type-predicates";
|
||||||
|
@ -57,7 +57,7 @@ function nounFilter(p: FilterPattern | undefined) {
|
||||||
: () => true;
|
: () => true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function NPNounPicker({ onChange, noun, nouns, clearButton }: { nouns: NounEntry[], noun: NounSelection | undefined, onChange: (p: NounSelection | undefined) => void, clearButton?: JSX.Element }) {
|
function NPNounPicker({ onChange, noun, nouns, clearButton, opts }: { nouns: NounEntry[], noun: NounSelection | undefined, onChange: (p: NounSelection | undefined) => void, clearButton?: JSX.Element, opts: T.TextOptions }) {
|
||||||
const [patternFilter, setPatternFilter] = useState<FilterPattern | undefined>(undefined);
|
const [patternFilter, setPatternFilter] = useState<FilterPattern | undefined>(undefined);
|
||||||
const [showFilter, setShowFilter] = useState<boolean>(false)
|
const [showFilter, setShowFilter] = useState<boolean>(false)
|
||||||
const nounsFiltered = nouns
|
const nounsFiltered = nouns
|
||||||
|
@ -101,6 +101,7 @@ function NPNounPicker({ onChange, noun, nouns, clearButton }: { nouns: NounEntry
|
||||||
entries={nounsFiltered}
|
entries={nounsFiltered}
|
||||||
onChange={onEntrySelect}
|
onChange={onEntrySelect}
|
||||||
name="Noun"
|
name="Noun"
|
||||||
|
opts={opts}
|
||||||
/>
|
/>
|
||||||
</div> : <div>
|
</div> : <div>
|
||||||
{noun && <div>
|
{noun && <div>
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
import EntrySelect from "../EntrySelect";
|
import EntrySelect from "../EntrySelect";
|
||||||
|
import {
|
||||||
|
Types as T,
|
||||||
|
} from "@lingdocs/pashto-inflector";
|
||||||
|
|
||||||
function makeParticipleSelection(verb: VerbEntry): ParticipleSelection {
|
function makeParticipleSelection(verb: VerbEntry): ParticipleSelection {
|
||||||
return {
|
return {
|
||||||
|
@ -7,11 +10,12 @@ function makeParticipleSelection(verb: VerbEntry): ParticipleSelection {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function NPParticiplePicker({ onChange, participle, verbs, clearButton }: {
|
function NPParticiplePicker({ onChange, participle, verbs, clearButton, opts }: {
|
||||||
verbs: VerbEntry[],
|
verbs: VerbEntry[],
|
||||||
participle: ParticipleSelection | undefined,
|
participle: ParticipleSelection | undefined,
|
||||||
onChange: (p: ParticipleSelection | undefined) => void,
|
onChange: (p: ParticipleSelection | undefined) => void,
|
||||||
clearButton: JSX.Element,
|
clearButton: JSX.Element,
|
||||||
|
opts: T.TextOptions,
|
||||||
}) {
|
}) {
|
||||||
function onEntrySelect(entry: VerbEntry | undefined) {
|
function onEntrySelect(entry: VerbEntry | undefined) {
|
||||||
if (!entry) {
|
if (!entry) {
|
||||||
|
@ -27,6 +31,7 @@ function NPParticiplePicker({ onChange, participle, verbs, clearButton }: {
|
||||||
entries={verbs}
|
entries={verbs}
|
||||||
onChange={onEntrySelect}
|
onChange={onEntrySelect}
|
||||||
name="Pariticple"
|
name="Pariticple"
|
||||||
|
opts={opts}
|
||||||
/>
|
/>
|
||||||
{participle && <div className="my-2 d-flex flex-row justify-content-around align-items-center">
|
{participle && <div className="my-2 d-flex flex-row justify-content-around align-items-center">
|
||||||
<div>Masc.</div>
|
<div>Masc.</div>
|
||||||
|
|
|
@ -6,15 +6,19 @@ import ParticiplePicker from "./NPParticiplePicker";
|
||||||
import { randomPerson } from "../../lib/np-tools";
|
import { randomPerson } from "../../lib/np-tools";
|
||||||
import { useState, useEffect } from "react";
|
import { useState, useEffect } from "react";
|
||||||
import { nouns, verbs } from "../../words/words";
|
import { nouns, verbs } from "../../words/words";
|
||||||
|
import {
|
||||||
|
Types as T,
|
||||||
|
} from "@lingdocs/pashto-inflector";
|
||||||
// import { capitalizeFirstLetter } from "../../lib/text-tools";
|
// import { capitalizeFirstLetter } from "../../lib/text-tools";
|
||||||
|
|
||||||
const npTypes: NPType[] = ["pronoun", "noun", "participle"];
|
const npTypes: NPType[] = ["pronoun", "noun", "participle"];
|
||||||
|
|
||||||
function NPPicker({ np, onChange, counterPart, asObject }: {
|
function NPPicker({ np, onChange, counterPart, asObject, opts }: {
|
||||||
onChange: (nps: NPSelection | undefined) => void,
|
onChange: (nps: NPSelection | undefined) => void,
|
||||||
np: NPSelection | undefined,
|
np: NPSelection | undefined,
|
||||||
counterPart: NPSelection | VerbObject | undefined,
|
counterPart: NPSelection | VerbObject | undefined,
|
||||||
asObject?: boolean,
|
asObject?: boolean,
|
||||||
|
opts: T.TextOptions,
|
||||||
}) {
|
}) {
|
||||||
const [npType, setNpType] = useState<NPType | undefined>(np ? np.type : undefined);
|
const [npType, setNpType] = useState<NPType | undefined>(np ? np.type : undefined);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
@ -64,6 +68,7 @@ function NPPicker({ np, onChange, counterPart, asObject }: {
|
||||||
pronoun={np}
|
pronoun={np}
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
clearButton={clearButton}
|
clearButton={clearButton}
|
||||||
|
opts={opts}
|
||||||
/>
|
/>
|
||||||
: npType === "noun"
|
: npType === "noun"
|
||||||
? <NounPicker
|
? <NounPicker
|
||||||
|
@ -71,6 +76,7 @@ function NPPicker({ np, onChange, counterPart, asObject }: {
|
||||||
noun={(np && np.type === "noun") ? np : undefined}
|
noun={(np && np.type === "noun") ? np : undefined}
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
clearButton={!isDynamicComplement ? clearButton : undefined}
|
clearButton={!isDynamicComplement ? clearButton : undefined}
|
||||||
|
opts={opts}
|
||||||
/>
|
/>
|
||||||
: npType === "participle"
|
: npType === "participle"
|
||||||
? <ParticiplePicker
|
? <ParticiplePicker
|
||||||
|
@ -78,6 +84,7 @@ function NPPicker({ np, onChange, counterPart, asObject }: {
|
||||||
participle={(np && np.type === "participle") ? np : undefined}
|
participle={(np && np.type === "participle") ? np : undefined}
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
clearButton={clearButton}
|
clearButton={clearButton}
|
||||||
|
opts={opts}
|
||||||
/>
|
/>
|
||||||
: null
|
: null
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,11 +55,12 @@ function pickerStateToPerson(s: PickerState): T.Person {
|
||||||
+ (6 * s.col);
|
+ (6 * s.col);
|
||||||
}
|
}
|
||||||
|
|
||||||
function NPPronounPicker({ onChange, pronoun, asObject, clearButton }: {
|
function NPPronounPicker({ onChange, pronoun, asObject, clearButton, opts }: {
|
||||||
pronoun: PronounSelection,
|
pronoun: PronounSelection,
|
||||||
onChange: (p: PronounSelection) => void,
|
onChange: (p: PronounSelection) => void,
|
||||||
asObject?: boolean,
|
asObject?: boolean,
|
||||||
clearButton?: JSX.Element,
|
clearButton?: JSX.Element,
|
||||||
|
opts: T.TextOptions,
|
||||||
}) {
|
}) {
|
||||||
const [display, setDisplay] = useStickyState<"persons" | "p" | "e">("persons", "prounoun-picker-display");
|
const [display, setDisplay] = useStickyState<"persons" | "p" | "e">("persons", "prounoun-picker-display");
|
||||||
|
|
||||||
|
|
|
@ -1,73 +0,0 @@
|
||||||
import {
|
|
||||||
isPluralNounEntry,
|
|
||||||
isMascNounEntry,
|
|
||||||
isUnisexNounEntry,
|
|
||||||
isVerbEntry,
|
|
||||||
} from "../../lib/type-predicates";
|
|
||||||
import {
|
|
||||||
getEnglishParticiple,
|
|
||||||
getEnglishVerb,
|
|
||||||
} from "../../lib/np-tools";
|
|
||||||
import {
|
|
||||||
getEnglishWord,
|
|
||||||
removeFVarients,
|
|
||||||
Types as T,
|
|
||||||
} from "@lingdocs/pashto-inflector";
|
|
||||||
|
|
||||||
export const zIndexProps = {
|
|
||||||
menuPortalTarget: document.body,
|
|
||||||
styles: { menuPortal: (base: any) => ({ ...base, zIndex: 9999 }) },
|
|
||||||
};
|
|
||||||
|
|
||||||
export function makeVerbSelectOption(e: VerbEntry): { value: string, label: string } {
|
|
||||||
const eng = getEnglishVerb(e.entry);
|
|
||||||
return {
|
|
||||||
label: `${e.entry.p} - ${removeFVarients(e.entry.f)} ${eng ? `(${eng})` : ""}`,
|
|
||||||
value: e.entry.ts.toString(),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function makeSelectOption(e: T.DictionaryEntry | VerbEntry | NounEntry | AdjectiveEntry | LocativeAdverbEntry): { value: string, label: string } {
|
|
||||||
const entry = "entry" in e ? e.entry : e;
|
|
||||||
const eng = (isVerbEntry(e))
|
|
||||||
? (getEnglishParticiple(e.entry))
|
|
||||||
: getEnglishWord(e);
|
|
||||||
const english = typeof eng === "string"
|
|
||||||
? eng
|
|
||||||
: !eng
|
|
||||||
? ""
|
|
||||||
: ("singular" in eng && eng.singular !== undefined)
|
|
||||||
? eng.singular
|
|
||||||
: eng.plural;
|
|
||||||
return {
|
|
||||||
label: `${entry.p} - ${removeFVarients(entry.f)} (${english})`,
|
|
||||||
value: entry.ts.toString(),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function makeNounSelection(entry: NounEntry, dynamicComplement?: true): NounSelection {
|
|
||||||
const number = isPluralNounEntry(entry) ? "plural" : "singular";
|
|
||||||
return {
|
|
||||||
type: "noun",
|
|
||||||
entry,
|
|
||||||
gender: isMascNounEntry(entry) ? "masc" : "fem",
|
|
||||||
number,
|
|
||||||
dynamicComplement,
|
|
||||||
...isUnisexNounEntry(entry) ? {
|
|
||||||
changeGender: function(gender: T.Gender): NounSelection {
|
|
||||||
return {
|
|
||||||
...this,
|
|
||||||
gender,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
} : {},
|
|
||||||
...number === "singular" ? {
|
|
||||||
changeNumber: function(number: NounNumber): NounSelection {
|
|
||||||
return {
|
|
||||||
...this,
|
|
||||||
number,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
} : {},
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -1,17 +1,25 @@
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import NPPicker from "../np-picker/NPPicker";
|
import NPPicker from "../np-picker/NPPicker";
|
||||||
import VerbPicker from "../VerbPicker";
|
import VerbPicker from "../VerbPicker";
|
||||||
import VerbPickerBelow from "../VerbPickerBelow";
|
import TensePicker from "../TensePicker";
|
||||||
import VPDisplay from "./VPDisplay";
|
import VPDisplay from "./VPDisplay";
|
||||||
import { verbs } from "../../words/words";
|
import { verbs } from "../../words/words";
|
||||||
import { renderVP } from "../../lib/phrase-building";
|
import { renderVP } from "../../lib/phrase-building";
|
||||||
import {
|
import {
|
||||||
isInvalidSubjObjCombo,
|
isInvalidSubjObjCombo,
|
||||||
} from "../../lib/np-tools";
|
} from "../../lib/np-tools";
|
||||||
|
import {
|
||||||
|
ButtonSelect,
|
||||||
|
defaultTextOptions,
|
||||||
|
Types as T,
|
||||||
|
} from "@lingdocs/pashto-inflector";
|
||||||
|
import ChartDisplay from "./ChartDisplay";
|
||||||
|
|
||||||
const kingEmoji = "👑";
|
const kingEmoji = "👑";
|
||||||
const servantEmoji = "🙇♂️";
|
const servantEmoji = "🙇♂️";
|
||||||
|
|
||||||
|
// TODO: Drill Down text display options
|
||||||
|
|
||||||
// TODO: SHOW KING AND SERVANT ONCE TENSE PICKED, EVEN IF NPs not selected
|
// TODO: SHOW KING AND SERVANT ONCE TENSE PICKED, EVEN IF NPs not selected
|
||||||
// TODO: Issue with dynamic compounds english making with plurals
|
// TODO: Issue with dynamic compounds english making with plurals
|
||||||
// TODO: Issue with "the money were taken"
|
// TODO: Issue with "the money were taken"
|
||||||
|
@ -22,9 +30,14 @@ const servantEmoji = "🙇♂️";
|
||||||
// TODO: option to show 3 modes Phrases - Charts - Quiz
|
// TODO: option to show 3 modes Phrases - Charts - Quiz
|
||||||
|
|
||||||
// TODO: error handling on error with rendering etc
|
// TODO: error handling on error with rendering etc
|
||||||
export function PhraseBuilder() {
|
export function PhraseBuilder(props: {
|
||||||
|
verb?: VerbEntry,
|
||||||
|
opts?: T.TextOptions,
|
||||||
|
}) {
|
||||||
const [subject, setSubject] = useState<NPSelection | undefined>(undefined);
|
const [subject, setSubject] = useState<NPSelection | undefined>(undefined);
|
||||||
|
const [mode, setMode] = useState<"charts" | "phrases">("phrases");
|
||||||
const [verb, setVerb] = useState<VerbSelection | undefined>(undefined);
|
const [verb, setVerb] = useState<VerbSelection | undefined>(undefined);
|
||||||
|
const textOpts = props.opts || defaultTextOptions;
|
||||||
function handleSubjectChange(subject: NPSelection | undefined, skipPronounConflictCheck?: boolean) {
|
function handleSubjectChange(subject: NPSelection | undefined, skipPronounConflictCheck?: boolean) {
|
||||||
if (!skipPronounConflictCheck && hasPronounConflict(subject, verb?.object)) {
|
if (!skipPronounConflictCheck && hasPronounConflict(subject, verb?.object)) {
|
||||||
alert("That combination of pronouns is not allowed");
|
alert("That combination of pronouns is not allowed");
|
||||||
|
@ -61,7 +74,18 @@ export function PhraseBuilder() {
|
||||||
subject={subject}
|
subject={subject}
|
||||||
changeSubject={(s) => handleSubjectChange(s, true)}
|
changeSubject={(s) => handleSubjectChange(s, true)}
|
||||||
onChange={setVerb}
|
onChange={setVerb}
|
||||||
|
opts={textOpts}
|
||||||
/>
|
/>
|
||||||
|
<div className="text-right mb-2">
|
||||||
|
<ButtonSelect
|
||||||
|
value={mode}
|
||||||
|
options={[
|
||||||
|
{ label: "Charts", value: "charts" },
|
||||||
|
{ label: "Phrases", value: "phrases" },
|
||||||
|
]}
|
||||||
|
handleChange={setMode}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
{(verb && (typeof verb.object === "object") && (verb.isCompound !== "dynamic")) &&
|
{(verb && (typeof verb.object === "object") && (verb.isCompound !== "dynamic")) &&
|
||||||
<div className="text-center mt-4">
|
<div className="text-center mt-4">
|
||||||
<button onClick={handleSubjObjSwap} className="btn btn-sm btn-light">
|
<button onClick={handleSubjObjSwap} className="btn btn-sm btn-light">
|
||||||
|
@ -69,36 +93,42 @@ export function PhraseBuilder() {
|
||||||
</button>
|
</button>
|
||||||
</div>}
|
</div>}
|
||||||
<div className="d-flex flex-row justify-content-around flex-wrap" style={{ marginLeft: "-0.5rem", marginRight: "-0.5rem" }}>
|
<div className="d-flex flex-row justify-content-around flex-wrap" style={{ marginLeft: "-0.5rem", marginRight: "-0.5rem" }}>
|
||||||
|
{mode !== "charts" && <>
|
||||||
|
<div className="my-2">
|
||||||
|
<div className="h5 text-center">Subject {showRole(VPRendered, "subject")}</div>
|
||||||
|
<NPPicker
|
||||||
|
np={subject}
|
||||||
|
counterPart={verb ? verb.object : undefined}
|
||||||
|
onChange={handleSubjectChange}
|
||||||
|
opts={textOpts}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
{verb && (verb.object !== "none") && <div className="my-2">
|
||||||
|
<div className="h5 text-center">Object {showRole(VPRendered, "object")}</div>
|
||||||
|
{(typeof verb.object === "number")
|
||||||
|
? <div className="text-muted">Unspoken 3rd Pers. Masc. Plur.</div>
|
||||||
|
: <NPPicker
|
||||||
|
asObject
|
||||||
|
np={verb.object}
|
||||||
|
counterPart={subject}
|
||||||
|
onChange={handleObjectChange}
|
||||||
|
opts={textOpts}
|
||||||
|
/>}
|
||||||
|
</div>}
|
||||||
|
</>}
|
||||||
<div className="my-2">
|
<div className="my-2">
|
||||||
<div className="h5 text-center">Subject {showRole(VPRendered, "subject")}</div>
|
<TensePicker
|
||||||
<NPPicker
|
|
||||||
np={subject}
|
|
||||||
counterPart={verb ? verb.object : undefined}
|
|
||||||
onChange={handleSubjectChange}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
{verb && (verb.object !== "none") && <div className="my-2">
|
|
||||||
<div className="h5 text-center">Object {showRole(VPRendered, "object")}</div>
|
|
||||||
{(typeof verb.object === "number")
|
|
||||||
? <div className="text-muted">Unspoken 3rd Pers. Masc. Plur.</div>
|
|
||||||
: <NPPicker
|
|
||||||
asObject
|
|
||||||
np={verb.object}
|
|
||||||
counterPart={subject}
|
|
||||||
onChange={handleObjectChange}
|
|
||||||
/>}
|
|
||||||
</div>}
|
|
||||||
<div className="my-2">
|
|
||||||
<VerbPickerBelow
|
|
||||||
verbs={verbs}
|
verbs={verbs}
|
||||||
verb={verb}
|
verb={verb}
|
||||||
onChange={setVerb}
|
onChange={setVerb}
|
||||||
|
mode={mode}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{verbPhrase && <div>
|
{(verbPhrase && (mode === "phrases")) &&
|
||||||
<VPDisplay VP={verbPhrase} />
|
<VPDisplay VP={verbPhrase} opts={textOpts} />
|
||||||
</div>}
|
}
|
||||||
|
{(verb && (mode === "charts")) && <ChartDisplay VS={verb} opts={textOpts} />}
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,13 +2,12 @@ import { useState } from "react";
|
||||||
import { renderVP, compileVP } from "../../lib/phrase-building";
|
import { renderVP, compileVP } from "../../lib/phrase-building";
|
||||||
import {
|
import {
|
||||||
InlinePs,
|
InlinePs,
|
||||||
defaultTextOptions as opts,
|
|
||||||
Types as T,
|
Types as T,
|
||||||
} from "@lingdocs/pashto-inflector";
|
} from "@lingdocs/pashto-inflector";
|
||||||
import AbbreviationFormSelector from "./AbbreviationFormSelector";
|
import AbbreviationFormSelector from "./AbbreviationFormSelector";
|
||||||
import { isPastTense } from "../../lib/phrase-building/vp-tools";
|
import { isPastTense } from "../../lib/phrase-building/vp-tools";
|
||||||
|
|
||||||
function VPDisplay({ VP }: { VP: VPSelection }) {
|
function VPDisplay({ VP, opts }: { VP: VPSelection, opts: T.TextOptions }) {
|
||||||
const [form, setForm] = useState<FormVersion>({ removeKing: false, shrinkServant: false });
|
const [form, setForm] = useState<FormVersion>({ removeKing: false, shrinkServant: false });
|
||||||
const [OSV, setOSV] = useState<boolean>(false);
|
const [OSV, setOSV] = useState<boolean>(false);
|
||||||
const result = compileVP(renderVP(VP), { ...form, OSV });
|
const result = compileVP(renderVP(VP), { ...form, OSV });
|
||||||
|
@ -33,15 +32,15 @@ function VPDisplay({ VP }: { VP: VPSelection }) {
|
||||||
{"long" in result.ps ?
|
{"long" in result.ps ?
|
||||||
<div>
|
<div>
|
||||||
{/* <div className="h6">Long Verb:</div> */}
|
{/* <div className="h6">Long Verb:</div> */}
|
||||||
<VariationLayer vs={result.ps.long} />
|
<VariationLayer vs={result.ps.long} opts={opts} />
|
||||||
{/* <div className="h6">Short Verb:</div> */}
|
{/* <div className="h6">Short Verb:</div> */}
|
||||||
<VariationLayer vs={result.ps.short} />
|
<VariationLayer vs={result.ps.short} opts={opts} />
|
||||||
{result.ps.mini && <>
|
{result.ps.mini && <>
|
||||||
{/* <div className="h6">Mini Verb:</div> */}
|
{/* <div className="h6">Mini Verb:</div> */}
|
||||||
<VariationLayer vs={result.ps.mini} />
|
<VariationLayer vs={result.ps.mini} opts={opts} />
|
||||||
</>}
|
</>}
|
||||||
</div>
|
</div>
|
||||||
: <VariationLayer vs={result.ps} />
|
: <VariationLayer vs={result.ps} opts={opts} />
|
||||||
}
|
}
|
||||||
{result.e && <div className="text-muted">
|
{result.e && <div className="text-muted">
|
||||||
{result.e.map((e, i) => <div key={i}>{e}</div>)}
|
{result.e.map((e, i) => <div key={i}>{e}</div>)}
|
||||||
|
@ -63,7 +62,7 @@ function whatsAdjustable(VP: VPSelection): "both" | "king" | "servant" {
|
||||||
: "king";
|
: "king";
|
||||||
}
|
}
|
||||||
|
|
||||||
function VariationLayer({ vs }: { vs: T.PsString[] }) {
|
function VariationLayer({ vs, opts }: { vs: T.PsString[], opts: T.TextOptions }) {
|
||||||
return <div className="mb-2">
|
return <div className="mb-2">
|
||||||
{vs.map((r, i) => <div key={i}>
|
{vs.map((r, i) => <div key={i}>
|
||||||
<InlinePs opts={opts}>{r}</InlinePs>
|
<InlinePs opts={opts}>{r}</InlinePs>
|
||||||
|
|
|
@ -20,6 +20,7 @@ import {
|
||||||
removeBa,
|
removeBa,
|
||||||
isPastTense,
|
isPastTense,
|
||||||
isPerfectTense,
|
isPerfectTense,
|
||||||
|
getTenseVerbForm,
|
||||||
} from "./vp-tools";
|
} from "./vp-tools";
|
||||||
import { isPattern4Entry } from "../type-predicates";
|
import { isPattern4Entry } from "../type-predicates";
|
||||||
import { renderEnglishVPBase } from "./english-vp-rendering";
|
import { renderEnglishVPBase } from "./english-vp-rendering";
|
||||||
|
@ -254,84 +255,6 @@ function getMatrixBlock<U>(f: {
|
||||||
return f[personToLabel(person)];
|
return f[personToLabel(person)];
|
||||||
}
|
}
|
||||||
|
|
||||||
function getTenseVerbForm(conjR: T.VerbConjugation, tense: VerbTense | PerfectTense, tenseCategory: "basic" | "modal" | "perfect", voice: "active" | "passive"): T.VerbForm {
|
|
||||||
const conj = (voice === "passive" && conjR.passive) ? conjR.passive : conjR;
|
|
||||||
if (tenseCategory === "basic") {
|
|
||||||
if (tense === "presentVerb") {
|
|
||||||
return conj.imperfective.nonImperative;
|
|
||||||
}
|
|
||||||
if (tense === "subjunctiveVerb") {
|
|
||||||
return conj.perfective.nonImperative;
|
|
||||||
}
|
|
||||||
if (tense === "imperfectiveFuture") {
|
|
||||||
return conj.imperfective.future;
|
|
||||||
}
|
|
||||||
if (tense === "perfectiveFuture") {
|
|
||||||
return conj.perfective.future;
|
|
||||||
}
|
|
||||||
if (tense === "imperfectivePast") {
|
|
||||||
return conj.imperfective.past;
|
|
||||||
}
|
|
||||||
if (tense === "perfectivePast") {
|
|
||||||
return conj.perfective.past;
|
|
||||||
}
|
|
||||||
if (tense === "habitualImperfectivePast") {
|
|
||||||
return conj.imperfective.habitualPast;
|
|
||||||
}
|
|
||||||
if (tense === "habitualPerfectivePast") {
|
|
||||||
return conj.perfective.habitualPast;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (tenseCategory === "modal") {
|
|
||||||
if (tense === "presentVerb") {
|
|
||||||
return conj.imperfective.modal.nonImperative;
|
|
||||||
}
|
|
||||||
if (tense === "subjunctiveVerb") {
|
|
||||||
return conj.perfective.modal.nonImperative;
|
|
||||||
}
|
|
||||||
if (tense === "imperfectiveFuture") {
|
|
||||||
return conj.imperfective.modal.future;
|
|
||||||
}
|
|
||||||
if (tense === "perfectiveFuture") {
|
|
||||||
return conj.perfective.modal.future;
|
|
||||||
}
|
|
||||||
if (tense === "imperfectivePast") {
|
|
||||||
return conj.imperfective.modal.past;
|
|
||||||
}
|
|
||||||
if (tense === "perfectivePast") {
|
|
||||||
return conj.perfective.modal.past;
|
|
||||||
}
|
|
||||||
if (tense === "habitualImperfectivePast") {
|
|
||||||
return conj.imperfective.modal.habitualPast;
|
|
||||||
}
|
|
||||||
if (tense === "habitualPerfectivePast") {
|
|
||||||
return conj.perfective.modal.habitualPast;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (tense === "present perfect") {
|
|
||||||
return conj.perfect.present;
|
|
||||||
}
|
|
||||||
if (tense === "past perfect") {
|
|
||||||
return conj.perfect.past;
|
|
||||||
}
|
|
||||||
if (tense === "future perfect") {
|
|
||||||
return conj.perfect.future;
|
|
||||||
}
|
|
||||||
if (tense === "habitual perfect") {
|
|
||||||
return conj.perfect.habitual;
|
|
||||||
}
|
|
||||||
if (tense === "subjunctive perfect") {
|
|
||||||
return conj.perfect.subjunctive;
|
|
||||||
}
|
|
||||||
if (tense === "wouldBe perfect") {
|
|
||||||
return conj.perfect.affirmational;
|
|
||||||
}
|
|
||||||
if (tense === "pastSubjunctive perfect") {
|
|
||||||
return conj.perfect.pastSubjunctiveHypothetical;
|
|
||||||
}
|
|
||||||
throw new Error("unknown tense");
|
|
||||||
}
|
|
||||||
|
|
||||||
function getEnglishParticiple(entry: T.DictionaryEntry): string {
|
function getEnglishParticiple(entry: T.DictionaryEntry): string {
|
||||||
if (!entry.ec) {
|
if (!entry.ec) {
|
||||||
console.log("errored participle");
|
console.log("errored participle");
|
||||||
|
|
|
@ -6,6 +6,85 @@ import {
|
||||||
} from "@lingdocs/pashto-inflector";
|
} from "@lingdocs/pashto-inflector";
|
||||||
import { psStringEquals } from "@lingdocs/pashto-inflector/dist/lib/p-text-helpers";
|
import { psStringEquals } from "@lingdocs/pashto-inflector/dist/lib/p-text-helpers";
|
||||||
|
|
||||||
|
export function getTenseVerbForm(conjR: T.VerbConjugation, tense: VerbTense | PerfectTense, tenseCategory: "basic" | "modal" | "perfect", voice: "active" | "passive"): T.VerbForm {
|
||||||
|
const conj = (voice === "passive" && conjR.passive) ? conjR.passive : conjR;
|
||||||
|
if (tenseCategory === "basic") {
|
||||||
|
if (tense === "presentVerb") {
|
||||||
|
return conj.imperfective.nonImperative;
|
||||||
|
}
|
||||||
|
if (tense === "subjunctiveVerb") {
|
||||||
|
return conj.perfective.nonImperative;
|
||||||
|
}
|
||||||
|
if (tense === "imperfectiveFuture") {
|
||||||
|
return conj.imperfective.future;
|
||||||
|
}
|
||||||
|
if (tense === "perfectiveFuture") {
|
||||||
|
return conj.perfective.future;
|
||||||
|
}
|
||||||
|
if (tense === "imperfectivePast") {
|
||||||
|
return conj.imperfective.past;
|
||||||
|
}
|
||||||
|
if (tense === "perfectivePast") {
|
||||||
|
return conj.perfective.past;
|
||||||
|
}
|
||||||
|
if (tense === "habitualImperfectivePast") {
|
||||||
|
return conj.imperfective.habitualPast;
|
||||||
|
}
|
||||||
|
if (tense === "habitualPerfectivePast") {
|
||||||
|
return conj.perfective.habitualPast;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (tenseCategory === "modal") {
|
||||||
|
if (tense === "presentVerb") {
|
||||||
|
return conj.imperfective.modal.nonImperative;
|
||||||
|
}
|
||||||
|
if (tense === "subjunctiveVerb") {
|
||||||
|
return conj.perfective.modal.nonImperative;
|
||||||
|
}
|
||||||
|
if (tense === "imperfectiveFuture") {
|
||||||
|
return conj.imperfective.modal.future;
|
||||||
|
}
|
||||||
|
if (tense === "perfectiveFuture") {
|
||||||
|
return conj.perfective.modal.future;
|
||||||
|
}
|
||||||
|
if (tense === "imperfectivePast") {
|
||||||
|
return conj.imperfective.modal.past;
|
||||||
|
}
|
||||||
|
if (tense === "perfectivePast") {
|
||||||
|
return conj.perfective.modal.past;
|
||||||
|
}
|
||||||
|
if (tense === "habitualImperfectivePast") {
|
||||||
|
return conj.imperfective.modal.habitualPast;
|
||||||
|
}
|
||||||
|
if (tense === "habitualPerfectivePast") {
|
||||||
|
return conj.perfective.modal.habitualPast;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (tense === "present perfect") {
|
||||||
|
return conj.perfect.present;
|
||||||
|
}
|
||||||
|
if (tense === "past perfect") {
|
||||||
|
return conj.perfect.past;
|
||||||
|
}
|
||||||
|
if (tense === "future perfect") {
|
||||||
|
return conj.perfect.future;
|
||||||
|
}
|
||||||
|
if (tense === "habitual perfect") {
|
||||||
|
return conj.perfect.habitual;
|
||||||
|
}
|
||||||
|
if (tense === "subjunctive perfect") {
|
||||||
|
return conj.perfect.subjunctive;
|
||||||
|
}
|
||||||
|
if (tense === "wouldBe perfect") {
|
||||||
|
return conj.perfect.affirmational;
|
||||||
|
}
|
||||||
|
if (tense === "pastSubjunctive perfect") {
|
||||||
|
return conj.perfect.pastSubjunctiveHypothetical;
|
||||||
|
}
|
||||||
|
throw new Error("unknown tense");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
export function getPersonFromNP(np: NPSelection): T.Person;
|
export function getPersonFromNP(np: NPSelection): T.Person;
|
||||||
export function getPersonFromNP(np: NPSelection | ObjectNP): T.Person | undefined;
|
export function getPersonFromNP(np: NPSelection | ObjectNP): T.Person | undefined;
|
||||||
export function getPersonFromNP(np: NPSelection | ObjectNP): T.Person | undefined {
|
export function getPersonFromNP(np: NPSelection | ObjectNP): T.Person | undefined {
|
||||||
|
|
Loading…
Reference in New Issue