wip fix prop

This commit is contained in:
Rizky 2023-12-04 18:52:52 +07:00
parent 73dba58f36
commit d92ae3305e
4 changed files with 294 additions and 8 deletions

View File

@ -7,7 +7,7 @@ import {
} from "@minoru/react-dnd-treeview"; } from "@minoru/react-dnd-treeview";
import { FC } from "react"; import { FC } from "react";
import { HTML5Backend } from "react-dnd-html5-backend"; import { HTML5Backend } from "react-dnd-html5-backend";
import { useGlobal } from "web-utils"; import { useGlobal, useLocal } from "web-utils";
import { IItem } from "../../../../utils/types/item"; import { IItem } from "../../../../utils/types/item";
import { EDGlobal, EdMeta } from "../../logic/ed-global"; import { EDGlobal, EdMeta } from "../../logic/ed-global";
import { EdPropCompTreeItem, PropItem } from "./prop-comp/tree-item"; import { EdPropCompTreeItem, PropItem } from "./prop-comp/tree-item";
@ -18,7 +18,7 @@ const propRef = {
export const EdSidePropComp: FC<{ meta: EdMeta }> = ({ meta }) => { export const EdSidePropComp: FC<{ meta: EdMeta }> = ({ meta }) => {
const p = useGlobal(EDGlobal, "EDITOR"); const p = useGlobal(EDGlobal, "EDITOR");
const local = useLocal({});
const item = meta?.item as IItem; const item = meta?.item as IItem;
if (!item) return null; if (!item) return null;
const TypedTree = DNDTree<PropItem>; const TypedTree = DNDTree<PropItem>;
@ -94,7 +94,13 @@ export const EdSidePropComp: FC<{ meta: EdMeta }> = ({ meta }) => {
}); });
}); });
}} }}
render={EdPropCompTreeItem} render={(node, params) => (
<EdPropCompTreeItem
node={node}
params={params}
render={local.render}
/>
)}
rootId={"root"} rootId={"root"}
classes={treeClasses} classes={treeClasses}
dropTargetOffset={10} dropTargetOffset={10}

View File

@ -0,0 +1,5 @@
import { PG } from "../../../logic/ed-global";
export const createEditScript = (p: PG, name: string) => {
return () => {};
};

View File

