diff --git a/src/components/TensePicker.tsx b/src/components/TensePicker.tsx
new file mode 100644
index 0000000..081933e
--- /dev/null
+++ b/src/components/TensePicker.tsx
@@ -0,0 +1,180 @@
+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:
present
,
+ value: "presentVerb",
+}, {
+ label: subjunctive
,
+ value: "subjunctiveVerb",
+}, {
+ label: imperf. future
,
+ value: "imperfectiveFuture",
+}, {
+ label: perf. future
,
+ value: "perfectiveFuture",
+}, {
+ label: continuous past
,
+ value: "imperfectivePast",
+}, {
+ label: simple past
,
+ value: "perfectivePast",
+}, {
+ label: habitual cont. past
,
+ value: "habitualImperfectivePast",
+}, {
+ label: habitual simp. past
,
+ 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 TensePicker({ onChange, verb, mode }: {
+ verbs: VerbEntry[],
+ verb: VerbSelection | undefined,
+ onChange: (p: VerbSelection | undefined) => void,
+ mode: "charts" | "phrases",
+}) {
+ 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
+
+
+
Tense:
+ {verb &&
+
+
}
+
+
+
;
+}
+
+export default TensePicker;
\ No newline at end of file
diff --git a/src/components/VerbPicker.tsx b/src/components/VerbPicker.tsx
index 1f6edc4..e8de5e1 100644
--- a/src/components/VerbPicker.tsx
+++ b/src/components/VerbPicker.tsx
@@ -1,22 +1,32 @@
import {
ButtonSelect,
Types as T,
+ RootsAndStems,
+ getVerbInfo,
} from "@lingdocs/pashto-inflector";
+import Hider from "@lingdocs/pashto-inflector/dist/components/Hider";
import {
makeVerbSelection,
} from "./phrase-builder/verb-selection";
import EntrySelect from "./EntrySelect";
+import useStickyState from "../useStickyState";
// TODO: dark on past tense selecitons
-function VerbPicker({ onChange, subject, changeSubject, verb, verbs, opts }: {
+function VerbPicker({ onChange, subject, changeSubject, verb, verbs, opts, verbLocked }: {
verbs: VerbEntry[],
verb: VerbSelection | undefined,
subject: NPSelection | undefined,
onChange: (p: VerbSelection | undefined) => void,
changeSubject: (p: NPSelection | undefined) => void,
opts: T.TextOptions,
+ verbLocked: boolean,
}) {
+ const [showRootsAndStems, setShowRootsAndStems] = useStickyState(false, "showRootsAndStems");
+ const info = verb ? getVerbInfo(verb.verb.entry, verb.verb.complement) : undefined;
+ if (info && ("stative" in info || "transitive" in info)) {
+ return ERROR: Verb version should be select first
;
+ }
// const [filters, useFilters] = useState({
// stative: true,
// dynamic: true,
@@ -56,7 +66,7 @@ function VerbPicker({ onChange, subject, changeSubject, verb, verbs, opts }: {
}
}
return
-
}
+ {info &&
+ setShowRootsAndStems(p => !p)}
+ hLevel={5}
+ >
+
+
+
}
{verb && verb.changeTransitivity &&
({ ...base, zIndex: 9999 }) },
+};
+
+export function makeVerbSelectOption(e: VerbEntry, opts: T.TextOptions): { value: string, label: string | JSX.Element } {
+ const eng = getEnglishVerb(e.entry);
+ return {
+ label:
+ {{ p: e.entry.p, f: removeFVarients(e.entry.f), e: eng }}
+ ,
+ value: e.entry.ts.toString(),
+ };
+}
+
+export function makeSelectOption(
+ e: T.DictionaryEntry | VerbEntry | NounEntry | AdjectiveEntry | LocativeAdverbEntry,
+ opts: T.TextOptions,
+): { value: string, label: JSX.Element | 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:
+ {{ p: entry.p, f: removeFVarients(entry.f), e: 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,
+ };
+ },
+ } : {},
+ };
+}
\ No newline at end of file
diff --git a/src/components/phrase-builder/ChartDisplay.tsx b/src/components/phrase-builder/ChartDisplay.tsx
new file mode 100644
index 0000000..74554b9
--- /dev/null
+++ b/src/components/phrase-builder/ChartDisplay.tsx
@@ -0,0 +1,29 @@
+import {
+ conjugateVerb,
+ VerbFormDisplay,
+ Types as T,
+} from "@lingdocs/pashto-inflector";
+import {
+ getTenseVerbForm,
+} from "../../lib/phrase-building/vp-tools";
+
+function ChartDisplay({ VS, opts }: { VS: VerbSelection, opts: T.TextOptions }) {
+ const conjugations = conjugateVerb(VS.verb.entry, VS.verb.complement);
+ if (!conjugations) {
+ return Error conjugating verb
;
+ }
+ if ("stative" in conjugations || "transitive" in conjugations) {
+ return Error: compound or transitivity type should be selected first
;
+ }
+ const form = getTenseVerbForm(conjugations, VS.tense, VS.tenseCategory, VS.voice);
+ return
+
+
;
+}
+
+export default ChartDisplay;
\ No newline at end of file
diff --git a/src/components/phrase-builder/PhraseBuilder.tsx b/src/components/phrase-builder/PhraseBuilder.tsx
index a9a0702..9d4db76 100644
--- a/src/components/phrase-builder/PhraseBuilder.tsx
+++ b/src/components/phrase-builder/PhraseBuilder.tsx
@@ -14,6 +14,8 @@ import {
Types as T,
} from "@lingdocs/pashto-inflector";
import ChartDisplay from "./ChartDisplay";
+import useStickyState from "../../useStickyState";
+import { makeVerbSelection } from "./verb-selection";
const kingEmoji = "👑";
const servantEmoji = "🙇♂️";
@@ -34,9 +36,11 @@ export function PhraseBuilder(props: {
verb?: VerbEntry,
opts?: T.TextOptions,
}) {
- const [subject, setSubject] = useState(undefined);
- const [mode, setMode] = useState<"charts" | "phrases">("phrases");
- const [verb, setVerb] = useState(undefined);
+ const [subject, setSubject] = useStickyState(undefined, "subjectNPSelection");
+ const [mode, setMode] = useStickyState<"charts" | "phrases">("phrases", "verbExplorerMode");
+ const [verb, setVerb] = useState(
+ props.verb ? makeVerbSelection(props.verb, setSubject, undefined) : undefined,
+ );
const textOpts = props.opts || defaultTextOptions;
function handleSubjectChange(subject: NPSelection | undefined, skipPronounConflictCheck?: boolean) {
if (!skipPronounConflictCheck && hasPronounConflict(subject, verb?.object)) {
@@ -69,6 +73,7 @@ export function PhraseBuilder(props: {
{servantEmoji} =
servant of phrase
- {(verb && (typeof verb.object === "object") && (verb.isCompound !== "dynamic")) &&
+ {(verb && (typeof verb.object === "object") && (verb.isCompound !== "dynamic") && (mode !== "charts")) &&