diff --git a/app/web/src/nova/ed/ed-base.tsx b/app/web/src/nova/ed/ed-base.tsx index 71ec5fca..6155823b 100644 --- a/app/web/src/nova/ed/ed-base.tsx +++ b/app/web/src/nova/ed/ed-base.tsx @@ -8,14 +8,13 @@ import { edInit } from "./logic/ed-init"; import { edRoute } from "./logic/ed-route"; import { edUndoManager } from "./logic/ed-undo"; import { EdPane } from "./panel/main/pane-resize"; +import { EdPopApi } from "./panel/popup/api/api-server"; import { EdPopCode } from "./panel/popup/code/code"; import { EdPopCompGroup } from "./panel/popup/comp/comp-group"; +import { EdPopComp } from "./panel/popup/comp/comp-popup"; import { EdPopPage } from "./panel/popup/page/page-popup"; import { EdPopScript } from "./panel/popup/script/pop-script"; import { EdPopSite } from "./panel/popup/site/site-popup"; -import { EdScriptInit } from "./panel/script/monaco/init"; -import { EdPopApi } from "./panel/popup/api/api-server"; -import { EdPopComp } from "./panel/popup/comp/comp-popup"; export const EdBase = () => { const p = useGlobal(EDGlobal, "EDITOR"); @@ -57,7 +56,6 @@ export const EdBase = () => { - ); diff --git a/app/web/src/nova/ed/logic/ed-global.ts b/app/web/src/nova/ed/logic/ed-global.ts index 94f0cff4..76015e97 100644 --- a/app/web/src/nova/ed/logic/ed-global.ts +++ b/app/web/src/nova/ed/logic/ed-global.ts @@ -10,6 +10,7 @@ import { DComp, DPage } from "../../../utils/types/root"; import { ISection } from "../../../utils/types/section"; import { IText, MText } from "../../../utils/types/text"; import { PageItem } from "../panel/popup/page/page-tree"; +import { FMCompDef } from "../../../utils/types/meta-fn"; export const EmptySite = { id: "", @@ -24,7 +25,7 @@ export const EmptySite = { export type ESite = typeof EmptySite; export type EPage = typeof EmptyPage; export type EComp = typeof EmptyComp; - +export type PropFieldKind = "visible" | "gen" | "value" | "option"; export type ISingleScope = { p: string[]; n: string; @@ -63,7 +64,6 @@ const target = { }; export const active = { hover_id: "", - prop_name: "", text: { id: "", content: "" }, get item_id() { if (target.active_id === false) { @@ -234,6 +234,9 @@ export const EDGlobal = { script: { open: false, mode: "js" as "js" | "css" | "html", + type: "item" as "item" | "prop", + prop_kind: "" as PropFieldKind, + prop_name: "", }, site: null as null | ((site_id: string) => void | Promise), site_form: null as null | { diff --git a/app/web/src/nova/ed/panel/popup/script/monaco.tsx b/app/web/src/nova/ed/panel/popup/script/monaco.tsx index 18e771db..222021a1 100644 --- a/app/web/src/nova/ed/panel/popup/script/monaco.tsx +++ b/app/web/src/nova/ed/panel/popup/script/monaco.tsx @@ -35,6 +35,7 @@ export const ScriptMonaco = () => { meta = p.comp.list[active.comp_id].meta[active.item_id]; } + let val = ""; useEffect(() => { return () => { p.script.do_edit = async () => {}; @@ -43,11 +44,6 @@ export const ScriptMonaco = () => { useEffect(() => { if (local.monaco && local.editor) { - const val: string = ( - typeof adv[p.ui.popup.script.mode] === "string" - ? adv[p.ui.popup.script.mode] - : "" - ) as any; local.monaco.editor.getModels().forEach((model) => { const uri = model.uri.toString(); if ( @@ -73,24 +69,12 @@ export const ScriptMonaco = () => { local.render(); }); } - }, [active.item_id]); + }, [active.item_id, val]); if (!meta) return null; const item = meta.item; const adv = item.adv || {}; - let val: string = ( - typeof adv[p.ui.popup.script.mode] === "string" - ? adv[p.ui.popup.script.mode] - : "" - ) as any; - - if (active.prop_name && item.type === "item" && item.component) { - const prop = item.component.props[active.prop_name]; - if (prop) { - val = prop.value; - } - } const doEdit = async (newval: string, all?: boolean) => { if (local.editor && jscript.prettier.standalone) { @@ -120,6 +104,14 @@ export const ScriptMonaco = () => { let mitem = meta.mitem; + if (p.ui.popup.script.type === "item") { + val = ( + typeof adv[p.ui.popup.script.mode] === "string" + ? adv[p.ui.popup.script.mode] + : "" + ) as any; + } + if (!mitem) { active.item_id = ""; return
no mitem
; @@ -136,6 +128,18 @@ export const ScriptMonaco = () => { } } + if (p.ui.popup.script.type === "prop") { + const mprops = mitem?.get("component")?.get("props"); + if (mprops) { + const mprop = mprops.get(p.ui.popup.script.prop_name); + if (mprop) { + if (p.ui.popup.script.prop_kind === "value") { + val = mprop.get("value"); + } + } + } + } + return ( { onOpenChange={(open) => { if (!open) { p.ui.popup.script.open = false; - active.prop_name = ""; p.render(); } }} diff --git a/app/web/src/nova/ed/panel/popup/script/workbench.tsx b/app/web/src/nova/ed/panel/popup/script/workbench.tsx index 185b2ff2..d5c1865c 100644 --- a/app/web/src/nova/ed/panel/popup/script/workbench.tsx +++ b/app/web/src/nova/ed/panel/popup/script/workbench.tsx @@ -8,8 +8,8 @@ export const ScriptWorkbench = () => {
- {active.prop_name ? ( -
{active.prop_name}
+ {p.ui.popup.script.type === "prop" ? ( + <> ) : ( <> {[ 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 8e54b45d..9e814a41 100644 --- a/app/web/src/nova/ed/panel/side/prop-comp.tsx +++ b/app/web/src/nova/ed/panel/side/prop-comp.tsx @@ -9,8 +9,10 @@ import { FC } from "react"; import { HTML5Backend } from "react-dnd-html5-backend"; import { useGlobal, useLocal } from "web-utils"; import { IItem } from "../../../../utils/types/item"; +import { FMCompDef } from "../../../../utils/types/meta-fn"; import { EDGlobal, EdMeta } from "../../logic/ed-global"; import { EdPropCompTreeItem, PropItem } from "./prop-comp/tree-item"; +import { propPopover } from "./prop-comp/prop-popover"; const propRef = { el: null as any, @@ -111,7 +113,31 @@ export const EdSidePropComp: FC<{ meta: EdMeta }> = ({ meta }) => { dragPreviewRender={() => <>} /> -
+
{ + if (mprops) { + const indexes: (number | undefined)[] = []; + mprops.forEach((e) => indexes.push(e.get("idx"))); + let idx: any = (indexes.sort().pop() || 0) + 1; + const name = `prop_${idx + 1}`; + const map = new Y.Map() as FMCompDef; + syncronize(map, { + idx: idx, + name, + type: "string", + value: '"hello"', + valueBuilt: '"hello"', + meta: { + type: "text", + }, + }); + mprops.set(name, map); + propPopover.name = name; + p.render(); + } + }} + > + New Prop
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 index cc8bbed6..b93d8d84 100644 --- 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 @@ -1,5 +1,25 @@ -import { PG } from "../../../logic/ed-global"; +import { MouseEventHandler } from "react"; +import { FMCompDef } from "../../../../../utils/types/meta-fn"; +import { PG, PropFieldKind } from "../../../logic/ed-global"; -export const createEditScript = (p: PG, name: string) => { - return () => {}; +export const createEditScript = ( + p: PG, + kind: PropFieldKind, + mprop: FMCompDef, + name: string +) => { + return ((e) => { + e.preventDefault(); + e.stopPropagation(); + + const meta = mprop.get("meta"); + if (meta) { + p.ui.popup.script.mode = "js"; + p.ui.popup.script.open = true; + p.ui.popup.script.type = "prop"; + p.ui.popup.script.prop_kind = kind; + p.ui.popup.script.prop_name = name; + p.render(); + } + }) as MouseEventHandler; }; 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 index 380d3350..c0e57138 100644 --- 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 @@ -58,6 +58,7 @@ export const EdPropPopover: FC<{ mprop: FMCompDef; name: string }> = ({ type="text" className="p-1 outline-none border focus:border-blue-500" value={local.name} + autoFocus onChange={(e) => { local.name = e.currentTarget.value .toLowerCase() @@ -100,7 +101,7 @@ export const EdPropPopover: FC<{ mprop: FMCompDef; name: string }> = ({
EDIT CODE
@@ -127,7 +128,7 @@ export const EdPropPopover: FC<{ mprop: FMCompDef; name: string }> = ({
EDIT CODE
@@ -137,7 +138,7 @@ export const EdPropPopover: FC<{ mprop: FMCompDef; name: string }> = ({
EDIT CODE
@@ -147,7 +148,7 @@ export const EdPropPopover: FC<{ mprop: FMCompDef; name: string }> = ({
VALUE
EDIT CODE
@@ -190,7 +191,7 @@ export const EdPropPopover: FC<{ mprop: FMCompDef; name: string }> = ({
EDIT CODE
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 2ac09ee1..338c552c 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 @@ -4,6 +4,7 @@ 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"; +import { TypedMap } from "yjs-types"; export type PropItem = { name: string; @@ -62,6 +63,42 @@ export const EdPropCompTreeItem: FC<{ {node.text} )} +
{ + e.preventDefault(); + e.stopPropagation(); + if (confirm("Are you sure ?")) { + const mprop = node.data?.mprop; + if (mprop){ + const parent = mprop.parent as TypedMap>; + parent.forEach((m, idx) => { + if (mprop === m) { + parent.delete(idx); + } + });} + } + }} + > + +
); }; + +const Trash = () => ( + + + +); diff --git a/app/web/src/nova/ed/panel/tree/node/item/action.tsx b/app/web/src/nova/ed/panel/tree/node/item/action.tsx index 0398c661..3c4015ec 100644 --- a/app/web/src/nova/ed/panel/tree/node/item/action.tsx +++ b/app/web/src/nova/ed/panel/tree/node/item/action.tsx @@ -51,6 +51,7 @@ export const EdTreeAction = ({ )} onClick={() => { p.ui.popup.script.open = true; + p.ui.popup.script.type = "item"; p.ui.popup.script.mode = (mode || "js") as any; p.render(); }} diff --git a/app/web/src/nova/view/render/meta/script.tsx b/app/web/src/nova/view/render/meta/script.tsx index 865f0a0c..67c5ad61 100644 --- a/app/web/src/nova/view/render/meta/script.tsx +++ b/app/web/src/nova/view/render/meta/script.tsx @@ -1,5 +1,6 @@ import hash_sum from "hash-sum"; -import { FC, ReactNode, Suspense, useEffect } from "react"; +import { FC, ReactNode, useEffect } from "react"; +import { useLocal } from "web-utils"; import { produceCSS } from "../../../../utils/css/gen"; import { createAPI, createDB } from "../../../../utils/script/init-api"; import { IItem } from "../../../../utils/types/item"; @@ -12,7 +13,6 @@ import { createLocal } from "./script/create-local"; import { createPassProp } from "./script/create-pass-prop"; import { ErrorBox } from "./script/error-box"; import { mergeScopeUpwards } from "./script/merge-upward"; -import { useLocal } from "web-utils"; const renderLimit = {} as Record< string, diff --git a/app/web/src/render/editor/panel/e-main-editor.tsx b/app/web/src/render/editor/panel/e-main-editor.tsx index 9d38f3f1..1d468892 100644 --- a/app/web/src/render/editor/panel/e-main-editor.tsx +++ b/app/web/src/render/editor/panel/e-main-editor.tsx @@ -5,7 +5,7 @@ import { mobileCSS } from "../elements/e-page"; import { editorStyle } from "../elements/style"; import { EditorGlobal } from "../logic/global"; import { Toolbar } from "./toolbar/Toolbar"; -import { EdScriptInit } from "../../../nova/ed/panel/script/monaco/init"; +import { EdScriptInit } from "./script/init"; const ETree = lazy(async () => ({ default: (await import("./tree/tree")).ETree, diff --git a/app/web/src/nova/ed/panel/script/monaco/init.tsx b/app/web/src/render/editor/panel/script/init.tsx similarity index 95% rename from app/web/src/nova/ed/panel/script/monaco/init.tsx rename to app/web/src/render/editor/panel/script/init.tsx index 8fcd4d02..0fece4c2 100644 --- a/app/web/src/nova/ed/panel/script/monaco/init.tsx +++ b/app/web/src/render/editor/panel/script/init.tsx @@ -1,7 +1,7 @@ import { ReactElement, ReactNode } from "react"; import { useLocal } from "web-utils"; -import { jscript } from "../../../../../utils/script/jscript"; -import { Loading } from "../../../../../utils/ui/loading"; +import { jscript } from "../../../../utils/script/jscript"; +import { Loading } from "../../../../utils/ui/loading"; export const EdScriptInit = () => { const Editor = jscript.editor; diff --git a/app/web/src/nova/ed/panel/script/monaco/monaco.tsx b/app/web/src/render/editor/panel/script/monaco.tsx similarity index 93% rename from app/web/src/nova/ed/panel/script/monaco/monaco.tsx rename to app/web/src/render/editor/panel/script/monaco.tsx index 42680449..225fb87e 100644 --- a/app/web/src/nova/ed/panel/script/monaco/monaco.tsx +++ b/app/web/src/render/editor/panel/script/monaco.tsx @@ -1,8 +1,8 @@ import type { Editor } from "@monaco-editor/react"; import { ReactElement } from "react"; -import { jsMount } from "../../../../../utils/script/mount"; -import { monacoTypings } from "../../../../../utils/script/typings"; -import { Modal } from "../../../../../utils/ui/modal"; +import { jsMount } from "../../../../utils/script/mount"; +import { monacoTypings } from "../../../../utils/script/typings"; +import { Modal } from "../../../../utils/ui/modal"; import { EdMonacoWrap } from "./init"; const monacoState = {} as Record; diff --git a/app/web/src/utils/script/mount.tsx b/app/web/src/utils/script/mount.tsx index 611fea2a..00f7bbf5 100644 --- a/app/web/src/utils/script/mount.tsx +++ b/app/web/src/utils/script/mount.tsx @@ -4,8 +4,8 @@ import { MonacoJsxSyntaxHighlight, getWorker, } from "monaco-jsx-syntax-highlight-v2"; -import { jscript } from "./jscript"; import { PG, active } from "../../nova/ed/logic/ed-global"; +import { jscript } from "./jscript"; export type MonacoEditor = Parameters[0]; type Monaco = Parameters[1]; @@ -13,7 +13,7 @@ type CompilerOptions = Parameters< Parameters[1]["languages"]["typescript"]["typescriptDefaults"]["setCompilerOptions"] >[0]; -export const jsMount = async (editor: MonacoEditor, monaco: Monaco, p: PG) => { +export const jsMount = async (editor: MonacoEditor, monaco: Monaco, p?: PG) => { const m = monaco as any; if (!m.customJSMounted) { m.customJSMounted = true; @@ -33,59 +33,63 @@ export const jsMount = async (editor: MonacoEditor, monaco: Monaco, p: PG) => { moduleResolution: monaco.languages.typescript.ModuleResolutionKind.NodeJs, }; - monaco.editor.registerEditorOpener({ - openCodeEditor(source, r, selectionOrPosition) { - p.ui.popup.script.mode === "js"; - const cpath = r.path.substring(`scope~`.length).split("__"); - const [comp_id, prev_comp_id, prev_item_id] = cpath[0].split("~"); - if (cpath[1]) { - const path = cpath[1].split("~"); - const type = path[0] as "prop" | "passprop" | "local"; - const id = path[path.length - 1].replace(".d.ts", ""); + if (p) { + monaco.editor.registerEditorOpener({ + openCodeEditor(source, r, selectionOrPosition) { + if (p) { + p.ui.popup.script.mode === "js"; + const cpath = r.path.substring(`scope~`.length).split("__"); + const [comp_id, prev_comp_id, prev_item_id] = cpath[0].split("~"); + if (cpath[1]) { + const path = cpath[1].split("~"); + const type = path[0] as "prop" | "passprop" | "local"; + const id = path[path.length - 1].replace(".d.ts", ""); - if (type === "prop") { - active.prop_name = path[1]; + if (type === "prop") { + p.ui.popup.script.prop_name = path[1]; - if ( - !prev_comp_id && - !prev_item_id && - active.instance.item_id && - active.comp_id - ) { - active.item_id = active.instance.item_id; - active.comp_id = active.instance.comp_id; - active.instance.item_id = ""; - active.instance.comp_id = ""; + if ( + !prev_comp_id && + !prev_item_id && + active.instance.item_id && + active.comp_id + ) { + active.item_id = active.instance.item_id; + active.comp_id = active.instance.comp_id; + active.instance.item_id = ""; + active.instance.comp_id = ""; + p.render(); + } + + return false; + } + + if (comp_id) { + let meta = p.page.meta[id]; + if (active.comp_id) { + meta = p.comp.list[active.comp_id].meta[id]; + } + + active.instance.comp_id = active.comp_id; + active.instance.item_id = active.item_id; + + if (meta && meta.item.originalId) { + active.item_id = meta.item.originalId; + } else { + active.item_id = id; + } + active.comp_id = comp_id; + } else { + active.item_id = id; + } p.render(); } - - return false; } - if (comp_id) { - let meta = p.page.meta[id]; - if (active.comp_id) { - meta = p.comp.list[active.comp_id].meta[id]; - } - - active.instance.comp_id = active.comp_id; - active.instance.item_id = active.item_id; - - if (meta && meta.item.originalId) { - active.item_id = meta.item.originalId; - } else { - active.item_id = id; - } - active.comp_id = comp_id; - } else { - active.item_id = id; - } - p.render(); - } - - return false; - }, - }); + return false; + }, + }); + } monaco.languages.registerDocumentFormattingEditProvider("typescript", { async provideDocumentFormattingEdits(model, options, token) {