diff --git a/app/web/src/nova/ed/panel/side/prop-comp.tsx b/app/web/src/nova/ed/panel/side/prop-comp.tsx index 2dc5cc3d..8e54b45d 100644 --- a/app/web/src/nova/ed/panel/side/prop-comp.tsx +++ b/app/web/src/nova/ed/panel/side/prop-comp.tsx @@ -7,7 +7,7 @@ import { } from "@minoru/react-dnd-treeview"; import { FC } from "react"; 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 { EDGlobal, EdMeta } from "../../logic/ed-global"; import { EdPropCompTreeItem, PropItem } from "./prop-comp/tree-item"; @@ -18,7 +18,7 @@ const propRef = { export const EdSidePropComp: FC<{ meta: EdMeta }> = ({ meta }) => { const p = useGlobal(EDGlobal, "EDITOR"); - + const local = useLocal({}); const item = meta?.item as IItem; if (!item) return null; const TypedTree = DNDTree; @@ -94,7 +94,13 @@ export const EdSidePropComp: FC<{ meta: EdMeta }> = ({ meta }) => { }); }); }} - render={EdPropCompTreeItem} + render={(node, params) => ( + + )} rootId={"root"} classes={treeClasses} dropTargetOffset={10} diff --git a/app/web/src/nova/ed/panel/side/prop-comp/edit-script.tsx b/app/web/src/nova/ed/panel/side/prop-comp/edit-script.tsx new file mode 100644 index 00000000..cc8bbed6 --- /dev/null +++ b/app/web/src/nova/ed/panel/side/prop-comp/edit-script.tsx @@ -0,0 +1,5 @@ +import { PG } from "../../../logic/ed-global"; + +export const createEditScript = (p: PG, name: string) => { + return () => {}; +}; diff --git a/app/web/src/nova/ed/panel/side/prop-comp/prop-popover.tsx b/app/web/src/nova/ed/panel/side/prop-comp/prop-popover.tsx new file mode 100644 index 00000000..380d3350 --- /dev/null +++ b/app/web/src/nova/ed/panel/side/prop-comp/prop-popover.tsx @@ -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 ( +
+
+ {[ + { label: "TXT", type: "text" }, + { label: "OPT", type: "option" }, + { label: "JSX", type: "content-element" }, + ].map((e) => { + return ( +
{ + mmeta.set("type", e.type as any); + }} + > + {e.label} +
+ ); + })} +
+
+
Name
+ { + 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 + >; + 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(); + } + }} + /> +
+ + {type === "content-element" && ( +
+
+ Visible +
+ +
+ EDIT CODE +
+
+ )} + + {type !== "content-element" && ( + <> +
.label { + padding-top: 0.75rem; + padding-bottom: 0.75rem; + } + ` + )} + > +
+ Generator +
+
+ EDIT CODE +
+
+
+ Visible +
+
+ EDIT CODE +
+
+ +
+
VALUE
+
+ EDIT CODE +
+
+ + )} + + {type === "option" && ( +
+
MODE
+ +
+ {["button", "dropdown"].map((e) => ( +
{ + 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} +
+ ))} +
+
+ )} + + {type === "option" && ( +
+
OPTIONS
+ +
+ EDIT CODE +
+
+ )} +
+ ); +}; + +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", +]; diff --git a/app/web/src/nova/ed/panel/side/prop-comp/tree-item.tsx b/app/web/src/nova/ed/panel/side/prop-comp/tree-item.tsx index 5c409f34..2ac09ee1 100644 --- a/app/web/src/nova/ed/panel/side/prop-comp/tree-item.tsx +++ b/app/web/src/nova/ed/panel/side/prop-comp/tree-item.tsx @@ -1,6 +1,9 @@ import { NodeRender } from "@minoru/react-dnd-treeview"; +import { FC } from "react"; import { MItem } from "../../../../../utils/types/item"; import { FMCompDef, FNCompDef } from "../../../../../utils/types/meta-fn"; +import { Popover } from "../../../../../utils/ui/popover"; +import { EdPropPopover, propPopover } from "./prop-popover"; export type PropItem = { name: string; @@ -9,8 +12,12 @@ export type PropItem = { prop: FNCompDef; }; -export const EdPropCompTreeItem: NodeRender = (node, params) => { - if (node.id === "root" || node.id === 'proot') { +export const EdPropCompTreeItem: FC<{ + node: Parameters>[0]; + params: Parameters>[1]; + render: () => void; +}> = ({ node, params, render }) => { + if (node.id === "root" || node.id === "proot") { return <>; } return ( @@ -34,9 +41,27 @@ export const EdPropCompTreeItem: NodeRender = (node, params) => { > -
- {node.text} -
+ {node.data && ( + { + if (!open) { + propPopover.name = ""; + } else { + propPopover.name = node.text; + } + render(); + }} + content={} + className="flex-1 pl-1 hover:bg-blue-100 cursor-pointer" + > + {node.text} + + )} ); };