towards new verb explorer form
This commit is contained in:
parent
0467080343
commit
9f9236ba9b
|
@ -5,7 +5,7 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@fortawesome/fontawesome-free": "^5.15.4",
|
"@fortawesome/fontawesome-free": "^5.15.4",
|
||||||
"@lingdocs/lingdocs-main": "^0.2.0",
|
"@lingdocs/lingdocs-main": "^0.2.0",
|
||||||
"@lingdocs/pashto-inflector": "^1.6.8",
|
"@lingdocs/pashto-inflector": "^1.6.9",
|
||||||
"@testing-library/jest-dom": "^5.11.4",
|
"@testing-library/jest-dom": "^5.11.4",
|
||||||
"@testing-library/react": "^11.1.0",
|
"@testing-library/react": "^11.1.0",
|
||||||
"@testing-library/user-event": "^12.1.10",
|
"@testing-library/user-event": "^12.1.10",
|
||||||
|
|
|
@ -1,73 +1,12 @@
|
||||||
import Select from "react-select";
|
|
||||||
import {
|
import {
|
||||||
makeNounSelection,
|
|
||||||
zIndexProps,
|
|
||||||
} from "./np-picker/picker-tools";
|
|
||||||
import {
|
|
||||||
Types as T,
|
|
||||||
ButtonSelect,
|
ButtonSelect,
|
||||||
getVerbInfo,
|
|
||||||
} from "@lingdocs/pashto-inflector";
|
} from "@lingdocs/pashto-inflector";
|
||||||
import { isPerfectTense } from "../lib/phrase-building/vp-tools";
|
import {
|
||||||
|
makeVerbSelection,
|
||||||
|
} from "./phrase-builder/verb-selection";
|
||||||
import EntrySelect from "./EntrySelect";
|
import EntrySelect from "./EntrySelect";
|
||||||
// import { useState } from "react";
|
|
||||||
|
|
||||||
const tenseOptions: { label: string | JSX.Element, value: VerbTense }[] = [{
|
// TODO: dark on past tense selecitons
|
||||||
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",
|
|
||||||
}];
|
|
||||||
|
|
||||||
// type Filters = {
|
|
||||||
// stative: boolean,
|
|
||||||
// dynamic: boolean,
|
|
||||||
// transitive: boolean,
|
|
||||||
// intransitive: boolean,
|
|
||||||
// grammaticallyTransitive: boolean,
|
|
||||||
// }
|
|
||||||
|
|
||||||
function VerbPicker({ onChange, subject, changeSubject, verb, verbs }: {
|
function VerbPicker({ onChange, subject, changeSubject, verb, verbs }: {
|
||||||
verbs: VerbEntry[],
|
verbs: VerbEntry[],
|
||||||
|
@ -90,65 +29,6 @@ function VerbPicker({ onChange, subject, changeSubject, verb, verbs }: {
|
||||||
}
|
}
|
||||||
onChange(makeVerbSelection(v, changeSubject, verb));
|
onChange(makeVerbSelection(v, changeSubject, verb));
|
||||||
}
|
}
|
||||||
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,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
function onVoiceSelect(value: "active" | "passive") {
|
function onVoiceSelect(value: "active" | "passive") {
|
||||||
if (verb && verb.changeVoice) {
|
if (verb && verb.changeVoice) {
|
||||||
if (value === "passive" && (typeof verb.object === "object")) {
|
if (value === "passive" && (typeof verb.object === "object")) {
|
||||||
|
@ -173,218 +53,63 @@ function VerbPicker({ onChange, subject, changeSubject, verb, verbs }: {
|
||||||
onChange(verb.changeStatDyn(c));
|
onChange(verb.changeStatDyn(c));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const tOptions = (verb?.tenseCategory === "perfect") ? perfectTenseOptions : tenseOptions;
|
return <div className="mb-3">
|
||||||
return <div style={{ maxWidth: "225px", minWidth: "175px" }}>
|
<div style={{ maxWidth: "300px", margin: "0 auto" }}>
|
||||||
<div>Verb:</div>
|
<div>Verb:</div>
|
||||||
<EntrySelect
|
<EntrySelect
|
||||||
entries={verbs}
|
entries={verbs}
|
||||||
value={verb?.verb}
|
value={verb?.verb}
|
||||||
onChange={onVerbSelect}
|
onChange={onVerbSelect}
|
||||||
name="Verb"
|
name="Verb"
|
||||||
isVerbSelect
|
isVerbSelect
|
||||||
/>
|
|
||||||
{/* <Select
|
|
||||||
value={verb && verb.verb.entry.ts.toString()}
|
|
||||||
// @ts-ignore
|
|
||||||
onChange={onEntrySelect}
|
|
||||||
className="mb-2"
|
|
||||||
// @ts-ignore
|
|
||||||
options={options}
|
|
||||||
isSearchable
|
|
||||||
// // @ts-ignore
|
|
||||||
placeholder={verb ? options.find(o => o.value === (verb.verb.entry).ts.toString())?.label : "Select Verb..."}
|
|
||||||
{...zIndexProps}
|
|
||||||
/> */}
|
|
||||||
{verb && verb.changeTransitivity && <div className="text-center mt-3">
|
|
||||||
<ButtonSelect
|
|
||||||
small
|
|
||||||
options={[{
|
|
||||||
label: "gramm. trans.",
|
|
||||||
value: "grammatically transitive",
|
|
||||||
}, {
|
|
||||||
label: "trans.",
|
|
||||||
value: "transitive",
|
|
||||||
}]}
|
|
||||||
value={notInstransitive(verb.transitivity)}
|
|
||||||
handleChange={handleChangeTransitivity}
|
|
||||||
/>
|
/>
|
||||||
</div>}
|
</div>
|
||||||
{verb && <div className="col text-center my-3">
|
<div className="d-flex flex-row justify-content-around flex-wrap" style={{ maxWidth: "400px", margin: "0 auto" }}>
|
||||||
<ButtonSelect
|
{verb && verb.changeTransitivity && <div className="text-center my-2">
|
||||||
small
|
<ButtonSelect
|
||||||
value={verb.tenseCategory}
|
small
|
||||||
options={[{
|
options={[{
|
||||||
label: "Basic",
|
label: "gramm. trans.",
|
||||||
value: "basic",
|
value: "grammatically transitive",
|
||||||
}, {
|
}, {
|
||||||
label: "Perfect",
|
label: "trans.",
|
||||||
value: "perfect",
|
value: "transitive",
|
||||||
}, {
|
}]}
|
||||||
label: "Modal",
|
value={notInstransitive(verb.transitivity)}
|
||||||
value: "modal",
|
handleChange={handleChangeTransitivity}
|
||||||
}]}
|
/>
|
||||||
handleChange={onTenseCategorySelect}
|
</div>}
|
||||||
/>
|
{verb && verb.changeVoice && <div className="text-center my-2">
|
||||||
</div>}
|
<ButtonSelect
|
||||||
{verb && verb.changeVoice && <div className="col text-center my-3">
|
small
|
||||||
<ButtonSelect
|
value={verb.voice}
|
||||||
small
|
options={[{
|
||||||
value={verb.voice}
|
label: "Active",
|
||||||
options={[{
|
value: "active",
|
||||||
label: "Active",
|
}, {
|
||||||
value: "active",
|
label: "Passive",
|
||||||
}, {
|
value: "passive",
|
||||||
label: "Passive",
|
}]}
|
||||||
value: "passive",
|
handleChange={onVoiceSelect}
|
||||||
}]}
|
/>
|
||||||
handleChange={onVoiceSelect}
|
</div>}
|
||||||
/>
|
{verb && verb.changeStatDyn && <div className="text-center my-2">
|
||||||
</div>}
|
<ButtonSelect
|
||||||
<div>Tense:</div>
|
small
|
||||||
<Select
|
options={[{
|
||||||
isSearchable={false}
|
label: "stative",
|
||||||
// for some reason can't use tOptions with find here;
|
value: "stative",
|
||||||
value={verb && ([...tenseOptions, ...perfectTenseOptions].find(o => o.value === verb.tense))}
|
}, {
|
||||||
onChange={onTenseSelect}
|
label: "dynamic",
|
||||||
className="mb-2"
|
value: "dynamic",
|
||||||
options={tOptions}
|
}]}
|
||||||
{...zIndexProps}
|
value={verb.isCompound ? verb.isCompound : "stative"}
|
||||||
/>
|
handleChange={handleChangeStatDyn}
|
||||||
{verb && verb.changeStatDyn && <div className="text-center">
|
/>
|
||||||
<ButtonSelect
|
</div>}
|
||||||
small
|
</div>
|
||||||
options={[{
|
|
||||||
label: "stative",
|
|
||||||
value: "stative",
|
|
||||||
}, {
|
|
||||||
label: "dynamic",
|
|
||||||
value: "dynamic",
|
|
||||||
}]}
|
|
||||||
value={verb.isCompound ? verb.isCompound : "stative"}
|
|
||||||
handleChange={handleChangeStatDyn}
|
|
||||||
/>
|
|
||||||
</div>}
|
|
||||||
{verb && <div className="d-flex flex-row justify-content-between align-items-center my-3" 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>;
|
||||||
}
|
}
|
||||||
|
|
||||||
function makeVerbSelection(verb: VerbEntry, changeSubject: (s: NPSelection | undefined) => void, oldVerbSelection?: VerbSelection): VerbSelection {
|
|
||||||
const info = getVerbInfo(verb.entry, verb.complement);
|
|
||||||
function getTransObjFromOldVerbSelection() {
|
|
||||||
if (
|
|
||||||
!oldVerbSelection ||
|
|
||||||
oldVerbSelection.object === "none" ||
|
|
||||||
typeof oldVerbSelection.object === "number" ||
|
|
||||||
oldVerbSelection.isCompound === "dynamic" ||
|
|
||||||
(oldVerbSelection.object?.type === "noun" && oldVerbSelection.object.dynamicComplement)
|
|
||||||
) return undefined;
|
|
||||||
return oldVerbSelection.object;
|
|
||||||
}
|
|
||||||
const transitivity: T.Transitivity = "grammaticallyTransitive" in info
|
|
||||||
? "transitive"
|
|
||||||
: info.transitivity;
|
|
||||||
const object = (transitivity === "grammatically transitive")
|
|
||||||
? T.Person.ThirdPlurMale
|
|
||||||
: (info.type === "dynamic compound" && oldVerbSelection?.voice !== "passive")
|
|
||||||
? makeNounSelection(info.objComplement.entry as NounEntry, true)
|
|
||||||
: (transitivity === "transitive" && oldVerbSelection?.voice !== "passive")
|
|
||||||
? getTransObjFromOldVerbSelection()
|
|
||||||
: "none";
|
|
||||||
if (oldVerbSelection?.voice === "passive" && info.type === "dynamic compound") {
|
|
||||||
changeSubject(makeNounSelection(info.objComplement.entry as NounEntry, true));
|
|
||||||
}
|
|
||||||
const isCompound = ("stative" in info || info.type === "stative compound")
|
|
||||||
? "stative"
|
|
||||||
: info.type === "dynamic compound"
|
|
||||||
? "dynamic"
|
|
||||||
: false;
|
|
||||||
// TODO: here and below in the changeStatDyn function ... allow for entries with complement
|
|
||||||
const dynAuxVerb: VerbEntry | undefined = isCompound !== "dynamic"
|
|
||||||
? undefined
|
|
||||||
: info.type === "dynamic compound"
|
|
||||||
? { entry: info.auxVerb } as VerbEntry
|
|
||||||
: "dynamic" in info
|
|
||||||
? { entry: info.dynamic.auxVerb } as VerbEntry
|
|
||||||
: undefined;
|
|
||||||
const tenseSelection = ((): { tenseCategory: "perfect", tense: PerfectTense } | {
|
|
||||||
tenseCategory: "basic" | "modal",
|
|
||||||
tense: VerbTense,
|
|
||||||
} => {
|
|
||||||
if (!oldVerbSelection) {
|
|
||||||
return { tense: "presentVerb", tenseCategory: "basic" };
|
|
||||||
}
|
|
||||||
if (oldVerbSelection.tenseCategory === "modal") {
|
|
||||||
return { tenseCategory: "modal", tense: isPerfectTense(oldVerbSelection.tense) ? "presentVerb" : oldVerbSelection.tense };
|
|
||||||
}
|
|
||||||
if (oldVerbSelection.tenseCategory === "basic") {
|
|
||||||
return { tenseCategory: "basic", tense: isPerfectTense(oldVerbSelection.tense) ? "presentVerb" : oldVerbSelection.tense };
|
|
||||||
}
|
|
||||||
return { tenseCategory: "perfect", tense: isPerfectTense(oldVerbSelection.tense) ? oldVerbSelection.tense : "present perfect" };
|
|
||||||
})();
|
|
||||||
return {
|
|
||||||
type: "verb",
|
|
||||||
verb: verb,
|
|
||||||
dynAuxVerb,
|
|
||||||
...tenseSelection,
|
|
||||||
object,
|
|
||||||
transitivity,
|
|
||||||
isCompound,
|
|
||||||
voice: transitivity === "transitive"
|
|
||||||
? (oldVerbSelection?.voice || "active")
|
|
||||||
: "active",
|
|
||||||
negative: oldVerbSelection ? oldVerbSelection.negative : false,
|
|
||||||
...("grammaticallyTransitive" in info) ? {
|
|
||||||
changeTransitivity: function(t) {
|
|
||||||
return {
|
|
||||||
...this,
|
|
||||||
transitivity: t,
|
|
||||||
object: t === "grammatically transitive" ? T.Person.ThirdPlurMale : undefined,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
} : {},
|
|
||||||
...("stative" in info) ? {
|
|
||||||
changeStatDyn: function(c) {
|
|
||||||
return {
|
|
||||||
...this,
|
|
||||||
isCompound: c,
|
|
||||||
object: c === "dynamic"
|
|
||||||
? makeNounSelection(info.dynamic.objComplement.entry as NounEntry, true)
|
|
||||||
: undefined,
|
|
||||||
dynAuxVerb: c === "dynamic"
|
|
||||||
? { entry: info.dynamic.auxVerb } as VerbEntry
|
|
||||||
: undefined,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
} : {},
|
|
||||||
...(transitivity === "transitive") ? {
|
|
||||||
changeVoice: function(v, s) {
|
|
||||||
return {
|
|
||||||
...this,
|
|
||||||
voice: v,
|
|
||||||
object: v === "active" ? s : "none",
|
|
||||||
};
|
|
||||||
},
|
|
||||||
} : {},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export default VerbPicker;
|
export default VerbPicker;
|
|
@ -0,0 +1,177 @@
|
||||||
|
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-4 mt-3">
|
||||||
|
{verb && <div className="col text-center mb-2">
|
||||||
|
<ButtonSelect
|
||||||
|
small
|
||||||
|
value={verb.tenseCategory}
|
||||||
|
options={[{
|
||||||
|
label: "Basic",
|
||||||
|
value: "basic",
|
||||||
|
}, {
|
||||||
|
label: "Perfect",
|
||||||
|
value: "perfect",
|
||||||
|
}, {
|
||||||
|
label: "Modal",
|
||||||
|
value: "modal",
|
||||||
|
}]}
|
||||||
|
handleChange={onTenseCategorySelect}
|
||||||
|
/>
|
||||||
|
</div>}
|
||||||
|
<div style={{ maxWidth: "300px", margin: "0 auto" }}>
|
||||||
|
<div>Tense:</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 my-3" 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;
|
|
@ -1,6 +1,7 @@
|
||||||
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 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";
|
||||||
|
@ -47,13 +48,20 @@ export function PhraseBuilder() {
|
||||||
<div>{kingEmoji} = <abbr title="controls the verb conjugation, can be removed">king</abbr> of phrase</div>
|
<div>{kingEmoji} = <abbr title="controls the verb conjugation, can be removed">king</abbr> of phrase</div>
|
||||||
<div>{servantEmoji} = <abbr title="can be shrunken into a mini-pronoun">servant</abbr> of phrase</div>
|
<div>{servantEmoji} = <abbr title="can be shrunken into a mini-pronoun">servant</abbr> of phrase</div>
|
||||||
</div>
|
</div>
|
||||||
|
<VerbPicker
|
||||||
|
verbs={verbs}
|
||||||
|
verb={verb}
|
||||||
|
subject={subject}
|
||||||
|
changeSubject={(s) => handleSubjectChange(s, true)}
|
||||||
|
onChange={setVerb}
|
||||||
|
/>
|
||||||
{(verb && (typeof verb.object === "object") && (verb.isCompound !== "dynamic")) &&
|
{(verb && (typeof verb.object === "object") && (verb.isCompound !== "dynamic")) &&
|
||||||
<div className="d-flex flex-row justify-content-around flex-wrap mb-2">
|
<div className="d-flex flex-row justify-content-around flex-wrap mt-4">
|
||||||
<button onClick={handleSubjObjSwap} className="btn btn-sm btn-light">
|
<button onClick={handleSubjObjSwap} className="btn btn-sm btn-light">
|
||||||
<i className="fas fa-exchange-alt mr-2" /> subj/obj
|
<i className="fas fa-exchange-alt mr-2" /> subj/obj
|
||||||
</button>
|
</button>
|
||||||
<div>{` `}</div>
|
{/* <div>{` `}</div> */}
|
||||||
</div>}
|
</div>}
|
||||||
<div className="d-flex flex-row justify-content-around flex-wrap">
|
<div className="d-flex flex-row justify-content-around flex-wrap">
|
||||||
<div className="my-2">
|
<div className="my-2">
|
||||||
<div className="h4">Subject {showRole(VPRendered, "subject")}</div>
|
<div className="h4">Subject {showRole(VPRendered, "subject")}</div>
|
||||||
|
@ -74,17 +82,12 @@ export function PhraseBuilder() {
|
||||||
onChange={handleObjectChange}
|
onChange={handleObjectChange}
|
||||||
/>}
|
/>}
|
||||||
</div>}
|
</div>}
|
||||||
<div className="my-2">
|
|
||||||
<div className="h4">Verb</div>
|
|
||||||
<VerbPicker
|
|
||||||
verbs={verbs}
|
|
||||||
verb={verb}
|
|
||||||
subject={subject}
|
|
||||||
changeSubject={(s) => handleSubjectChange(s, true)}
|
|
||||||
onChange={setVerb}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
<VerbPickerBelow
|
||||||
|
verbs={verbs}
|
||||||
|
verb={verb}
|
||||||
|
onChange={setVerb}
|
||||||
|
/>
|
||||||
{verbPhrase && <div>
|
{verbPhrase && <div>
|
||||||
<VPDisplay VP={verbPhrase} />
|
<VPDisplay VP={verbPhrase} />
|
||||||
</div>}
|
</div>}
|
||||||
|
|
|
@ -0,0 +1,108 @@
|
||||||
|
import {
|
||||||
|
makeNounSelection,
|
||||||
|
} from "../np-picker/picker-tools";
|
||||||
|
import {
|
||||||
|
getVerbInfo,
|
||||||
|
Types as T,
|
||||||
|
} from "@lingdocs/pashto-inflector";
|
||||||
|
import { isPerfectTense } from "../../lib/phrase-building/vp-tools";
|
||||||
|
|
||||||
|
export function makeVerbSelection(verb: VerbEntry, changeSubject: (s: NPSelection | undefined) => void, oldVerbSelection?: VerbSelection): VerbSelection {
|
||||||
|
const info = getVerbInfo(verb.entry, verb.complement);
|
||||||
|
function getTransObjFromOldVerbSelection() {
|
||||||
|
if (
|
||||||
|
!oldVerbSelection ||
|
||||||
|
oldVerbSelection.object === "none" ||
|
||||||
|
typeof oldVerbSelection.object === "number" ||
|
||||||
|
oldVerbSelection.isCompound === "dynamic" ||
|
||||||
|
(oldVerbSelection.object?.type === "noun" && oldVerbSelection.object.dynamicComplement)
|
||||||
|
) return undefined;
|
||||||
|
return oldVerbSelection.object;
|
||||||
|
}
|
||||||
|
const transitivity: T.Transitivity = "grammaticallyTransitive" in info
|
||||||
|
? "transitive"
|
||||||
|
: info.transitivity;
|
||||||
|
const object = (transitivity === "grammatically transitive")
|
||||||
|
? T.Person.ThirdPlurMale
|
||||||
|
: (info.type === "dynamic compound" && oldVerbSelection?.voice !== "passive")
|
||||||
|
? makeNounSelection(info.objComplement.entry as NounEntry, true)
|
||||||
|
: (transitivity === "transitive" && oldVerbSelection?.voice !== "passive")
|
||||||
|
? getTransObjFromOldVerbSelection()
|
||||||
|
: "none";
|
||||||
|
if (oldVerbSelection?.voice === "passive" && info.type === "dynamic compound") {
|
||||||
|
changeSubject(makeNounSelection(info.objComplement.entry as NounEntry, true));
|
||||||
|
}
|
||||||
|
const isCompound = ("stative" in info || info.type === "stative compound")
|
||||||
|
? "stative"
|
||||||
|
: info.type === "dynamic compound"
|
||||||
|
? "dynamic"
|
||||||
|
: false;
|
||||||
|
// TODO: here and below in the changeStatDyn function ... allow for entries with complement
|
||||||
|
const dynAuxVerb: VerbEntry | undefined = isCompound !== "dynamic"
|
||||||
|
? undefined
|
||||||
|
: info.type === "dynamic compound"
|
||||||
|
? { entry: info.auxVerb } as VerbEntry
|
||||||
|
: "dynamic" in info
|
||||||
|
? { entry: info.dynamic.auxVerb } as VerbEntry
|
||||||
|
: undefined;
|
||||||
|
const tenseSelection = ((): { tenseCategory: "perfect", tense: PerfectTense } | {
|
||||||
|
tenseCategory: "basic" | "modal",
|
||||||
|
tense: VerbTense,
|
||||||
|
} => {
|
||||||
|
if (!oldVerbSelection) {
|
||||||
|
return { tense: "presentVerb", tenseCategory: "basic" };
|
||||||
|
}
|
||||||
|
if (oldVerbSelection.tenseCategory === "modal") {
|
||||||
|
return { tenseCategory: "modal", tense: isPerfectTense(oldVerbSelection.tense) ? "presentVerb" : oldVerbSelection.tense };
|
||||||
|
}
|
||||||
|
if (oldVerbSelection.tenseCategory === "basic") {
|
||||||
|
return { tenseCategory: "basic", tense: isPerfectTense(oldVerbSelection.tense) ? "presentVerb" : oldVerbSelection.tense };
|
||||||
|
}
|
||||||
|
return { tenseCategory: "perfect", tense: isPerfectTense(oldVerbSelection.tense) ? oldVerbSelection.tense : "present perfect" };
|
||||||
|
})();
|
||||||
|
return {
|
||||||
|
type: "verb",
|
||||||
|
verb: verb,
|
||||||
|
dynAuxVerb,
|
||||||
|
...tenseSelection,
|
||||||
|
object,
|
||||||
|
transitivity,
|
||||||
|
isCompound,
|
||||||
|
voice: transitivity === "transitive"
|
||||||
|
? (oldVerbSelection?.voice || "active")
|
||||||
|
: "active",
|
||||||
|
negative: oldVerbSelection ? oldVerbSelection.negative : false,
|
||||||
|
...("grammaticallyTransitive" in info) ? {
|
||||||
|
changeTransitivity: function(t) {
|
||||||
|
return {
|
||||||
|
...this,
|
||||||
|
transitivity: t,
|
||||||
|
object: t === "grammatically transitive" ? T.Person.ThirdPlurMale : undefined,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
} : {},
|
||||||
|
...("stative" in info) ? {
|
||||||
|
changeStatDyn: function(c) {
|
||||||
|
return {
|
||||||
|
...this,
|
||||||
|
isCompound: c,
|
||||||
|
object: c === "dynamic"
|
||||||
|
? makeNounSelection(info.dynamic.objComplement.entry as NounEntry, true)
|
||||||
|
: undefined,
|
||||||
|
dynAuxVerb: c === "dynamic"
|
||||||
|
? { entry: info.dynamic.auxVerb } as VerbEntry
|
||||||
|
: undefined,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
} : {},
|
||||||
|
...(transitivity === "transitive") ? {
|
||||||
|
changeVoice: function(v, s) {
|
||||||
|
return {
|
||||||
|
...this,
|
||||||
|
voice: v,
|
||||||
|
object: v === "active" ? s : "none",
|
||||||
|
};
|
||||||
|
},
|
||||||
|
} : {},
|
||||||
|
};
|
||||||
|
}
|
|
@ -1684,10 +1684,10 @@
|
||||||
pbf "^3.2.1"
|
pbf "^3.2.1"
|
||||||
rambda "^6.7.0"
|
rambda "^6.7.0"
|
||||||
|
|
||||||
"@lingdocs/pashto-inflector@^1.6.8":
|
"@lingdocs/pashto-inflector@^1.6.9":
|
||||||
version "1.6.8"
|
version "1.6.9"
|
||||||
resolved "https://npm.lingdocs.com/@lingdocs%2fpashto-inflector/-/pashto-inflector-1.6.8.tgz#adc94c84c49cc067e26fb3066fae2a13b9d25d03"
|
resolved "https://npm.lingdocs.com/@lingdocs%2fpashto-inflector/-/pashto-inflector-1.6.9.tgz#cd66b8afe1c55ce609ba25952984cd5c329355ac"
|
||||||
integrity sha512-BGzMP0URWm6fEGdUUX653oImSMEkn11S/3vxeQILrQDCUNjGpNPQlORF27OlzCs8+n9lDBMDQHVjfhBlAZFN4w==
|
integrity sha512-ipssrtenaDr9k/VFz6WAxZ/spVb62IFgxczSVsd8Zc/fdIqzy9UKV4R4efJhBp2d7h5QadqBkfEk81PUZu48UQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
classnames "^2.2.6"
|
classnames "^2.2.6"
|
||||||
pbf "^3.2.1"
|
pbf "^3.2.1"
|
||||||
|
|
Loading…
Reference in New Issue