create EP picker
This commit is contained in:
parent
8d33931aa8
commit
e39f77c8b3
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@lingdocs/pashto-inflector",
|
||||
"version": "2.8.7",
|
||||
"version": "2.8.8",
|
||||
"author": "lingdocs.com",
|
||||
"description": "A Pashto inflection and verb conjugation engine, inculding React components for displaying Pashto text, inflections, and conjugations",
|
||||
"homepage": "https://verbs.lingdocs.com",
|
||||
|
|
|
@ -1,19 +1,17 @@
|
|||
import * as T from "../../types";
|
||||
import useStickyState, { useStickyReducer } from "../../lib/useStickyState";
|
||||
import NPPicker from "../np-picker/NPPicker";
|
||||
import EquativePicker from "./EquativePicker";
|
||||
import EPDisplay from "./EPDisplay";
|
||||
import ButtonSelect from "../ButtonSelect";
|
||||
import EqCompPicker from "./eq-comp-picker/EqCompPicker";
|
||||
import EqChartsDisplay from "./EqChartsDisplay";
|
||||
import epsReducer from "./eps-reducer";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import { completeEPSelection } from "../../lib/phrase-building/render-ep";
|
||||
import { makeEPSBlocks } from "../../lib/phrase-building/blocks-utils";
|
||||
import APPicker from "../ap-picker/APPicker";
|
||||
import EquativePicker from "./EquativePicker";
|
||||
import autoAnimate from "@formkit/auto-animate";
|
||||
// @ts-ignore
|
||||
import LZString from "lz-string";
|
||||
import EPPicker from "./EPPicker";
|
||||
const phraseURLParam = "EPhrase";
|
||||
|
||||
const blankEps: T.EPSelectionState = {
|
||||
|
@ -35,14 +33,11 @@ const blankEps: T.EPSelectionState = {
|
|||
function EPExplorer(props: {
|
||||
opts: T.TextOptions,
|
||||
entryFeeder: T.EntryFeeder,
|
||||
} & ({
|
||||
eps: T.EPSelectionState,
|
||||
onChange: (eps: T.EPSelectionState) => void,
|
||||
} | {})) {
|
||||
}) {
|
||||
const [mode, setMode] = useStickyState<"charts" | "phrases">("charts", "EPExplorerMode");
|
||||
const [eps, adjustEps] = useStickyReducer(
|
||||
epsReducer,
|
||||
"eps" in props ? props.eps : blankEps,
|
||||
blankEps,
|
||||
"EPState7",
|
||||
flashMessage,
|
||||
);
|
||||
|
@ -63,6 +58,9 @@ function EPExplorer(props: {
|
|||
}
|
||||
// eslint-disable-next-line
|
||||
}, []);
|
||||
function handleEpsChange(e: T.EPSelectionState) {
|
||||
adjustEps({ type: "load EPS", payload: e });
|
||||
}
|
||||
function flashMessage(msg: string) {
|
||||
setAlert(msg);
|
||||
setTimeout(() => {
|
||||
|
@ -114,86 +112,21 @@ function EPExplorer(props: {
|
|||
</div>
|
||||
</div>}
|
||||
</div>
|
||||
{mode === "phrases" && <div className="clickable h5" onClick={() => adjustEps({ type: "insert new AP" })}>+ AP</div>}
|
||||
<div ref={parent} className="d-flex flex-row justify-content-around flex-wrap" style={{ marginLeft: "-0.5rem", marginRight: "-0.5rem" }}>
|
||||
{mode === "phrases" && <>
|
||||
{eps.blocks.map(({ block, key }, i) => (
|
||||
<div className="my-2 card block-card p-1 mx-1" key={key}>
|
||||
<div className="d-flex flex-row justify-content-between mb-1" style={{ height: "1rem" }}>
|
||||
{i > 0 ? <div
|
||||
className="small clickable ml-1"
|
||||
onClick={() => adjustEps({ type: "shift block", payload: { index: i, direction: "back" }})}
|
||||
>
|
||||
<i className="fas fa-chevron-left" />
|
||||
</div> : <div/>}
|
||||
{i < eps.blocks.length - 1 ? <div
|
||||
className="small clickable mr-1"
|
||||
onClick={() => adjustEps({ type: "shift block", payload: { index: i, direction: "forward" }})}
|
||||
>
|
||||
<i className="fas fa-chevron-right" />
|
||||
</div> : <div/>}
|
||||
</div>
|
||||
{block && block.type === "subjectSelection"
|
||||
? <NPPicker
|
||||
phraseIsComplete={phraseIsComplete}
|
||||
heading={<div className="h5 text-center">Subject</div>}
|
||||
entryFeeder={props.entryFeeder}
|
||||
np={block.selection}
|
||||
counterPart={undefined}
|
||||
role="subject"
|
||||
onChange={payload => adjustEps({ type: "set subject", payload })}
|
||||
{mode === "phrases" &&
|
||||
<EPPicker
|
||||
opts={props.opts}
|
||||
/>
|
||||
: <APPicker
|
||||
phraseIsComplete={phraseIsComplete}
|
||||
heading="AP"
|
||||
entryFeeder={props.entryFeeder}
|
||||
AP={block}
|
||||
opts={props.opts}
|
||||
onChange={AP => adjustEps({ type: "set AP", payload: { index: i, AP } })}
|
||||
onRemove={() => adjustEps({ type: "remove AP", payload: i })}
|
||||
eps={eps}
|
||||
onChange={handleEpsChange}
|
||||
/>}
|
||||
</div>
|
||||
))}
|
||||
<div className="my-2 card block-card p-1">
|
||||
<div className="h5 text-center">Predicate</div>
|
||||
<div className="mb-2 text-center">
|
||||
<ButtonSelect
|
||||
small
|
||||
options={[
|
||||
{ value: "NP", label: "NP" },
|
||||
{ value: "Complement", label: "Complement" },
|
||||
]}
|
||||
value={eps.predicate.type}
|
||||
handleChange={payload => adjustEps({ type: "set predicate type", payload })}
|
||||
/>
|
||||
</div>
|
||||
{eps.predicate.type === "NP" ? <NPPicker
|
||||
phraseIsComplete={phraseIsComplete}
|
||||
entryFeeder={props.entryFeeder}
|
||||
np={eps.predicate.type === "NP" ? eps.predicate.NP : undefined}
|
||||
counterPart={undefined}
|
||||
role="subject"
|
||||
onChange={payload => adjustEps({ type: "set predicate NP", payload })}
|
||||
opts={props.opts}
|
||||
/> : <EqCompPicker
|
||||
phraseIsComplete={phraseIsComplete}
|
||||
comp={eps.predicate.type === "Complement" ? eps.predicate.Complement : undefined}
|
||||
onChange={payload => adjustEps({ type: "set predicate comp", payload })}
|
||||
opts={props.opts}
|
||||
entryFeeder={props.entryFeeder}
|
||||
/>}
|
||||
</div>
|
||||
</>}
|
||||
<div className="my-2">
|
||||
{mode === "charts" && <div className="my-2">
|
||||
<div className="h5 text-center clickable">Equative</div>
|
||||
<EquativePicker
|
||||
equative={eps.equative}
|
||||
onChange={payload => adjustEps({ type: "set equative", payload })}
|
||||
hideNegative={mode === "charts"}
|
||||
hideNegative={false}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>}
|
||||
{mode === "charts" && <EqChartsDisplay tense={eps.equative.tense} opts={props.opts} />}
|
||||
{mode === "phrases" && <EPDisplay
|
||||
opts={props.opts}
|
||||
|
|
|
@ -0,0 +1,124 @@
|
|||
import * as T from "../../types";
|
||||
import NPPicker from "../np-picker/NPPicker";
|
||||
import EquativePicker from "./EquativePicker";
|
||||
import ButtonSelect from "../ButtonSelect";
|
||||
import EqCompPicker from "./eq-comp-picker/EqCompPicker";
|
||||
import epsReducer, { EpsReducerAction } from "./eps-reducer";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import { completeEPSelection } from "../../lib/phrase-building/render-ep";
|
||||
import APPicker from "../ap-picker/APPicker";
|
||||
import autoAnimate from "@formkit/auto-animate";
|
||||
|
||||
function EPPicker({ opts, eps, onChange, entryFeeder }: {
|
||||
opts: T.TextOptions,
|
||||
eps: T.EPSelectionState,
|
||||
onChange: (eps: T.EPSelectionState) => void,
|
||||
entryFeeder: T.EntryFeeder,
|
||||
}) {
|
||||
const parent = useRef<HTMLDivElement>(null);
|
||||
const [alert, setAlert] = useState<string | undefined>("");
|
||||
useEffect(() => {
|
||||
parent.current && autoAnimate(parent.current);
|
||||
}, [parent]);
|
||||
function adjustEps(action: EpsReducerAction) {
|
||||
onChange(epsReducer(eps, action, handleAlert));
|
||||
}
|
||||
function handleAlert(msg: string) {
|
||||
setAlert(msg);
|
||||
setTimeout(() => {
|
||||
setAlert(undefined);
|
||||
}, 1500);
|
||||
}
|
||||
const phraseIsComplete = !!completeEPSelection(eps);
|
||||
return <div>
|
||||
<div className="clickable h5" onClick={() => adjustEps({ type: "insert new AP" })}>+ AP</div>
|
||||
<div ref={parent} className="d-flex flex-row justify-content-around flex-wrap" style={{ marginLeft: "-0.5rem", marginRight: "-0.5rem" }}>
|
||||
{eps.blocks.map(({ block, key }, i) => (
|
||||
<div className="my-2 card block-card p-1 mx-1" key={key}>
|
||||
<div className="d-flex flex-row justify-content-between mb-1" style={{ height: "1rem" }}>
|
||||
{i > 0 ? <div
|
||||
className="small clickable ml-1"
|
||||
onClick={() => adjustEps({ type: "shift block", payload: { index: i, direction: "back" }})}
|
||||
>
|
||||
<i className="fas fa-chevron-left" />
|
||||
</div> : <div/>}
|
||||
{i < eps.blocks.length - 1 ? <div
|
||||
className="small clickable mr-1"
|
||||
onClick={() => adjustEps({ type: "shift block", payload: { index: i, direction: "forward" }})}
|
||||
>
|
||||
<i className="fas fa-chevron-right" />
|
||||
</div> : <div/>}
|
||||
</div>
|
||||
{block && block.type === "subjectSelection"
|
||||
? <NPPicker
|
||||
phraseIsComplete={phraseIsComplete}
|
||||
heading={<div className="h5 text-center">Subject</div>}
|
||||
entryFeeder={entryFeeder}
|
||||
np={block.selection}
|
||||
counterPart={undefined}
|
||||
role="subject"
|
||||
onChange={payload => adjustEps({ type: "set subject", payload })}
|
||||
opts={opts}
|
||||
/>
|
||||
: <APPicker
|
||||
phraseIsComplete={phraseIsComplete}
|
||||
heading="AP"
|
||||
entryFeeder={entryFeeder}
|
||||
AP={block}
|
||||
opts={opts}
|
||||
onChange={AP => adjustEps({ type: "set AP", payload: { index: i, AP } })}
|
||||
onRemove={() => adjustEps({ type: "remove AP", payload: i })}
|
||||
/>}
|
||||
</div>
|
||||
))}
|
||||
<div className="my-2 card block-card p-1">
|
||||
<div className="h5 text-center">Predicate</div>
|
||||
<div className="mb-2 text-center">
|
||||
<ButtonSelect
|
||||
small
|
||||
options={[
|
||||
{ value: "NP", label: "NP" },
|
||||
{ value: "Complement", label: "Complement" },
|
||||
]}
|
||||
value={eps.predicate.type}
|
||||
handleChange={payload => adjustEps({ type: "set predicate type", payload })}
|
||||
/>
|
||||
</div>
|
||||
{eps.predicate.type === "NP" ? <NPPicker
|
||||
phraseIsComplete={phraseIsComplete}
|
||||
entryFeeder={entryFeeder}
|
||||
np={eps.predicate.type === "NP" ? eps.predicate.NP : undefined}
|
||||
counterPart={undefined}
|
||||
role="subject"
|
||||
onChange={payload => adjustEps({ type: "set predicate NP", payload })}
|
||||
opts={opts}
|
||||
/> : <EqCompPicker
|
||||
phraseIsComplete={phraseIsComplete}
|
||||
comp={eps.predicate.type === "Complement" ? eps.predicate.Complement : undefined}
|
||||
onChange={payload => adjustEps({ type: "set predicate comp", payload })}
|
||||
opts={opts}
|
||||
entryFeeder={entryFeeder}
|
||||
/>}
|
||||
</div>
|
||||
<div className="my-2">
|
||||
<div className="h5 text-center clickable">Equative</div>
|
||||
<EquativePicker
|
||||
equative={eps.equative}
|
||||
onChange={payload => adjustEps({ type: "set equative", payload })}
|
||||
hideNegative={false}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
{alert && <div className="alert alert-warning text-center" role="alert" style={{
|
||||
position: "fixed",
|
||||
top: "30%",
|
||||
left: "50%",
|
||||
transform: "translate(-50%, -50%)",
|
||||
zIndex: 9999999999999,
|
||||
}}>
|
||||
{alert}
|
||||
</div>}
|
||||
</div>;
|
||||
}
|
||||
|
||||
export default EPPicker;
|
|
@ -7,7 +7,7 @@ import { isUnisexNounEntry } from "../../lib/type-predicates";
|
|||
import { checkEPForMiniPronounsError } from "../../lib/phrase-building/compile";
|
||||
import { adjustSubjectSelection, getSubjectSelection, insertNewAP, removeAP, setAP, shiftBlock } from "../../lib/phrase-building/blocks-utils";
|
||||
|
||||
type EpsReducerAction = {
|
||||
export type EpsReducerAction = {
|
||||
type: "set predicate type",
|
||||
payload: "NP" | "Complement",
|
||||
} | {
|
||||
|
|
|
@ -149,6 +149,7 @@ import {
|
|||
renderAPSelection,
|
||||
} from "./lib/phrase-building/render-ap";
|
||||
import NPPicker from "./components/np-picker/NPPicker";
|
||||
import EPPicker from "./components/ep-explorer/EPPicker";
|
||||
import EPExplorer from "./components/ep-explorer/EPExplorer";
|
||||
import shuffleArray from "./lib/shuffle-array";
|
||||
import defaultTextOptions from "./lib/default-text-options";
|
||||
|
@ -253,6 +254,7 @@ export {
|
|||
APBlock,
|
||||
Block,
|
||||
EPDisplay,
|
||||
EPPicker,
|
||||
// OTHER
|
||||
typePredicates,
|
||||
grammarUnits,
|
||||
|
|
Loading…
Reference in New Issue