@ -0,0 +1,250 @@
import { FC } from "react";
import { FMCompDef, FNCompDef } from "../../../../../utils/types/meta-fn";
import { useGlobal, useLocal } from "web-utils";
import { TypedMap } from "yjs-types";
import { createEditScript } from "./edit-script";
import { EDGlobal } from "../../../logic/ed-global";
export const propPopover = {
name: "",
};
export const EdPropPopover: FC<{ mprop: FMCompDef; name: string }> = ({
mprop,
name,
}) => {
const p = useGlobal(EDGlobal, "EDITOR");
const mmeta = mprop.get("meta");
const local = useLocal({
name,
});
if (!mmeta) return null;
const type = mmeta.get("type");
return (
<div
className={cx(
"flex text-sm flex-col items-stretch space-y-1 py-1 w-[300px]"
)}
>
<div className="px-2 py-1 flex space-x-1">
{[
{ label: "TXT", type: "text" },
{ label: "OPT", type: "option" },
{ label: "JSX", type: "content-element" },
].map((e) => {
return (
<div
key={e.type}
className={cx(
type === e.type
? "bg-blue-500 text-white"
: "hover:bg-blue-100",
" px-2 cursor-pointer"
)}
onClick={() => {
mmeta.set("type", e.type as any);
}}
>
{e.label}
</div>
);
})}
</div>
<div className="border-t border-slate-300 px-2 pt-2 pb-1 flex flex-col items-stretch">
<div className="uppercase text-xs text-slate-500">Name</div>
<input
spellCheck={false}
type="text"
className="p-1 outline-none border focus:border-blue-500"
value={local.name}
onChange={(e) => {
local.name = e.currentTarget.value
.toLowerCase()
.replace(/\W/gi, "_");
local.render();
}}
onBlur={() => {
if (local.name !== name) {
const keys = Object.keys(mprop.parent?.toJSON());
if ([...keys, ...keywords].includes(local.name)) {
alert(`Cannot use "${local.name}" as name`);
local.name = name;
local.render();
return;
}
mprop.doc?.transact(() => {
const parent = mprop.parent as TypedMap<
Record<string, FMCompDef>
>;
parent.set(local.name, parent.get(name)?.clone() as any);
parent.delete(name);
});
propPopover.name = local.name;
local.render();
}
}}
onKeyDown={(e) => {
if (e.key === "Enter") {
e.currentTarget.blur();
}
}}
/>
</div>
{type === "content-element" && (
<div className="border-t border-slate-300 pl-2 pt-1 flex justify-between items-center">
<div className="uppercase text-xs label self-stretch flex items-center">
Visible
</div>
<div
className="m-1 px-1 bg-white cursor-pointer hover:bg-blue-500 hover:text-white hover:border-blue-500 font-mono border border-slate-300 text-[11px]"
onClick={createEditScript(p, "master-visible")}
>
EDIT CODE
</div>
</div>
)}
{type !== "content-element" && (
<>
<div
className={cx(
"border-t border-slate-300 pl-2 flex justify-between items-center",
css`
margin-bottom: -0.25rem !important;
> .label {
padding-top: 0.75rem;
padding-bottom: 0.75rem;
}
`
)}
>
<div className="uppercase text-xs label self-stretch flex items-center">
Generator
</div>
<div
className="m-1 px-1 bg-white cursor-pointer hover:bg-blue-500 hover:text-white hover:border-blue-500 font-mono border border-slate-300 text-[11px] flex "
onClick={createEditScript(p, "master-gen")}
>
EDIT CODE
</div>
<div className=" border-l border-slate-300 mr-2 self-stretch"></div>
<div className="uppercase text-xs label self-stretch flex items-center">
Visible
</div>
<div
className="m-1 px-1 bg-white cursor-pointer hover:bg-blue-500 hover:text-white hover:border-blue-500 font-mono border border-slate-300 text-[11px]"
onClick={createEditScript(p, "master-visible")}
>
EDIT CODE
</div>
</div>
<div className="border-t border-slate-300 pl-2 pt-1 flex justify-between items-center">
<div className="uppercase text-xs">VALUE</div>
<div
className="m-1 px-1 bg-white cursor-pointer hover:bg-blue-500 hover:text-white hover:border-blue-500 font-mono border border-slate-300 text-[11px]"
onClick={createEditScript(p, "master-value")}
>
EDIT CODE
</div>
</div>
</>
)}
{type === "option" && (
<div className="border-t border-slate-300 pl-2 pt-1 flex justify-between items-center select-none">
<div className="uppercase text-xs">MODE</div>
<div className="flex pr-1">
{["button", "dropdown"].map((e) => (
<div
key={e}
onClick={() => {
const meta = mprop.get("meta");
if (meta) {
meta.set("option_mode", e as any);
}
}}
className={cx(
"m-1 px-1 capitalize text-center cursor-pointer font-mono border border-slate-300 text-[11px]",
e === mmeta.get("option_mode") ||
(e === "button" && !mmeta.get("option_mode"))
? "bg-blue-500 text-white"
: `hover:bg-blue-500 hover:text-white bg-white hover:border-blue-500`
)}
>
{e}
</div>
))}
</div>
</div>
)}
{type === "option" && (
<div className="border-t border-slate-300 pl-2 pt-1 flex justify-between items-center">
<div className="uppercase text-xs">OPTIONS</div>
<div
className="m-1 px-1 bg-white cursor-pointer hover:bg-blue-500 hover:text-white hover:border-blue-500 font-mono border border-slate-300 text-[11px]"
onClick={createEditScript(p, "master-option")}
>
EDIT CODE
</div>
</div>
)}
</div>
);
};
const keywords = [
"await",
"break",
"case",
"catch",
"class",
"const",
"continue",
"debugger",
"default",
"delete",
"do",
"else",
"enum",
"export",
"extends",
"false",
"finally",
"for",
"function",
"if",
"implements",
"import",
"in",
"instanceof",
"interface",
"let",
"new",
"null",
"package",
"private",
"protected",
"public",
"return",
"super",
"switch",
"static",
"this",
"throw",
"try",
"true",
"typeof",
"var",
"void",
"while",
"with",
"yield",
];

View File

@ -1,6 +1,9 @@
import { NodeRender } from "@minoru/react-dnd-treeview"; import { NodeRender } from "@minoru/react-dnd-treeview";
import { FC } from "react";
import { MItem } from "../../../../../utils/types/item"; import { MItem } from "../../../../../utils/types/item";
import { FMCompDef, FNCompDef } from "../../../../../utils/types/meta-fn"; import { FMCompDef, FNCompDef } from "../../../../../utils/types/meta-fn";
import { Popover } from "../../../../../utils/ui/popover";
import { EdPropPopover, propPopover } from "./prop-popover";
export type PropItem = { export type PropItem = {
name: string; name: string;
@ -9,8 +12,12 @@ export type PropItem = {
prop: FNCompDef; prop: FNCompDef;
}; };
export const EdPropCompTreeItem: NodeRender<PropItem> = (node, params) => { export const EdPropCompTreeItem: FC<{
if (node.id === "root" || node.id === 'proot') { node: Parameters<NodeRender<PropItem>>[0];
params: Parameters<NodeRender<PropItem>>[1];
render: () => void;
}> = ({ node, params, render }) => {
if (node.id === "root" || node.id === "proot") {
return <></>; return <></>;
} }
return ( return (
@ -34,9 +41,27 @@ export const EdPropCompTreeItem: NodeRender<PropItem> = (node, params) => {
></path> ></path>
</svg> </svg>
</div> </div>
<div className="flex-1 pl-1 hover:bg-blue-100 cursor-pointer"> {node.data && (
{node.text} <Popover
</div> placement="left-start"
autoFocus={false}
backdrop={false}
open={propPopover.name === node.text}
popoverClassName="bg-white shadow-lg border border-slate-300"
onOpenChange={(open) => {
if (!open) {
propPopover.name = "";
} else {
propPopover.name = node.text;
}
render();
}}
content={<EdPropPopover mprop={node.data.mprop} name={node.text} />}
className="flex-1 pl-1 hover:bg-blue-100 cursor-pointer"
>
{node.text}
</Popover>
)}
</div> </div>
); );
}; };