This commit is contained in:
Rizky 2023-12-09 11:17:28 +07:00
parent 1745a5eebc
commit 9e39b7d0fd
13 changed files with 170 additions and 295 deletions

View File

@ -119,7 +119,8 @@ export type EdMeta = {
mitem?: MItem; mitem?: MItem;
}; };
parent_mcomp?: { parent_mcomp?: {
mitem: MItem; minstance: MItem;
meta: EdMeta;
mcomp: MItem; mcomp: MItem;
}; };
el?: ReactElement; el?: ReactElement;

View File

@ -45,32 +45,34 @@ export const treeRebuild = async (p: PG, arg?: { note?: string }) => {
}); });
} }
sections.map((e) => { ldoc.doc.transact(() => {
if (p.page.root_id === "root") { sections.map((e) => {
p.page.entry.push(e.get("id")); if (p.page.root_id === "root") {
} p.page.entry.push(e.get("id"));
syncWalkMap(
{
note: "tree-rebuild layout",
comps: p.comp.list,
item_loading: p.ui.tree.item_loading,
meta: p.page.meta,
scope: p.page.scope,
},
{
is_layout: true,
mitem: e,
parent_item: { id: p.page.root_id },
tree_root_id: p.page.root_id,
skip_add_tree: true,
portal,
each(meta) {
if (meta.item.name === "content") {
p.page.root_id = meta.item.id;
}
},
} }
); syncWalkMap(
{
note: "tree-rebuild layout",
comps: p.comp.list,
item_loading: p.ui.tree.item_loading,
meta: p.page.meta,
scope: p.page.scope,
},
{
is_layout: true,
mitem: e,
parent_item: { id: p.page.root_id },
tree_root_id: p.page.root_id,
skip_add_tree: true,
portal,
each(meta) {
if (meta.item.name === "content") {
p.page.root_id = meta.item.id;
}
},
}
);
});
}); });
for (const [k, portal_out] of Object.entries(portal.out)) { for (const [k, portal_out] of Object.entries(portal.out)) {

View File

@ -87,37 +87,38 @@ const walkCompTree = async (p: PG, mitem: MItem, comp_id: string) => {
out: {} as Record<string, EdMeta>, out: {} as Record<string, EdMeta>,
}; };
syncWalkLoad(p, mitem, (id) => loadComponent(p, id)); syncWalkLoad(p, mitem, (id) => loadComponent(p, id));
mitem.doc?.transact(() => {
syncWalkMap(
{
note: "walk-comp",
comps: p.comp.list,
item_loading: p.ui.tree.item_loading,
meta,
tree,
component_not_found(id) {
setTimeout(() => {
if (loadcomp.pending.has(id) || p.comp.list[id]) {
waitUntil(() => !loadcomp.pending.has(id)).then(async () => {
walkCompTree(p, mitem, comp_id);
syncWalkMap( const { tree, meta } = await walkCompTree(p, mitem, comp_id);
{ p.comp.list[comp_id].tree = tree;
note: "walk-comp", p.comp.list[comp_id].meta = meta;
comps: p.comp.list, p.render();
item_loading: p.ui.tree.item_loading, });
meta, }
tree, }, 100);
component_not_found(id) { },
setTimeout(() => {
if (loadcomp.pending.has(id) || p.comp.list[id]) {
waitUntil(() => !loadcomp.pending.has(id)).then(async () => {
walkCompTree(p, mitem, comp_id);
const { tree, meta } = await walkCompTree(p, mitem, comp_id);
p.comp.list[comp_id].tree = tree;
p.comp.list[comp_id].meta = meta;
p.render();
});
}
}, 100);
}, },
}, {
{ mitem,
mitem, is_layout: false,
is_layout: false, parent_item: { id: "root" },
parent_item: { id: "root" }, portal,
portal, tree_root_id: "root",
tree_root_id: "root", }
} );
); });
return { tree, meta }; return { tree, meta };
}; };

View File

