add formulas and fix dark mode bad select colors

This commit is contained in:
lingdocs 2022-04-22 17:54:35 +05:00
parent 5dc01ee1ab
commit e2844f9bf4
9 changed files with 76 additions and 41 deletions

View File

@ -1,6 +1,6 @@
{ {
"name": "@lingdocs/pashto-inflector", "name": "@lingdocs/pashto-inflector",
"version": "2.1.7", "version": "2.1.8",
"author": "lingdocs.com", "author": "lingdocs.com",
"description": "A Pashto inflection and verb conjugation engine, inculding React components for displaying Pashto text, inflections, and conjugations", "description": "A Pashto inflection and verb conjugation engine, inculding React components for displaying Pashto text, inflections, and conjugations",
"homepage": "https://verbs.lingdocs.com", "homepage": "https://verbs.lingdocs.com",

View File

@ -26,7 +26,7 @@ import * as T from "./types";
import { isNounEntry } from "./lib/type-predicates"; import { isNounEntry } from "./lib/type-predicates";
import defualtTextOptions from "./lib/default-text-options"; import defualtTextOptions from "./lib/default-text-options";
import PhraseBuilder from "./components/vp-explorer/VPExplorer"; import PhraseBuilder from "./components/vp-explorer/VPExplorer";
import { useStickyState } from "./library"; import useStickyState from "./lib/useStickyState";
type VerbType = "simple" | "stative compound" | "dynamic compound"; type VerbType = "simple" | "stative compound" | "dynamic compound";
const verbTypes: VerbType[] = [ const verbTypes: VerbType[] = [
"simple", "simple",

View File

@ -7,7 +7,7 @@ import {
makeVerbSelectOption, makeVerbSelectOption,
} from "./np-picker/picker-tools"; } from "./np-picker/picker-tools";
const customStyles: StylesConfig = { export const customStyles: StylesConfig = {
menuPortal: (base) => ({ menuPortal: (base) => ({
...base, ...base,
zIndex: 99999, zIndex: 99999,
@ -19,17 +19,12 @@ const customStyles: StylesConfig = {
option: (provided, state) => ({ option: (provided, state) => ({
...provided, ...provided,
padding: "10px 5px", padding: "10px 5px",
color: "#121418",
}), }),
input: (base) => ({ input: (base) => ({
...base, ...base,
padding: 0, padding: 0,
}), }),
singleValue: (provided, state) => {
const opacity = state.isDisabled ? 0.5 : 1;
const transition = 'opacity 300ms';
return { ...provided, opacity, transition };
}
} }
function EntrySelect<E extends T.DictionaryEntry | T.VerbEntry>(props: ({ function EntrySelect<E extends T.DictionaryEntry | T.VerbEntry>(props: ({
@ -108,7 +103,7 @@ function EntrySelect<E extends T.DictionaryEntry | T.VerbEntry>(props: ({
styles={customStyles} styles={customStyles}
isSearchable={true} isSearchable={true}
value={value} value={value}
// @ts-ignore // @ts-ignore - gets messed up when using customStyles
onChange={onChange} onChange={onChange}
className="mb-2" className="mb-2"
options={options} options={options}

View File

@ -23,11 +23,6 @@ import {
translatePhonetics, translatePhonetics,
} from "../../lib/translate-phonetics"; } from "../../lib/translate-phonetics";
export const zIndexProps = {
menuPortalTarget: document.body,
styles: { menuPortal: (base: any) => ({ ...base, zIndex: 9999 }) },
};
export function makeVerbSelectOption(e: T.VerbEntry, opts: T.TextOptions): { value: string, label: string | JSX.Element } { export function makeVerbSelectOption(e: T.VerbEntry, opts: T.TextOptions): { value: string, label: string | JSX.Element } {
const engV = getEnglishVerb(e.entry); const engV = getEnglishVerb(e.entry);
const eng = engV || truncateEnglish(e.entry.e); const eng = engV || truncateEnglish(e.entry.e);

View File

@ -1,67 +1,83 @@
import Select from "react-select"; import Select from "react-select";
import {
zIndexProps,
} from "../np-picker/picker-tools";
import * as T from "../../types"; import * as T from "../../types";
import ButtonSelect from "../ButtonSelect"; import ButtonSelect from "../ButtonSelect";
import { isImperativeTense, isModalTense, isPerfectTense, isVerbTense } from "../../lib/type-predicates"; import { isImperativeTense, isModalTense, isPerfectTense, isVerbTense } from "../../lib/type-predicates";
import { ensure2ndPersSubjPronounAndNoConflict } from "../../lib/phrase-building/vp-tools"; import { ensure2ndPersSubjPronounAndNoConflict } from "../../lib/phrase-building/vp-tools";
import useStickyState from "../../lib/useStickyState";
import { customStyles } from "../EntrySelect";
const verbTenseOptions: { label: string | JSX.Element, value: T.VerbTense }[] = [{ const verbTenseOptions: { label: string | JSX.Element, value: T.VerbTense, formula: string }[] = [{
label: <div><i className="fas fa-video mr-2" />present</div>, label: <div><i className="fas fa-video mr-2" />present</div>,
value: "presentVerb", value: "presentVerb",
formula: "imperfective stem + present verb ending",
}, { }, {
label: <div><i className="fas fa-camera mr-2" />subjunctive</div>, label: <div><i className="fas fa-camera mr-2" />subjunctive</div>,
value: "subjunctiveVerb", value: "subjunctiveVerb",
formula: "perfective stem + present verb ending",
}, { }, {
label: <div><i className="fas fa-video mr-2" />imperfective future</div>, label: <div><i className="fas fa-video mr-2" />imperfective future</div>,
value: "imperfectiveFuture", value: "imperfectiveFuture",
formula: "ba + present",
}, { }, {
label: <div><i className="fas fa-camera mr-2" />perfective future</div>, label: <div><i className="fas fa-camera mr-2" />perfective future</div>,
value: "perfectiveFuture", value: "perfectiveFuture",
formula: "ba + subjunctive",
}, { }, {
label: <div><i className="fas fa-video mr-2" />continuous past</div>, label: <div><i className="fas fa-video mr-2" />continuous past</div>,
value: "imperfectivePast", value: "imperfectivePast",
formula: "imperfective root + past verb ending",
}, { }, {
label: <div><i className="fas fa-camera mr-2" />simple past</div>, label: <div><i className="fas fa-camera mr-2" />simple past</div>,
value: "perfectivePast", value: "perfectivePast",
formula: "perfective root + past verb ending",
}, { }, {
label: <div><i className="fas fa-video mr-2" />habitual continual past</div>, label: <div><i className="fas fa-video mr-2" />habitual continual past</div>,
value: "habitualImperfectivePast", value: "habitualImperfectivePast",
formula: "ba + contiunous past",
}, { }, {
label: <div><i className="fas fa-camera mr-2" />habitual simple past</div>, label: <div><i className="fas fa-camera mr-2" />habitual simple past</div>,
value: "habitualPerfectivePast", value: "habitualPerfectivePast",
formula: "ba + simple past",
}]; }];
const perfectTenseOptions: { label: string | JSX.Element, value: T.PerfectTense }[] = [{ const perfectTenseOptions: { label: string | JSX.Element, value: T.PerfectTense, formula: string }[] = [{
label: "Present Perfect", label: "Present Perfect",
value: "presentPerfect", value: "presentPerfect",
formula: "past participle + present equative",
}, { }, {
label: "Habitual Perfect", label: "Habitual Perfect",
value: "habitualPerfect", value: "habitualPerfect",
formula: "past participle + habitual equative",
}, { }, {
label: "Subjunctive Perfect", label: "Subjunctive Perfect",
value: "subjunctivePerfect", value: "subjunctivePerfect",
formula: "past participle + subjunctive equative",
}, { }, {
label: "Future Perfect", label: "Future Perfect",
value: "futurePerfect", value: "futurePerfect",
formula: "past participle + future equative",
}, { }, {
label: "Past Perfect", label: "Past Perfect",
value: "pastPerfect", value: "pastPerfect",
formula: "past participle + past equative",
}, { }, {
label: `"Would Be" Perfect`, label: `"Would Be" Perfect`,
value: "wouldBePerfect", value: "wouldBePerfect",
formula: `past participle + "would be" equative`,
}, { }, {
label: "Past Subjunctive Perfect", label: "Past Subjunctive Perfect",
value: "pastSubjunctivePerfect", value: "pastSubjunctivePerfect",
formula: "past participle + past subjunctive equative",
}]; }];
const imperativeTenseOptions: { label: string | JSX.Element, value: T.ImperativeTense }[] = [{ const imperativeTenseOptions: { label: string | JSX.Element, value: T.ImperativeTense, formula: string }[] = [{
label: <div><i className="fas fa-video mr-2" />imperfective imperative</div>, label: <div><i className="fas fa-video mr-2" />imperfective imperative</div>,
value: "imperfectiveImperative", value: "imperfectiveImperative",
formula: "imperfective stem + imperative ending",
}, { }, {
label: <div><i className="fas fa-camera mr-2" />perfective imperative</div>, label: <div><i className="fas fa-camera mr-2" />perfective imperative</div>,
value: "perfectiveImperative", value: "perfectiveImperative",
formula: "perfective stem + imperative ending",
}]; }];
export function getRandomTense(o?: T.PerfectTense | T.VerbTense | T.ModalTense | T.ImperativeTense): T.PerfectTense | T.VerbTense | T.ModalTense | T.ImperativeTense { export function getRandomTense(o?: T.PerfectTense | T.VerbTense | T.ModalTense | T.ImperativeTense): T.PerfectTense | T.VerbTense | T.ModalTense | T.ImperativeTense {
@ -92,6 +108,7 @@ function TensePicker(props: ({
onChange: (p: T.VPSelection) => void, onChange: (p: T.VPSelection) => void,
mode: "charts" | "phrases" | "quiz", mode: "charts" | "phrases" | "quiz",
}) { }) {
const [showFormula, setShowFormula] = useStickyState<boolean>(false, "showFormula");
function onTenseSelect(o: { value: T.VerbTense | T.PerfectTense | T.ImperativeTense } | null) { function onTenseSelect(o: { value: T.VerbTense | T.PerfectTense | T.ImperativeTense } | null) {
if ("vpsComplete" in props) return; if ("vpsComplete" in props) return;
const value = o?.value ? o.value : undefined; const value = o?.value ? o.value : undefined;
@ -199,9 +216,15 @@ function TensePicker(props: ({
: verbTenseOptions; : verbTenseOptions;
const showImperativeOption = ("vps" in props && props.vps.verb.voice === "active") const showImperativeOption = ("vps" in props && props.vps.verb.voice === "active")
|| ("vpsComplete" in props && props.vpsComplete.verb.voice !== "active"); || ("vpsComplete" in props && props.vpsComplete.verb.voice !== "active");
const canShowFormula = "vps" in props && props.vps.verb.tenseCategory !== "modal";
return <div> return <div>
<div style={{ maxWidth: "300px", minWidth: "250px", margin: "0 auto" }}> <div style={{ maxWidth: "300px", minWidth: "250px", margin: "0 auto" }}>
<div className="h5">Tense:</div> <div className="d-flex flex-row justify-content-between align-items-center">
<div className="h5">Tense:</div>
{canShowFormula && <div className="clickable mb-2 small" onClick={() => setShowFormula(x => !x)}>
🧪 {!showFormula ? "Show" : "Hide"} Formula
</div>}
</div>
{("vpsComplete" in props || props.vps.verb) && <div className="mb-2"> {("vpsComplete" in props || props.vps.verb) && <div className="mb-2">
<ButtonSelect <ButtonSelect
small small
@ -237,22 +260,25 @@ function TensePicker(props: ({
? <div style={{ fontSize: "larger" }} className="mb-3"> ? <div style={{ fontSize: "larger" }} className="mb-3">
{[...verbTenseOptions, ...perfectTenseOptions, ...imperativeTenseOptions].find(o => o.value === props.vpsComplete.verb.tense)?.label} {[...verbTenseOptions, ...perfectTenseOptions, ...imperativeTenseOptions].find(o => o.value === props.vpsComplete.verb.tense)?.label}
</div> </div>
: <Select : <>
isSearchable={false} <Select
// for some reason can't use tOptions with find here; isSearchable={false}
value={props.vps.verb && ([...verbTenseOptions, ...perfectTenseOptions, ...imperativeTenseOptions].find(o => o.value === props.vps.verb[ // for some reason can't use tOptions with find here;
props.vps.verb.tenseCategory === "perfect" value={props.vps.verb && ([...verbTenseOptions, ...perfectTenseOptions, ...imperativeTenseOptions].find(o => o.value === props.vps.verb[
? "perfectTense" props.vps.verb.tenseCategory === "perfect"
: props.vps.verb.tenseCategory === "imperative" ? "perfectTense"
? "imperativeTense" : props.vps.verb.tenseCategory === "imperative"
: "verbTense" ? "imperativeTense"
]))} : "verbTense"
onChange={onTenseSelect} ]))}
className="mb-2" // @ts-ignore - gets messed up when using customStyles
options={tOptions} onChange={onTenseSelect}
{...zIndexProps} className="mb-2"
/>} options={tOptions}
{"vps" in props && props.vps.verb && (props.mode !== "quiz") && <div className="d-flex flex-row justify-content-between align-items-center mt-3 mb-1" style={{ width: "100%" }}> styles={customStyles}
/>
</>}
{"vps" in props && props.vps.verb && (props.mode !== "quiz") && <div className="d-flex flex-row justify-content-between align-items-center mt-2 mb-1" style={{ width: "100%" }}>
<div className="btn btn-light clickable" onClick={moveTense("back")}> <div className="btn btn-light clickable" onClick={moveTense("back")}>
<i className="fas fa-chevron-left" /> <i className="fas fa-chevron-left" />
</div> </div>
@ -272,6 +298,23 @@ function TensePicker(props: ({
<i className="fas fa-chevron-right" /> <i className="fas fa-chevron-right" />
</div> </div>
</div>} </div>}
{(canShowFormula && "vps" in props && showFormula && props.vps.verb.tenseCategory !== "modal") && (() => {
// TODO: Be able to show modal formulas too
const curr = (props.vps.verb.tenseCategory === "imperative" && props.vps.verb.negative)
? imperativeTenseOptions.find(x => x.value === "imperfectiveImperative")
: [...verbTenseOptions, ...perfectTenseOptions, ...imperativeTenseOptions].find(o => o.value === props.vps.verb[
props.vps.verb.tenseCategory === "perfect"
? "perfectTense"
: props.vps.verb.tenseCategory === "imperative"
? "imperativeTense"
: "verbTense"
]);
if (curr && "formula" in curr) {
return <div style={{ width: "250px", overflowY: "auto" }}>
<samp>{curr.formula}</samp>
</div>
}
})()}
</div> </div>
</div>; </div>;
} }

View File

@ -5,7 +5,7 @@ import {
isPastTense, isPastTense,
completeVPSelection, completeVPSelection,
} from "../../lib/phrase-building/vp-tools"; } from "../../lib/phrase-building/vp-tools";
import { useStickyState } from "../../library"; import useStickyState from "../../lib/useStickyState";
import Examples from "../Examples"; import Examples from "../Examples";
function VPDisplay({ VP, opts }: { VP: T.VPSelection, opts: T.TextOptions }) { function VPDisplay({ VP, opts }: { VP: T.VPSelection, opts: T.TextOptions }) {

View File

@ -47,7 +47,9 @@ export function revertSpelling(input: string, spelling: T.Spelling): string {
: "ي"}(?![\u0621-\u065f\u0670-\u06d3\u06d5])`, "g"), "ي") : "ي"}(?![\u0621-\u065f\u0670-\u06d3\u06d5])`, "g"), "ي")
.replace(/ے(?![\u0621-\u065f\u0670-\u06d3\u06d5])/g, "ی") .replace(/ے(?![\u0621-\u065f\u0670-\u06d3\u06d5])/g, "ی")
.replace(/ائ(?![\u0621-\u065f\u0670-\u06d3\u06d5])/g, "ای") .replace(/ائ(?![\u0621-\u065f\u0670-\u06d3\u06d5])/g, "ای")
.replace(/اے(?![\u0621-\u065f\u0670-\u06d3\u06d5])/g, "ای")
.replace(/وئ(?![\u0621-\u065f\u0670-\u06d3\u06d5])/g, "وی") .replace(/وئ(?![\u0621-\u065f\u0670-\u06d3\u06d5])/g, "وی")
.replace(/وے(?![\u0621-\u065f\u0670-\u06d3\u06d5])/g, "وی")
.replace(/(?:ائی|ائي)(?=[\u0621-\u065f\u0670-\u06d3\u06d5])/g, "اي") .replace(/(?:ائی|ائي)(?=[\u0621-\u065f\u0670-\u06d3\u06d5])/g, "اي")
.replace(/(?:وئی|وئي)(?=[\u0621-\u065f\u0670-\u06d3\u06d5])/g, "وي") .replace(/(?:وئی|وئي)(?=[\u0621-\u065f\u0670-\u06d3\u06d5])/g, "وي")
.replace(/ائ(?=ي|ی|ې)/g, "اي") .replace(/ائ(?=ي|ی|ې)/g, "اي")

View File

@ -27,7 +27,7 @@ import {
isPerfectTense, isPerfectTense,
} from "../type-predicates"; } from "../type-predicates";
import { renderEnglishVPBase } from "./english-vp-rendering"; import { renderEnglishVPBase } from "./english-vp-rendering";
import { personGender } from "../../library"; import { personGender } from "../../lib/misc-helpers";
// TODO: ISSUE GETTING SPLIT HEAD NOT MATCHING WITH FUTURE VERBS // TODO: ISSUE GETTING SPLIT HEAD NOT MATCHING WITH FUTURE VERBS

File diff suppressed because one or more lines are too long