better UI and fixed bug being able to close the imperative subject
This commit is contained in:
parent
10532cb3bb
commit
611f5defe5
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@lingdocs/pashto-inflector",
|
"name": "@lingdocs/pashto-inflector",
|
||||||
"version": "2.1.3",
|
"version": "2.1.4",
|
||||||
"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",
|
||||||
|
|
|
@ -27,14 +27,16 @@ function Examples({
|
||||||
children,
|
children,
|
||||||
ex,
|
ex,
|
||||||
opts,
|
opts,
|
||||||
|
lineHeight,
|
||||||
}: {
|
}: {
|
||||||
ex?: PsStringWSub | PsStringWSub[] | T.PsJSX | T.PsJSX[],
|
ex?: PsStringWSub | PsStringWSub[] | T.PsJSX | T.PsJSX[],
|
||||||
children: PsStringWSub | PsStringWSub[],
|
children: PsStringWSub | PsStringWSub[],
|
||||||
opts: T.TextOptions,
|
opts: T.TextOptions,
|
||||||
|
lineHeight?: 0 | 1 | 2 | 3 | 4,
|
||||||
}) {
|
}) {
|
||||||
const examples = children || ex;
|
const examples = children || ex;
|
||||||
const Example = ({ children: text }: { children: PsStringWSub }) => (
|
const Example = ({ children: text }: { children: PsStringWSub }) => (
|
||||||
<div className="mt-1 mb-3">
|
<div className={lineHeight !== undefined ? `mb-${lineHeight}` : `mt-1 mb-3`}>
|
||||||
<div>
|
<div>
|
||||||
<Pashto opts={opts}>{text}</Pashto>
|
<Pashto opts={opts}>{text}</Pashto>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -63,7 +63,6 @@ function NPNounPicker(props: ({
|
||||||
}) & {
|
}) & {
|
||||||
noun: T.NounSelection | undefined,
|
noun: T.NounSelection | undefined,
|
||||||
onChange: (p: T.NounSelection | undefined) => void,
|
onChange: (p: T.NounSelection | undefined) => void,
|
||||||
clearButton?: JSX.Element,
|
|
||||||
opts: T.TextOptions,
|
opts: T.TextOptions,
|
||||||
}) {
|
}) {
|
||||||
// const [patternFilter, setPatternFilter] = useState<FilterPattern | undefined>(undefined);
|
// const [patternFilter, setPatternFilter] = useState<FilterPattern | undefined>(undefined);
|
||||||
|
@ -82,14 +81,6 @@ function NPNounPicker(props: ({
|
||||||
// setShowFilter(false);
|
// setShowFilter(false);
|
||||||
// }
|
// }
|
||||||
return <div style={{ maxWidth: "225px", minWidth: "125px" }}>
|
return <div style={{ maxWidth: "225px", minWidth: "125px" }}>
|
||||||
<div className="d-flex flex-row justify-content-left">
|
|
||||||
{props.clearButton}
|
|
||||||
{/* {(!showFilter && !(noun?.dynamicComplement)) && <div className="text-right">
|
|
||||||
<button className="btn btn-sm btn-light mb-2 text-small" onClick={() => setShowFilter(true)}>
|
|
||||||
<i className="fas fa-filter fa-xs" />
|
|
||||||
</button>
|
|
||||||
</div>} */}
|
|
||||||
</div>
|
|
||||||
{/* {showFilter && <div className="mb-2 text-center">
|
{/* {showFilter && <div className="mb-2 text-center">
|
||||||
<div className="d-flex flex-row justify-content-between">
|
<div className="d-flex flex-row justify-content-between">
|
||||||
<div className="text-small mb-1">Filter by inflection pattern</div>
|
<div className="text-small mb-1">Filter by inflection pattern</div>
|
||||||
|
|
|
@ -16,7 +16,6 @@ function NPParticiplePicker(props: ({
|
||||||
}) & {
|
}) & {
|
||||||
participle: T.ParticipleSelection | undefined,
|
participle: T.ParticipleSelection | undefined,
|
||||||
onChange: (p: T.ParticipleSelection | undefined) => void,
|
onChange: (p: T.ParticipleSelection | undefined) => void,
|
||||||
clearButton: JSX.Element,
|
|
||||||
opts: T.TextOptions,
|
opts: T.TextOptions,
|
||||||
}) {
|
}) {
|
||||||
function onEntrySelect(entry: T.VerbEntry | undefined) {
|
function onEntrySelect(entry: T.VerbEntry | undefined) {
|
||||||
|
@ -27,7 +26,6 @@ function NPParticiplePicker(props: ({
|
||||||
props.onChange(makeParticipleSelection(entry));
|
props.onChange(makeParticipleSelection(entry));
|
||||||
}
|
}
|
||||||
return <div style={{ maxWidth: "225px" }}>
|
return <div style={{ maxWidth: "225px" }}>
|
||||||
{props.clearButton}
|
|
||||||
<h6>Participle</h6>
|
<h6>Participle</h6>
|
||||||
<EntrySelect
|
<EntrySelect
|
||||||
value={props.participle?.verb}
|
value={props.participle?.verb}
|
||||||
|
|
|
@ -14,6 +14,7 @@ import { isSecondPerson } from "../../lib/phrase-building/vp-tools";
|
||||||
const npTypes: T.NPType[] = ["pronoun", "noun", "participle"];
|
const npTypes: T.NPType[] = ["pronoun", "noun", "participle"];
|
||||||
|
|
||||||
function NPPicker(props: {
|
function NPPicker(props: {
|
||||||
|
heading?: JSX.Element,
|
||||||
onChange: (nps: T.NPSelection | undefined) => void,
|
onChange: (nps: T.NPSelection | undefined) => void,
|
||||||
np: T.NPSelection | undefined,
|
np: T.NPSelection | undefined,
|
||||||
counterPart: T.NPSelection | T.VerbObject | undefined,
|
counterPart: T.NPSelection | T.VerbObject | undefined,
|
||||||
|
@ -58,11 +59,21 @@ function NPPicker(props: {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const isDynamicComplement = props.np && props.np.type === "noun" && props.np.dynamicComplement;
|
const isDynamicComplement = props.np && props.np.type === "noun" && props.np.dynamicComplement;
|
||||||
const clearButton = !props.cantClear
|
const clearButton = (!props.cantClear && !props.is2ndPersonPicker && !isDynamicComplement)
|
||||||
? <button className="btn btn-sm btn-light mb-2" onClick={handleClear}>X</button>
|
? <button className="btn btn-sm btn-light mb-2" onClick={handleClear}>X</button>
|
||||||
: <div></div>;
|
: <div></div>;
|
||||||
return <div style={{ minWidth: "9rem" }}>
|
return <>
|
||||||
{!npType && <div className="text-center mt-3">
|
<div className="d-flex flex-row justify-content-between">
|
||||||
|
<div></div>
|
||||||
|
<div>
|
||||||
|
{props.heading}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
{npType && clearButton}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div style={{ minWidth: "9rem" }}>
|
||||||
|
{!npType && <div className="text-center">
|
||||||
<div className="h6 mr-3">
|
<div className="h6 mr-3">
|
||||||
Choose NP
|
Choose NP
|
||||||
</div>
|
</div>
|
||||||
|
@ -82,7 +93,6 @@ function NPPicker(props: {
|
||||||
asObject={props.asObject}
|
asObject={props.asObject}
|
||||||
pronoun={props.np}
|
pronoun={props.np}
|
||||||
onChange={props.onChange}
|
onChange={props.onChange}
|
||||||
clearButton={clearButton}
|
|
||||||
is2ndPersonPicker={props.is2ndPersonPicker}
|
is2ndPersonPicker={props.is2ndPersonPicker}
|
||||||
opts={props.opts}
|
opts={props.opts}
|
||||||
/>
|
/>
|
||||||
|
@ -96,7 +106,6 @@ function NPPicker(props: {
|
||||||
}}
|
}}
|
||||||
noun={(props.np && props.np.type === "noun") ? props.np : undefined}
|
noun={(props.np && props.np.type === "noun") ? props.np : undefined}
|
||||||
onChange={props.onChange}
|
onChange={props.onChange}
|
||||||
clearButton={!isDynamicComplement ? clearButton : undefined}
|
|
||||||
opts={props.opts}
|
opts={props.opts}
|
||||||
/>
|
/>
|
||||||
: npType === "participle"
|
: npType === "participle"
|
||||||
|
@ -109,12 +118,12 @@ function NPPicker(props: {
|
||||||
}}
|
}}
|
||||||
participle={(props.np && props.np.type === "participle") ? props.np : undefined}
|
participle={(props.np && props.np.type === "participle") ? props.np : undefined}
|
||||||
onChange={props.onChange}
|
onChange={props.onChange}
|
||||||
clearButton={clearButton}
|
|
||||||
opts={props.opts}
|
opts={props.opts}
|
||||||
/>
|
/>
|
||||||
: null
|
: null
|
||||||
}
|
}
|
||||||
</div>;
|
</div>
|
||||||
|
</>;
|
||||||
}
|
}
|
||||||
|
|
||||||
// {(npType && !isDynamicComplement) && }
|
// {(npType && !isDynamicComplement) && }
|
||||||
|
|
|
@ -103,8 +103,7 @@ function NPPronounPicker({ onChange, pronoun, asObject, clearButton, opts, is2nd
|
||||||
? [pSpecA[1]]
|
? [pSpecA[1]]
|
||||||
: pSpecA;
|
: pSpecA;
|
||||||
return <div style={{ maxWidth: "145px", padding: 0 }}>
|
return <div style={{ maxWidth: "145px", padding: 0 }}>
|
||||||
{clearButton}
|
<div className="d-flex flex-row justify-content-between mb-2">
|
||||||
<div className="d-flex flex-row justify-content-between mb-3">
|
|
||||||
{isThirdPerson(pronoun.person) ? <ButtonSelect
|
{isThirdPerson(pronoun.person) ? <ButtonSelect
|
||||||
xSmall
|
xSmall
|
||||||
options={[
|
options={[
|
||||||
|
@ -133,7 +132,7 @@ function NPPronounPicker({ onChange, pronoun, asObject, clearButton, opts, is2nd
|
||||||
className={classNames({ "table-active": active, "text-on-gender-color": active })}
|
className={classNames({ "table-active": active, "text-on-gender-color": active })}
|
||||||
style={{
|
style={{
|
||||||
backgroundColor: active ? gColors[p.gender] : "inherit",
|
backgroundColor: active ? gColors[p.gender] : "inherit",
|
||||||
padding: "0.25rem 0",
|
padding: "0.15rem 0",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div className="my-1">
|
<div className="my-1">
|
||||||
|
|
|
@ -57,10 +57,10 @@ const perfectTenseOptions: { label: string | JSX.Element, value: T.PerfectTense
|
||||||
}];
|
}];
|
||||||
|
|
||||||
const imperativeTenseOptions: { label: string | JSX.Element, value: T.ImperativeTense }[] = [{
|
const imperativeTenseOptions: { label: string | JSX.Element, value: T.ImperativeTense }[] = [{
|
||||||
label: <div><i className="fas fa-video mr-2" />imperfective imp.</div>,
|
label: <div><i className="fas fa-video mr-2" />imperfective imperative</div>,
|
||||||
value: "imperfectiveImperative",
|
value: "imperfectiveImperative",
|
||||||
}, {
|
}, {
|
||||||
label: <div><i className="fas fa-camera mr-2" />perfective imp.</div>,
|
label: <div><i className="fas fa-camera mr-2" />perfective imperative</div>,
|
||||||
value: "perfectiveImperative",
|
value: "perfectiveImperative",
|
||||||
}];
|
}];
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
import { renderVP, compileVP } from "../../lib/phrase-building/index";
|
import { renderVP, compileVP } from "../../lib/phrase-building/index";
|
||||||
import * as T from "../../types";
|
import * as T from "../../types";
|
||||||
import InlinePs from "../InlinePs";
|
|
||||||
import AbbreviationFormSelector from "./AbbreviationFormSelector";
|
import AbbreviationFormSelector from "./AbbreviationFormSelector";
|
||||||
import {
|
import {
|
||||||
isPastTense,
|
isPastTense,
|
||||||
completeVPSelection,
|
completeVPSelection,
|
||||||
} from "../../lib/phrase-building/vp-tools";
|
} from "../../lib/phrase-building/vp-tools";
|
||||||
import { useStickyState } from "../../library";
|
import { useStickyState } from "../../library";
|
||||||
|
import Examples from "../Examples";
|
||||||
|
|
||||||
function VPDisplay({ VP, opts }: { VP: T.VPSelection, opts: T.TextOptions }) {
|
function VPDisplay({ VP, opts }: { VP: T.VPSelection, opts: T.TextOptions }) {
|
||||||
const [form, setForm] = useStickyState<T.FormVersion>({ removeKing: false, shrinkServant: false }, "abbreviationForm");
|
const [form, setForm] = useStickyState<T.FormVersion>({ removeKing: false, shrinkServant: false }, "abbreviationForm");
|
||||||
|
@ -21,7 +21,7 @@ function VPDisplay({ VP, opts }: { VP: T.VPSelection, opts: T.TextOptions }) {
|
||||||
</div>;
|
</div>;
|
||||||
}
|
}
|
||||||
const result = compileVP(renderVP(VPComplete), { ...form, OSV });
|
const result = compileVP(renderVP(VPComplete), { ...form, OSV });
|
||||||
return <div className="text-center mt-2">
|
return <div className="text-center">
|
||||||
{VP.verb.transitivity === "transitive" && <div className="form-check mb-2">
|
{VP.verb.transitivity === "transitive" && <div className="form-check mb-2">
|
||||||
<input
|
<input
|
||||||
className="form-check-input"
|
className="form-check-input"
|
||||||
|
@ -52,7 +52,7 @@ function VPDisplay({ VP, opts }: { VP: T.VPSelection, opts: T.TextOptions }) {
|
||||||
</div>
|
</div>
|
||||||
: <VariationLayer vs={result.ps} opts={opts} />
|
: <VariationLayer vs={result.ps} opts={opts} />
|
||||||
}
|
}
|
||||||
{result.e && <div className="text-muted">
|
{result.e && <div className="text-muted mt-3">
|
||||||
{result.e.map((e, i) => <div key={i}>{e}</div>)}
|
{result.e.map((e, i) => <div key={i}>{e}</div>)}
|
||||||
</div>}
|
</div>}
|
||||||
</div>
|
</div>
|
||||||
|
@ -74,9 +74,7 @@ function whatsAdjustable(VP: T.VPSelectionComplete): "both" | "king" | "servant"
|
||||||
|
|
||||||
function VariationLayer({ vs, opts }: { vs: T.PsString[], opts: T.TextOptions }) {
|
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}>
|
<Examples opts={opts} lineHeight={0}>{vs}</Examples>
|
||||||
<InlinePs opts={opts}>{r}</InlinePs>
|
|
||||||
</div>)}
|
|
||||||
</div>;
|
</div>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -133,17 +133,11 @@ export function VPExplorer(props: {
|
||||||
{ label: "Phrases", value: "phrases" },
|
{ label: "Phrases", value: "phrases" },
|
||||||
{ label: "Quiz", value: "quiz" },
|
{ label: "Quiz", value: "quiz" },
|
||||||
]}
|
]}
|
||||||
handleChange={(x) => {
|
handleChange={setMode}
|
||||||
// TODO: remove this and implement the imperative in quiz
|
|
||||||
// if (x === "quiz") {
|
|
||||||
|
|
||||||
// }
|
|
||||||
setMode(x);
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{(vps.verb && (typeof vps.verb.object === "object") && (vps.verb.isCompound !== "dynamic") && (vps.verb.tenseCategory !== "imperative") &&(mode === "phrases")) &&
|
{(vps.verb && (typeof vps.verb.object === "object") && (vps.verb.isCompound !== "dynamic") && (vps.verb.tenseCategory !== "imperative") &&(mode === "phrases")) &&
|
||||||
<div className="text-center mt-4">
|
<div className="text-center my-2">
|
||||||
<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>
|
||||||
|
@ -151,10 +145,10 @@ export function VPExplorer(props: {
|
||||||
{mode !== "quiz" && <div className="d-flex flex-row justify-content-around flex-wrap" style={{ marginLeft: "-0.5rem", marginRight: "-0.5rem" }}>
|
{mode !== "quiz" && <div className="d-flex flex-row justify-content-around flex-wrap" style={{ marginLeft: "-0.5rem", marginRight: "-0.5rem" }}>
|
||||||
{mode === "phrases" && <>
|
{mode === "phrases" && <>
|
||||||
<div className="my-2">
|
<div className="my-2">
|
||||||
{roles.king === "subject"
|
|
||||||
? <div className="h5 text-center clickable" onClick={() => setShowingExplanation({ role: "king", item: "subject" })}>Subject {roleIcon.king}</div>
|
|
||||||
: <div className="h5 text-center clickable" onClick={() => setShowingExplanation({ role: "servant", item: "subject" })}>Subject {roleIcon.servant}</div>}
|
|
||||||
<NPPicker
|
<NPPicker
|
||||||
|
heading={roles.king === "subject"
|
||||||
|
? <div className="h5 text-center clickable" onClick={() => setShowingExplanation({ role: "king", item: "subject" })}>Subject {roleIcon.king}</div>
|
||||||
|
: <div className="h5 text-center clickable" onClick={() => setShowingExplanation({ role: "servant", item: "subject" })}>Subject {roleIcon.servant}</div>}
|
||||||
{..."getNounByTs" in props ? {
|
{..."getNounByTs" in props ? {
|
||||||
getNounByTs: props.getNounByTs,
|
getNounByTs: props.getNounByTs,
|
||||||
getVerbByTs: props.getVerbByTs,
|
getVerbByTs: props.getVerbByTs,
|
||||||
|
@ -172,12 +166,12 @@ export function VPExplorer(props: {
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{vps.verb && (vps.verb.object !== "none") && <div className="my-2">
|
{vps.verb && (vps.verb.object !== "none") && <div className="my-2">
|
||||||
{roles.king === "object"
|
|
||||||
? <div className="h5 text-center clickable" onClick={() => setShowingExplanation({ role: "king", item: "object" })}>Object {roleIcon.king}</div>
|
|
||||||
: <div className="h5 text-center clickable" onClick={() => setShowingExplanation({ role: "servant", item: "object" })}>Object {roleIcon.servant}</div>}
|
|
||||||
{(typeof vps.verb.object === "number")
|
{(typeof vps.verb.object === "number")
|
||||||
? <div className="text-muted">Unspoken 3rd Pers. Masc. Plur.</div>
|
? <div className="text-muted">Unspoken 3rd Pers. Masc. Plur.</div>
|
||||||
: <NPPicker
|
: <NPPicker
|
||||||
|
heading={roles.king === "object"
|
||||||
|
? <div className="h5 text-center clickable" onClick={() => setShowingExplanation({ role: "king", item: "object" })}>Object {roleIcon.king}</div>
|
||||||
|
: <div className="h5 text-center clickable" onClick={() => setShowingExplanation({ role: "servant", item: "object" })}>Object {roleIcon.servant}</div>}
|
||||||
{..."getNounByTs" in props ? {
|
{..."getNounByTs" in props ? {
|
||||||
getNounByTs: props.getNounByTs,
|
getNounByTs: props.getNounByTs,
|
||||||
getVerbByTs: props.getVerbByTs,
|
getVerbByTs: props.getVerbByTs,
|
||||||
|
|
Loading…
Reference in New Issue