@ -81,7 +81,7 @@ export const syncWalkMap = (
each?: (meta: EdMeta) => void; each?: (meta: EdMeta) => void;
} }
) => { ) => {
const { mitem, parent_item, parent_mcomp } = arg; const { mitem, parent_item } = arg;
if (typeof mitem.get !== "function") { if (typeof mitem.get !== "function") {
return; return;
} }
@ -98,8 +98,8 @@ export const syncWalkMap = (
} }
let mapped = false; let mapped = false;
if (parent_mcomp && id) { if (arg.parent_mcomp && id) {
const fcomp = parent_mcomp.mitem.get("component"); const fcomp = arg.parent_mcomp.minstance.get("component");
if (fcomp) { if (fcomp) {
const ref_ids = fcomp.get("ref_ids"); const ref_ids = fcomp.get("ref_ids");
@ -162,14 +162,20 @@ export const syncWalkMap = (
if (ref_comp && mitem_comp) { if (ref_comp && mitem_comp) {
const mcomp = ref_comp.doc.getMap("map").get("root"); const mcomp = ref_comp.doc.getMap("map").get("root");
if (mcomp) { const minstance = arg.parent_mcomp
let ref_ids: Record<string, string> = item_comp.ref_ids; ? arg.parent_mcomp.minstance
if (!ref_ids) { : (mitem as MItem);
mitem_comp.set("ref_ids", new Y.Map() as any);
ref_ids = {};
}
let mref_ids = minstance.get("component")?.get("ref_ids");
if (!mref_ids) {
minstance.get("component")?.set("ref_ids", new Y.Map() as any);
mref_ids = minstance.get("component")?.get("ref_ids");
}
if (mcomp) {
const old_id = item.id; const old_id = item.id;
const ref_ids = mref_ids?.toJSON() || {};
mapItem(mcomp, item, ref_ids); mapItem(mcomp, item, ref_ids);
item.id = old_id; item.id = old_id;
@ -177,10 +183,11 @@ export const syncWalkMap = (
item, item,
mitem: mitem as MItem, mitem: mitem as MItem,
parent_item, parent_item,
parent_mcomp: parent_mcomp, parent_mcomp: arg.parent_mcomp,
indexed_scope: {}, indexed_scope: {},
is_layout: arg.is_layout, is_layout: arg.is_layout,
}; };
if (item.name.startsWith("⬅")) { if (item.name.startsWith("⬅")) {
arg.portal.in[item.name] = meta; arg.portal.in[item.name] = meta;
} }
@ -232,7 +239,7 @@ export const syncWalkMap = (
tree_root_id: arg.tree_root_id, tree_root_id: arg.tree_root_id,
mitem: mcontent, mitem: mcontent,
jsx_prop_name: k, jsx_prop_name: k,
parent_mcomp: arg.parent_mcomp, parent_mcomp: { minstance, meta, mcomp },
parent_item: { id: item.id, mitem: mitem as MItem }, parent_item: { id: item.id, mitem: mitem as MItem },
portal: arg.portal, portal: arg.portal,
skip_add_tree: skip_tree_child, skip_add_tree: skip_tree_child,
@ -254,7 +261,7 @@ export const syncWalkMap = (
tree_root_id: arg.tree_root_id, tree_root_id: arg.tree_root_id,
mitem: e, mitem: e,
parent_item: { id: item.id, mitem: mitem as MItem }, parent_item: { id: item.id, mitem: mitem as MItem },
parent_mcomp: { mitem: mitem as MItem, mcomp }, parent_mcomp: { minstance, meta, mcomp },
skip_add_tree: true, skip_add_tree: true,
portal: arg.portal, portal: arg.portal,
each: arg.each, each: arg.each,
@ -274,7 +281,7 @@ export const syncWalkMap = (
jsx_prop_name: arg.jsx_prop_name, jsx_prop_name: arg.jsx_prop_name,
mitem: mitem as MItem, mitem: mitem as MItem,
parent_item, parent_item,
parent_mcomp: parent_mcomp, parent_mcomp: arg.parent_mcomp,
indexed_scope: {}, indexed_scope: {},
}; };

View File

@ -1,11 +1,11 @@
import { useGlobal, useLocal } from "web-utils"; import { useEffect } from "react";
import { useGlobal } from "web-utils";
import { Loading } from "../../../../utils/ui/loading"; import { Loading } from "../../../../utils/ui/loading";
import { View } from "../../../view/view"; import { View } from "../../../view/view";
import { EDGlobal, active } from "../../logic/ed-global"; import { EDGlobal, EdMeta, active } from "../../logic/ed-global";
import { getMetaById } from "../../logic/tree/build"; import { getMetaById } from "../../logic/tree/build";
import { loadComponent } from "../../logic/tree/sync-walk"; import { loadComponent } from "../../logic/tree/sync-walk";
import { code } from "../popup/code/code"; import { code } from "../popup/code/code";
import { useEffect } from "react";
export const EdMain = () => { export const EdMain = () => {
const p = useGlobal(EDGlobal, "EDITOR"); const p = useGlobal(EDGlobal, "EDITOR");
@ -49,60 +49,12 @@ export const EdMain = () => {
}} }}
hover={{ hover={{
get(meta) { get(meta) {
const item = meta.item; return active.hover_id === meta.item.id;
if (active.comp_id) {
const p = meta.parent_mcomp;
if (p) {
if (
p.mitem.get("id") !== active.instance.item_id ||
p.mcomp.get("component")?.get("id") !== active.comp_id
)
return false;
}
}
if (
item.originalId === active.hover_id ||
item.id === active.hover_id
)
return true;
return false;
}, },
set(meta) { set(meta) {
if (meta.parent_mcomp) { const outer = getOuterItem(meta);
const id = meta.parent_mcomp.mitem.get("id"); if (outer) {
if (active.instance.item_id !== id) { active.hover_id = outer.id;
const original_id =
meta.parent_mcomp.mitem.get("originalId");
if (active.comp_id && original_id) {
active.hover_id = original_id;
} else if (id) {
active.hover_id = id;
}
p.render();
p.page.render();
focus();
return;
}
}
if (active.comp_id) {
const parent = meta.parent_mcomp;
if (parent) {
const mcomp = parent.mcomp;
if (mcomp.get("component")?.get("id") === active.comp_id) {
active.hover_id = meta.item.originalId || meta.item.id;
}
} else {
active.hover_id = meta.item.id;
}
} else {
active.hover_id = meta.item.id;
} }
p.render(); p.render();
@ -111,86 +63,12 @@ export const EdMain = () => {
}} }}
active={{ active={{
get(meta) { get(meta) {
const item = meta.item; return active.item_id === meta.item.id;
if (active.comp_id) {
const p = meta.parent_mcomp;
if (p) {
if (
p.mitem.get("id") !== active.instance.item_id ||
p.mcomp.get("component")?.get("id") !== active.comp_id
)
return false;
}
}
if (
item.originalId === active.item_id ||
item.id === active.item_id
)
return true;
return false;
}, },
set(meta) { set(meta) {
if (meta.parent_mcomp) { const outer = getOuterItem(meta);
const id = meta.parent_mcomp.mitem.get("id"); if (outer) {
if (active.instance.item_id !== id) { active.item_id = outer.id;
const original_id =
meta.parent_mcomp.mitem.get("originalId");
let active_id = "";
if (active.comp_id && original_id) {
active_id = original_id;
} else if (id) {
active_id = id;
}
if (active_id) {
if (active.item_id !== active_id) {
active.item_id = active_id;
} else {
const comp_id = meta.parent_mcomp.mcomp
.get("component")
?.get("id");
if (comp_id) {
active.instance.item_id = active_id;
active.instance.comp_id = active.comp_id;
active.comp_id = comp_id || "";
const root = p.comp.list[comp_id].tree.find(
(e) => e.parent === "root"
);
if (root && typeof root.id === "string") {
active.item_id = root.id || "";
}
}
}
}
p.render();
p.page.render();
focus();
return;
}
}
if (active.comp_id) {
const parent = meta.parent_mcomp;
if (parent) {
const mcomp = parent.mcomp;
if (mcomp.get("component")?.get("id") === active.comp_id) {
active.item_id = meta.item.originalId || meta.item.id;
}
} else {
active.comp_id = "";
active.item_id = meta.item.id;
active.instance.item_id = "";
active.instance.comp_id = "";
}
} else {
active.item_id = meta.item.id;
} }
p.render(); p.render();
@ -274,6 +152,15 @@ export const EdMain = () => {
); );
}; };
const getOuterItem = (meta: EdMeta) => {
let cur: undefined | EdMeta = meta;
while (cur.parent_mcomp) {
cur = cur.parent_mcomp.meta;
}
return cur.item;
};
function setEndOfContenteditable(div: any) { function setEndOfContenteditable(div: any) {
let range: any, sel: any; let range: any, sel: any;
if (document.createRange) { if (document.createRange) {

View File

@ -23,6 +23,8 @@ export const ScriptMonaco = () => {
editor: null as null | MonacoEditor, editor: null as null | MonacoEditor,
monaco: null as null | Monaco, monaco: null as null | Monaco,
changeTimeout: 0 as any, changeTimeout: 0 as any,
init: false,
value: "",
historyOpen: false, historyOpen: false,
idbstore: createStore(`prasi-page-${p.page.cur.id}`, "script-history"), idbstore: createStore(`prasi-page-${p.page.cur.id}`, "script-history"),
}); });
@ -45,33 +47,57 @@ export const ScriptMonaco = () => {
}, []); }, []);
useEffect(() => { useEffect(() => {
if (local.monaco && local.editor) { (async () => {
local.monaco.editor.getModels().forEach((model) => { const editor = local.editor;
const uri = model.uri.toString(); const monaco = local.monaco;
if ( if (monaco && editor) {
uri.startsWith("inmemory://model") || if (!local.init) {
uri.startsWith("ts:comp-") || if (p.ui.popup.script.mode === "js") {
uri.startsWith("ts:page-") monaco.editor.getModels().forEach((model) => {
) { model.dispose();
model.dispose(); });
} monaco.editor.getModels().forEach((model) => {
}); if (model.uri.toString().startsWith("inmemory://model")) {
model.dispose();
}
});
let model = local.monaco.editor.createModel( let model = monaco.editor.createModel(
val, val,
"typescript", "typescript",
local.monaco.Uri.parse( monaco.Uri.parse(
`ts:${ `ts:${
active.comp_id ? `comp-${active.comp_id}` : `page-${p.page.cur.id}` active.comp_id
}-${active.item_id}.tsx` ? `comp-${active.comp_id}`
) : `page-${p.page.cur.id}`
); }-${active.item_id}.tsx`
local.editor.setModel(model); )
declareScope(p, local.editor, local.monaco).then(() => { );
local.render(); editor.setModel(model);
}); await jsMount(editor, monaco, p);
} await monacoTypings(
}, [active.item_id, val]); {
site_dts: p.site_dts,
script: {
siteTypes: {},
},
site: p.site.config,
},
monaco,
{ types: {}, values: {} }
);
declareScope(p, editor, monaco).then(() => {
local.render();
});
}
local.init = true;
local.value = val;
local.render();
}
}
})();
}, [active.item_id, local.monaco, local.editor]);
if (!meta) return null; if (!meta) return null;
@ -121,9 +147,9 @@ export const ScriptMonaco = () => {
} else if ( } else if (
item.type === "item" && item.type === "item" &&
item.component?.id && item.component?.id &&
meta.parent_mcomp?.mitem meta.parent_mcomp?.meta.mitem
) { ) {
mitem = meta.parent_mcomp?.mitem; mitem = meta.parent_mcomp?.meta.mitem;
if (!mitem) { if (!mitem) {
active.item_id = ""; active.item_id = "";
@ -170,11 +196,8 @@ async () => {
} }
} }
if (!meta) return null;
return ( return (
<Editor <Editor
value={val}
options={{ options={{
minimap: { enabled: false }, minimap: { enabled: false },
wordWrap: "wordWrapColumn", wordWrap: "wordWrapColumn",
@ -188,7 +211,10 @@ async () => {
language={ language={
{ css: "scss", js: "typescript", html: "html" }[p.ui.popup.script.mode] { css: "scss", js: "typescript", html: "html" }[p.ui.popup.script.mode]
} }
value={local.value}
onChange={(val) => { onChange={(val) => {
local.value = val || "";
local.render();
clearTimeout(scriptEdit.timeout); clearTimeout(scriptEdit.timeout);
scriptEdit.timeout = setTimeout(() => { scriptEdit.timeout = setTimeout(() => {
const meta = getMetaById(p, active.item_id); const meta = getMetaById(p, active.item_id);
@ -222,46 +248,13 @@ async () => {
}, 1000); }, 1000);
}} }}
onMount={async (editor, monaco) => { onMount={async (editor, monaco) => {
local.monaco = monaco;
local.editor = editor; local.editor = editor;
local.render();
editor.focus(); editor.focus();
setTimeout(() => { setTimeout(() => {
editor.focus(); editor.focus();
}, 300); }, 300);
const value = editor.getValue();
if (p.ui.popup.script.mode === "js") {
monaco.editor.getModels().forEach((model) => {
if (model.uri.toString().startsWith("inmemory://model")) {
model.dispose();
}
});
let model = monaco.editor.createModel(
value,
"typescript",
monaco.Uri.parse(
`ts:${
active.comp_id
? `comp-${active.comp_id}`
: `page-${p.page.cur.id}`
}-${active.item_id}.tsx`
)
);
editor.setModel(model);
await jsMount(editor, monaco, p);
await monacoTypings(
{
site_dts: p.site_dts,
script: {
siteTypes: {},
},
site: p.site.config,
},
monaco,
{ types: {}, values: {} }
);
await declareScope(p, editor, monaco);
}
}} }}
/> />
); );

View File

@ -20,11 +20,6 @@ export const declareScope = async (
if (!s) return; if (!s) return;
s.p.push(active_id); s.p.push(active_id);
monaco.editor.getModels().forEach((model) => {
if (model.uri.toString().startsWith("ts:scope~")) {
model.dispose();
}
});
const existing: Record<string, IEachArgScope> = {}; const existing: Record<string, IEachArgScope> = {};
@ -143,7 +138,8 @@ const spreadScope = (
if (!item) { if (!item) {
if (meta) { if (meta) {
if (meta.parent_mcomp) { if (meta.parent_mcomp) {
comp_id = meta.parent_mcomp.mitem.get("component")?.get("id") || ""; comp_id =
meta.parent_mcomp.meta.mitem?.get("component")?.get("id") || "";
if (comp_id) { if (comp_id) {
const scope = p.comp.list[comp_id].scope; const scope = p.comp.list[comp_id].scope;
item = scope[meta.item.originalId || meta.item.id]; item = scope[meta.item.originalId || meta.item.id];

View File

@ -95,7 +95,7 @@ export const EdSidePropInstance: FC<{ meta: EdMeta }> = ({ meta }) => {
</div> </div>
</div> </div>
<div className="flex flex-1 relative overflow-auto"> <div className="flex flex-1 relative overflow-y-auto overflow-x-hidden">
<div className={cx("absolute inset-0")}> <div className={cx("absolute inset-0")}>
{local.rightClickEvent && ( {local.rightClickEvent && (
<Menu <Menu

View File

@ -17,25 +17,11 @@ export const EdPropInstanceText: FC<{
const p = useGlobal(EDGlobal, "EDITOR"); const p = useGlobal(EDGlobal, "EDITOR");
const local = useLocal({ const local = useLocal({
value: "", value: mprop.get("value"),
codeEditing: false, codeEditing: false,
timeout: null as any, timeout: null as any,
}); });
const val = mprop.get("value");
const valBuilt = mprop.get("valueBuilt");
useEffect(() => {
if (val) {
try {
eval(`local.value = ${valBuilt}`);
} catch (e) {}
} else {
local.value = "";
}
local.render();
}, [val, valBuilt]);
return ( return (
<div className="flex items-center min-h-[28px]"> <div className="flex items-center min-h-[28px]">
<EdPropLabel name={name} /> <EdPropLabel name={name} />

View File

@ -92,7 +92,7 @@ export const EdSidePropComp: FC<{ meta: EdMeta }> = ({ meta }) => {
Back to Instance Back to Instance
</div> </div>
</div> </div>
<div className="flex flex-1 relative overflow-auto"> <div className="flex flex-1 relative overflow-y-auto overflow-x-hidden">
<div <div
className={cx("absolute inset-0")} className={cx("absolute inset-0")}
ref={(ref) => (propRef.el = ref)} ref={(ref) => (propRef.el = ref)}

View File

@ -33,11 +33,11 @@ export const nodeRender: NodeRender<EdMeta> = (node, prm) => {
const meta = getMetaById(p, node.data?.parent_item.id); const meta = getMetaById(p, node.data?.parent_item.id);
if (meta) { if (meta) {
if (meta.propvis) { if (meta.propvis) {
jsxPropVisCache[node.data.item.id] = meta.propvis; jsxPropVisCache[meta.item.id] = meta.propvis;
if (meta.propvis[node.data.jsx_prop_name] === false) return <></>; if (meta.propvis[node.data.jsx_prop_name] === false) return <></>;
} else { } else {
if (jsxPropVisCache[node.data.item.id]) { if (jsxPropVisCache[meta.item.id]) {
meta.propvis = jsxPropVisCache[node.data.item.id]; meta.propvis = jsxPropVisCache[meta.item.id];
if (meta.propvis) { if (meta.propvis) {
if (meta.propvis[node.data.jsx_prop_name] === false) return <></>; if (meta.propvis[node.data.jsx_prop_name] === false) return <></>;
} }

View File

@ -1,6 +1,6 @@
import importModule from "../../../render/editor/tools/dynamic-import"; import importModule from "../../../render/editor/tools/dynamic-import";
import { devLoader } from "../../../render/live/dev-loader"; import { devLoader } from "../../../render/live/dev-loader";
import { createAPI, createDB } from "../../../utils/script/init-api"; import { createAPI, createDB, initApi } from "../../../utils/script/init-api";
import { VG } from "./global"; import { VG } from "./global";
export const oldLoadCode = async (v: VG) => { export const oldLoadCode = async (v: VG) => {
@ -21,11 +21,12 @@ export const oldLoadCode = async (v: VG) => {
} }
} }
await initApi(site.config);
await importModule(loader.npm(p, "site", site.id)); await importModule(loader.npm(p, "site", site.id));
if (site.js_compiled) { if (site.js_compiled) {
const config = site.config as any; const config = site.config as any;
const exec = (fn: string, scopes: any) => { const exec = (fn: string, scopes: any) => {
if (config.api_url) { if (config.api_url && !scopes["api"]) {
scopes["api"] = createAPI(config.api_url); scopes["api"] = createAPI(config.api_url);
scopes["db"] = createDB(config.api_url); scopes["db"] = createDB(config.api_url);
} }

View File

@ -39,6 +39,7 @@ export const jsMount = async (editor: MonacoEditor, monaco: Monaco, p?: PG) => {
if (p) { if (p) {
p.ui.popup.script.mode === "js"; p.ui.popup.script.mode === "js";
const cpath = r.path.substring(`scope~`.length).split("__"); const cpath = r.path.substring(`scope~`.length).split("__");
const [comp_id, prev_comp_id, prev_item_id] = cpath[0].split("~"); const [comp_id, prev_comp_id, prev_item_id] = cpath[0].split("~");
if (cpath[1]) { if (cpath[1]) {
const path = cpath[1].split("~"); const path = cpath[1].split("~");