better UI for removing king

This commit is contained in:
lingdocs 2022-08-02 13:27:19 -05:00
parent dc75525e74
commit a3a0cd9319
8 changed files with 149 additions and 20 deletions

View File

@ -1,6 +1,6 @@
{
"name": "@lingdocs/pashto-inflector",
"version": "3.6.8",
"version": "3.6.9",
"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",

View File

@ -1,15 +1,19 @@
import * as T from "../../types";
import { useState } from "react";
import AdjectivePicker from "./AdjectivePicker";
import classNames from "classnames";
function AdjectiveManager(props: {
adjectives: T.AdjectiveSelection[],
entryFeeder: T.EntryFeeder,
opts: T.TextOptions,
demonstrative: T.NounSelection["demonstrative"],
onChange: (adjs: T.AdjectiveSelection[]) => void,
onDemonstrativeChange: (dem: T.NounSelection["demonstrative"]) => void,
phraseIsComplete: boolean,
}) {
const [adding, setAdding] = useState<boolean>(false);
const [addingDemonstrative, setAddingDemonstrative] = useState<boolean>(false);
function handleChange(i: number) {
return (a: T.AdjectiveSelection | undefined) => {
if (a === undefined) return;
@ -53,6 +57,21 @@ function AdjectiveManager(props: {
onChange={handleAddNew}
/>
</div>}
{addingDemonstrative && <div>
<div className="d-flex flex-row justify-content-between mb-1">
<div>Add Demonstrative</div>
<div className="clickable" onClick={() => {
setAddingDemonstrative(false);
props.onDemonstrativeChange(undefined);
}}>
<i className="fas fa-trash" />
</div>
</div>
<DemonstrativePicker
demonstrative={props.demonstrative}
onChange={props.onDemonstrativeChange}
/>
</div>}
{props.adjectives.map((adj, i) => <div key={i}>
<div className="d-flex flex-row justify-content-between">
<div>Adjective</div>
@ -75,12 +94,55 @@ function AdjectiveManager(props: {
onChange={handleChange(i)}
/>
</div>)}
{!adding && !props.adjectives.length && <h6 className="clickable" style={{ float: "right" }}>
{/* {!adding && !props.adjectives.length && <h6 className="clickable" style={{ float: "right" }}>
<div className="clickable" onClick={() => setAdding(true)}>+ Adj.</div>
</h6>} */}
{!addingDemonstrative && !props.demonstrative && <h6 className="clickable mr-2" style={{ float: "right" }}>
<div className="clickable" onClick={() => setAddingDemonstrative(true)}>+ Demons.</div>
</h6>}
</div>;
}
function DemonstrativePicker({ demonstrative, onChange }: {
demonstrative: T.NounSelection["demonstrative"],
onChange: (dem: T.NounSelection["demonstrative"]) => void,
}) {
function handleDChange(d: "daa" | "hagha" | "dagha") {
if (!demonstrative) {
onChange({
type: "demonstrative",
demonstrative: d,
hideNoun: false,
});
} else {
onChange({
...demonstrative,
demonstrative: d,
});
}
}
return <div className="d-flex flex-row justify-content-around py-1">
<div>
<button
className={classNames("btn", "btn-outline-secondary", { active: demonstrative?.demonstrative === "daa" })}
onClick={() => handleDChange("daa")}
>دا</button>
</div>
<div>
<button
className={classNames("btn", "btn-outline-secondary", { active: demonstrative?.demonstrative === "hagha" })}
onClick={() => handleDChange("hagha")}
>هغه</button>
</div>
<div>
<button
className={classNames("btn", "btn-outline-secondary", { active: demonstrative?.demonstrative === "dagha" })}
onClick={() => handleDChange("dagha")}
>دغه</button>
</div>
</div>;
}
function remove<X>(arr: X[], i: number): X[] {
return [
...arr.slice(0, i),

View File

@ -85,6 +85,14 @@ function NPNounPicker(props: {
});
}
}
function handleDemonstrativeUpdate(demonstrative: undefined | T.NounSelection["demonstrative"]) {
if (props.noun) {
props.onChange({
...props.noun,
demonstrative,
});
}
}
return <div style={{ maxWidth: "225px", minWidth: "125px" }}>
{/* {showFilter && <div className="mb-2 text-center">
<div className="d-flex flex-row justify-content-between">
@ -102,9 +110,11 @@ function NPNounPicker(props: {
{props.noun && <AdjectiveManager
phraseIsComplete={props.phraseIsComplete}
adjectives={props.noun?.adjectives}
demonstrative={props.noun.demonstrative}
entryFeeder={props.entryFeeder}
opts={props.opts}
onChange={handelAdjectivesUpdate}
onDemonstrativeChange={handleDemonstrativeUpdate}
/>}
<h6>Noun</h6>
{!(props.noun && props.noun.dynamicComplement) ? <div>

View File

@ -108,7 +108,7 @@ function NPPicker(props: {
: <div></div>;
const possesiveLabel = props.np?.selection.type === "participle" ? "Subj/Obj" : "Possesor";
return <div style={{
opacity: props.isRemoved ? 0.6 : 1,
opacity: props.isRemoved ? 0.5 : 1,
}}>
<div className="d-flex flex-row justify-content-between">
<div></div>

View File

@ -114,5 +114,6 @@ export function makeNounSelection(entry: T.NounEntry, old: T.NounSelection | und
adjectives: (!dynamicComplement && old) ? old.adjectives : [],
possesor: !dynamicComplement ? old?.possesor : undefined,
dynamicComplement,
demonstrative: undefined,
};
}

View File

@ -103,21 +103,23 @@ function VPPicker({ opts, vps, onChange, entryFeeder }: {
heading={roles.king === "subject"
? <div className="h5 text-center">
Subj. <span onClick={() => setShowingExplanation({ role: "king", item: "subject" })}>{roleIcon.king}</span>
{/* {(rendered && rendered.whatsAdjustable !== "servant") &&
<span onClick={() => adjustVps({ type: "toggle king remove" })} className="mx-2 clickable">
{!VPS?.form.removeKing ? "🫣" : "🚫" }
</span>
} */}
{(rendered && rendered.whatsAdjustable !== "servant") &&
<KingRemover
onChange={() => adjustVps({ type: "toggle king remove" })}
showKing={!VPS?.form.removeKing}
/>
}
</div>
: <div className="h5 text-center">
Subj.
{` `}
<span className="clickable" onClick={() => setShowingExplanation({ role: "servant", item: "subject" })}>{roleIcon.servant}</span>
{` `}
{(rendered && rendered.whatsAdjustable !== "king") &&
<span onClick={() => adjustVps({ type: "toggle servant shrink" })} className="mx-2 clickable">
{!servantIsShrunk ? "🪄" : "👶"}
</span>
{(rendered && rendered.whatsAdjustable !== "king") &&
<ServantShrinker
shrunk={servantIsShrunk}
onClick={() => adjustVps({ type: "toggle servant shrink" })}
/>
}
</div>}
entryFeeder={entryFeeder}
@ -146,11 +148,12 @@ function VPPicker({ opts, vps, onChange, entryFeeder }: {
heading={roles.king === "object"
? <div className="h5 text-center">
Obj. <span onClick={() => setShowingExplanation({ role: "king", item: "object" })}>{roleIcon.king}</span>
{/* {(rendered && rendered.whatsAdjustable !== "servant") &&
<span onClick={() => adjustVps({ type: "toggle king remove" })} className="mx-2 clickable">
{!VPS?.form.removeKing ? "🙈" : "🚫"}
</span>
} */}
{(rendered && rendered.whatsAdjustable !== "servant") &&
<KingRemover
onChange={() => adjustVps({ type: "toggle king remove" })}
showKing={!VPS?.form.removeKing}
/>
}
</div>
: <div className="h5 text-center">
Obj.
@ -158,9 +161,7 @@ function VPPicker({ opts, vps, onChange, entryFeeder }: {
<span className="clickable" onClick={() => setShowingExplanation({ role: "servant", item: "object" })}>{roleIcon.servant}</span>
{` `}
{(rendered && rendered.whatsAdjustable !== "king") &&
<span onClick={() => adjustVps({ type: "toggle servant shrink" })} className="mx-2 clickable">
{!servantIsShrunk ? "🪄" : "👶"}
</span>
<ServantShrinker shrunk={servantIsShrunk} onClick={() => adjustVps({ type: "toggle servant shrink" })} />
}
</div>}
entryFeeder={entryFeeder}
@ -213,4 +214,28 @@ function VPPicker({ opts, vps, onChange, entryFeeder }: {
</div>;
}
function ServantShrinker({ shrunk, onClick }: {
shrunk: boolean;
onClick: () => void;
}) {
return <span className="mx-2 clickable" onClick={onClick}>
{!shrunk ? "🪄" : "👶"}
</span>;
}
function KingRemover({ showKing, onChange }: {
showKing: boolean;
onChange: () => void;
}) {
return <span className="form-check form-check-inline ml-3">
<input
checked={showKing}
onChange={onChange}
className="form-check-input"
type="checkbox"
id="showKingCheck"
/>
</span>;
}
export default VPPicker;

View File

@ -71,9 +71,24 @@ export function renderNounSelection(n: T.NounSelection, inflected: boolean, role
ps: pashto,
e: english,
possesor: renderPossesor(n.possesor, role),
demonstrative: renderDemonstrative(n.demonstrative, inflected && n.number === "plural"),
};
}
function renderDemonstrative(demonstrative: T.DemonstrativeSelection | undefined, plurInflected: boolean): T.Rendered<T.DemonstrativeSelection> | undefined {
if (!demonstrative) {
return undefined;
}
return {
...demonstrative,
ps: demonstrative.demonstrative === "daa"
? (plurInflected ? { p: "دې", f: "de" } : { p: "دا", f: "daa" })
: demonstrative.demonstrative === "dagha"
? (plurInflected ? { p: "دغه", f: "dágha" } : { p: "دغو", f: "dágho" })
: (plurInflected ? { p: "هغه", f: "hágha" } : { p: "هغو", f: "hágho" })
}
}
function renderPronounSelection(p: T.PronounSelection, inflected: boolean, englishInflected: boolean, role: "servant" | "king" | "none"): T.Rendered<T.PronounSelection> {
const [row, col] = getVerbBlockPosFromPerson(p.person);
return {

View File

@ -649,6 +649,13 @@ export type NounSelection = {
dynamicComplement?: boolean,
adjectives: AdjectiveSelection[],
possesor: undefined | PossesorSelection,
demonstrative: undefined | DemonstrativeSelection,
};
export type DemonstrativeSelection = {
type: "demonstrative",
demonstrative: "daa" | "hagha" | "dagha",
hideNoun: boolean,
};
export type AdverbSelection = {
@ -708,6 +715,7 @@ export type Rendered<
| AdjectiveSelection
| SandwichSelection<Sandwich>
| ComplementSelection
| DemonstrativeSelection
| ComplementSelection["selection"]
| UnselectedComplementSelection
| undefined
@ -757,6 +765,13 @@ export type Rendered<
inflected: boolean,
person: Person,
}
: T extends DemonstrativeSelection
? {
type: "demonstrative",
demonstrative: DemonstrativeSelection["demonstrative"],
hideNoun: boolean,
ps: PsString,
}
: T extends ComplementSelection
? {
type: "complement",
@ -797,6 +812,7 @@ export type Rendered<
shrunken: boolean,
np: Rendered<NPSelection>,
},
demonstrative?: Rendered<DemonstrativeSelection>,
};
export type EPSelectionState = {