wip fix tree-rebuild
This commit is contained in:
parent
8188589065
commit
3c25a62192
|
|
@ -12,7 +12,6 @@ export const comp_load: SAction["comp"]["load"] = async function (
|
|||
) {
|
||||
const result: Record<string, IScopeComp> = {};
|
||||
for (const id of ids) {
|
||||
const root = await loadComponent(id, this);
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import { GenMetaP } from "../../../../web/src/nova/vi/utils/types";
|
|||
import { IItem } from "../../../../web/src/utils/types/item";
|
||||
import { DPage } from "../../../../web/src/utils/types/root";
|
||||
import { SAction } from "../actions";
|
||||
import { loadComponent } from "../editor/load-component";
|
||||
import { loadComponent, userSyncComponent } from "../editor/load-component";
|
||||
import { parseJs } from "../editor/parser/parse-js";
|
||||
import { activity } from "../entity/activity";
|
||||
import { conns } from "../entity/conn";
|
||||
|
|
@ -201,6 +201,8 @@ const scanMeta = async (doc: DPage, sync: SyncConnection) => {
|
|||
});
|
||||
}
|
||||
await loading[id];
|
||||
} else {
|
||||
userSyncComponent(sync, id);
|
||||
}
|
||||
|
||||
if (docs.comp[id]) {
|
||||
|
|
@ -239,6 +241,6 @@ const scanMeta = async (doc: DPage, sync: SyncConnection) => {
|
|||
comps[id] = { id, snapshot: await gzipAsync(snap.bin) };
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return { meta: simplifyMeta(meta), comps, entry };
|
||||
};
|
||||
|
|
|
|||
|
|
@ -6,10 +6,11 @@ import { gzipAsync } from "../entity/zlib";
|
|||
import { sendWS } from "../sync-handler";
|
||||
import { SyncConnection, SyncType } from "../type";
|
||||
|
||||
export const loadComponent = async (id: string, sync: SyncConnection) => {
|
||||
let snap = snapshot.get("comp", id);
|
||||
let ydoc = docs.comp[id];
|
||||
export const loadComponent = async (comp_id: string, sync: SyncConnection) => {
|
||||
let snap = snapshot.get("comp", comp_id);
|
||||
let ydoc = docs.comp[comp_id];
|
||||
const conf = sync.conf;
|
||||
|
||||
if (!conf) return undefined;
|
||||
|
||||
const createUndoManager = async (root: Y.Map<any>) => {
|
||||
|
|
@ -21,25 +22,28 @@ export const loadComponent = async (id: string, sync: SyncConnection) => {
|
|||
};
|
||||
|
||||
const attachOnUpdate = async (doc: Y.Doc, um: Y.UndoManager) => {
|
||||
snapshot.set("comp", id, "id_doc", um.doc.clientID);
|
||||
snapshot.set("comp", comp_id, "id_doc", um.doc.clientID);
|
||||
|
||||
doc.on("update", async (update: Uint8Array, origin: any) => {
|
||||
const bin = Y.encodeStateAsUpdate(doc);
|
||||
snapshot.set("comp", id, "bin", bin);
|
||||
snapshot.set("comp", comp_id, "bin", bin);
|
||||
|
||||
const sv_local = await gzipAsync(update);
|
||||
|
||||
const all = user.active.findAll({ comp_id: id });
|
||||
const all = user.active.findAll({ comp_id: comp_id });
|
||||
|
||||
all.map((e) => {
|
||||
if (origin !== um) {
|
||||
if (e.client_id === origin) return;
|
||||
}
|
||||
|
||||
const ws = conns.get(e.client_id)?.ws;
|
||||
|
||||
if (ws) {
|
||||
sendWS(ws, {
|
||||
type: SyncType.Event,
|
||||
event: "remote_svlocal",
|
||||
data: { type: "comp", sv_local, id },
|
||||
data: { type: "comp", sv_local, id: comp_id },
|
||||
});
|
||||
}
|
||||
});
|
||||
|
|
@ -51,16 +55,16 @@ export const loadComponent = async (id: string, sync: SyncConnection) => {
|
|||
};
|
||||
|
||||
if (!snap && !ydoc) {
|
||||
const comp = await db.component.findFirst({ where: { id } });
|
||||
const comp = await db.component.findFirst({ where: { id: comp_id } });
|
||||
if (comp) {
|
||||
const doc = new Y.Doc();
|
||||
let root = doc.getMap("map");
|
||||
syncronize(root, { id, root: comp.content_tree });
|
||||
syncronize(root, { id: comp_id, root: comp.content_tree });
|
||||
|
||||
const um = await createUndoManager(root);
|
||||
docs.comp[id] = {
|
||||
docs.comp[comp_id] = {
|
||||
doc: doc as any,
|
||||
id,
|
||||
id: comp_id,
|
||||
um,
|
||||
};
|
||||
|
||||
|
|
@ -69,7 +73,7 @@ export const loadComponent = async (id: string, sync: SyncConnection) => {
|
|||
|
||||
snapshot.update({
|
||||
bin,
|
||||
id,
|
||||
id: comp_id,
|
||||
type: "comp",
|
||||
name: comp.name,
|
||||
ts: Date.now(),
|
||||
|
|
@ -86,23 +90,23 @@ export const loadComponent = async (id: string, sync: SyncConnection) => {
|
|||
});
|
||||
|
||||
return {
|
||||
id: id,
|
||||
id: comp_id,
|
||||
name: comp.name,
|
||||
snapshot: await gzipAsync(bin),
|
||||
};
|
||||
}
|
||||
} else if (snap && !ydoc) {
|
||||
const doc = new Y.Doc();
|
||||
snapshot.set("comp", id, "id_doc", doc.clientID);
|
||||
snapshot.set("comp", comp_id, "id_doc", doc.clientID);
|
||||
Y.applyUpdate(doc, snap.bin);
|
||||
let root = doc.getMap("map");
|
||||
|
||||
const um = await createUndoManager(root);
|
||||
await attachOnUpdate(doc, um);
|
||||
|
||||
docs.comp[id] = {
|
||||
docs.comp[comp_id] = {
|
||||
doc: doc as any,
|
||||
id,
|
||||
id: comp_id,
|
||||
um,
|
||||
};
|
||||
|
||||
|
|
@ -112,11 +116,11 @@ export const loadComponent = async (id: string, sync: SyncConnection) => {
|
|||
user_id: sync.user_id,
|
||||
site_id: conf.site_id,
|
||||
page_id: conf.page_id,
|
||||
comp_id: id,
|
||||
comp_id: comp_id,
|
||||
});
|
||||
|
||||
return {
|
||||
id: id,
|
||||
id: comp_id,
|
||||
name: snap.name,
|
||||
snapshot: await gzipAsync(snap.bin),
|
||||
};
|
||||
|
|
@ -127,7 +131,7 @@ export const loadComponent = async (id: string, sync: SyncConnection) => {
|
|||
user_id: sync.user_id,
|
||||
site_id: conf.site_id,
|
||||
page_id: conf.page_id,
|
||||
comp_id: id,
|
||||
comp_id: comp_id,
|
||||
});
|
||||
|
||||
return {
|
||||
|
|
@ -137,3 +141,15 @@ export const loadComponent = async (id: string, sync: SyncConnection) => {
|
|||
};
|
||||
}
|
||||
};
|
||||
|
||||
export const userSyncComponent = (sync: SyncConnection, comp_id: string) => {
|
||||
const conf = sync.conf;
|
||||
|
||||
user.active.add({
|
||||
client_id: sync.client_id,
|
||||
user_id: sync.user_id,
|
||||
site_id: conf?.site_id || "",
|
||||
page_id: conf?.page_id || "",
|
||||
comp_id: comp_id,
|
||||
});
|
||||
};
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@ export const user = {
|
|||
page_id: string;
|
||||
comp_id?: string;
|
||||
client_id: string;
|
||||
select: "" | "comp" | "item" | "section" | "text";
|
||||
},
|
||||
"client_id"
|
||||
>("client_id"),
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ export const syncHandler: WebSocketHandler<WSData> = {
|
|||
close(ws) {
|
||||
const client_id = wconns.get(ws);
|
||||
if (client_id) {
|
||||
user.active.delAll({ client_id });
|
||||
activity.site.disconnect(ws);
|
||||
conns.delete(client_id);
|
||||
wconns.delete(ws);
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
import { NodeModel } from "@minoru/react-dnd-treeview";
|
||||
import { compress, decompress } from "wasm-gzip";
|
||||
import { IItem } from "../../../../utils/types/item";
|
||||
import { DComp } from "../../../../utils/types/root";
|
||||
import { genMeta } from "../../../vi/meta/meta";
|
||||
import { IMeta, PG } from "../ed-global";
|
||||
import { NodeModel } from "@minoru/react-dnd-treeview";
|
||||
import { pushTreeNode } from "../tree/build/push-tree";
|
||||
|
||||
export const loadcomp = {
|
||||
|
|
@ -39,87 +39,108 @@ export const loadComponent = async (p: PG, id_comp: string) => {
|
|||
|
||||
export const loadCompSnapshot = async (
|
||||
p: PG,
|
||||
id_comp: string,
|
||||
comp_id: string,
|
||||
snapshot: Uint8Array
|
||||
) => {
|
||||
const doc = new Y.Doc() as DComp;
|
||||
Y.applyUpdate(doc as any, decompress(snapshot));
|
||||
const mitem = doc.getMap("map").get("root");
|
||||
if (mitem) {
|
||||
if (typeof p.comp.list[id_comp]?.on_update === "function") {
|
||||
doc.off("update", p.comp.list[id_comp].on_update);
|
||||
if (typeof p.comp.list[comp_id]?.on_update === "function") {
|
||||
doc.off("update", p.comp.list[comp_id].on_update);
|
||||
}
|
||||
|
||||
const meta: Record<string, IMeta> = {};
|
||||
const tree: NodeModel<IMeta>[] = [];
|
||||
const item = mitem.toJSON() as IItem;
|
||||
p.comp.loaded[id_comp] = {
|
||||
comp: item,
|
||||
};
|
||||
genMeta(
|
||||
{
|
||||
comps: p.comp.loaded,
|
||||
meta,
|
||||
on: {
|
||||
visit(m) {
|
||||
pushTreeNode(p, m, meta, tree);
|
||||
const updated = updateComponentMeta(p, doc, comp_id);
|
||||
if (updated) {
|
||||
const { meta, tree } = updated;
|
||||
if (p.comp.list[comp_id]) {
|
||||
p.comp.list[comp_id].meta = meta;
|
||||
p.comp.list[comp_id].tree = tree;
|
||||
} else {
|
||||
p.comp.list[comp_id] = {
|
||||
comp: { id: comp_id, snapshot },
|
||||
doc,
|
||||
meta,
|
||||
tree,
|
||||
async on_update(bin, origin) {
|
||||
if (origin === "sv_remote" || origin === "local") {
|
||||
return;
|
||||
}
|
||||
|
||||
if (m.parent) {
|
||||
if (m.parent.id === "root") {
|
||||
if (m.item.id === item.id) {
|
||||
m.mitem = mitem;
|
||||
}
|
||||
} else {
|
||||
const parent = meta[m.parent.id];
|
||||
const res = await p.sync.yjs.sv_local(
|
||||
"comp",
|
||||
comp_id,
|
||||
Buffer.from(compress(bin))
|
||||
);
|
||||
|
||||
if (parent.mitem) {
|
||||
parent.mitem.get("childs")?.forEach((child) => {
|
||||
if (child.get("id") === m.item.id) {
|
||||
m.mitem = child;
|
||||
}
|
||||
});
|
||||
}
|
||||
if (res) {
|
||||
const diff_local = Y.encodeStateAsUpdate(
|
||||
doc as any,
|
||||
decompress(res.sv)
|
||||
);
|
||||
Y.applyUpdate(doc as any, decompress(res.diff), "local");
|
||||
await p.sync.yjs.diff_local(
|
||||
"comp",
|
||||
comp_id,
|
||||
Buffer.from(compress(diff_local))
|
||||
);
|
||||
const updated = updateComponentMeta(p, doc, comp_id);
|
||||
|
||||
if (updated) {
|
||||
p.comp.list[comp_id].meta = updated.meta;
|
||||
p.comp.list[comp_id].tree = updated.tree;
|
||||
}
|
||||
p.render();
|
||||
}
|
||||
},
|
||||
},
|
||||
note: "load-comp",
|
||||
},
|
||||
{ item, ignore_first_component: true }
|
||||
);
|
||||
};
|
||||
|
||||
p.comp.list[id_comp] = {
|
||||
comp: { id: id_comp, snapshot },
|
||||
doc,
|
||||
meta,
|
||||
tree,
|
||||
async on_update(bin, origin) {
|
||||
if (origin === "sv_remote" || origin === "local") {
|
||||
return;
|
||||
}
|
||||
|
||||
const res = await p.sync.yjs.sv_local(
|
||||
"comp",
|
||||
id_comp,
|
||||
Buffer.from(compress(bin))
|
||||
);
|
||||
|
||||
if (res) {
|
||||
const diff_local = Y.encodeStateAsUpdate(
|
||||
doc as any,
|
||||
decompress(res.sv)
|
||||
);
|
||||
Y.applyUpdate(doc as any, decompress(res.diff), "local");
|
||||
await p.sync.yjs.diff_local(
|
||||
"comp",
|
||||
id_comp,
|
||||
Buffer.from(compress(diff_local))
|
||||
);
|
||||
p.render();
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
doc.on("update", p.comp.list[id_comp].on_update);
|
||||
doc.on("update", p.comp.list[comp_id].on_update);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export const updateComponentMeta = (p: PG, doc: DComp, comp_id: string) => {
|
||||
const mitem = doc.getMap("map").get("root");
|
||||
if (!mitem) return;
|
||||
|
||||
const meta: Record<string, IMeta> = {};
|
||||
const tree: NodeModel<IMeta>[] = [];
|
||||
const item = mitem.toJSON() as IItem;
|
||||
p.comp.loaded[comp_id] = {
|
||||
comp: item,
|
||||
};
|
||||
genMeta(
|
||||
{
|
||||
comps: p.comp.loaded,
|
||||
meta,
|
||||
on: {
|
||||
visit(m) {
|
||||
pushTreeNode(p, m, meta, tree);
|
||||
|
||||
if (m.parent) {
|
||||
if (m.parent.id === "root") {
|
||||
if (m.item.id === item.id) {
|
||||
m.mitem = mitem;
|
||||
}
|
||||
} else {
|
||||
const parent = meta[m.parent.id];
|
||||
|
||||
if (parent.mitem) {
|
||||
parent.mitem.get("childs")?.forEach((child) => {
|
||||
if (child.get("id") === m.item.id) {
|
||||
m.mitem = child;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
note: "load-comp",
|
||||
},
|
||||
{ item, ignore_first_component: true }
|
||||
);
|
||||
return { meta, tree };
|
||||
};
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import { EmptySite, PG } from "./ed-global";
|
|||
import { treeRebuild } from "./tree/build";
|
||||
import { reloadPage } from "./ed-route";
|
||||
import { loadSite } from "./ed-site";
|
||||
import { updateComponentMeta } from "./comp/load";
|
||||
|
||||
const decoder = new TextDecoder();
|
||||
|
||||
|
|
@ -172,9 +173,20 @@ export const edInitSync = (p: PG) => {
|
|||
sv,
|
||||
diff
|
||||
);
|
||||
|
||||
if (res) {
|
||||
Y.applyUpdate(doc, decompress(res.diff), "sv_remote");
|
||||
await treeRebuild(p, { note: "sv_remote" });
|
||||
if (data.type === "page") {
|
||||
await treeRebuild(p, { note: "sv_remote" });
|
||||
} else {
|
||||
const updated = updateComponentMeta(p, doc, data.id);
|
||||
if (updated) {
|
||||
p.comp.list[data.id].meta = updated.meta;
|
||||
p.comp.list[data.id].tree = updated.tree;
|
||||
}
|
||||
await treeRebuild(p, { note: "sv_remote" });
|
||||
}
|
||||
p.render();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -0,0 +1,66 @@
|
|||
import { MItem } from "../../../../../utils/types/item";
|
||||
import { FNAdv } from "../../../../../utils/types/meta-fn";
|
||||
import { PG } from "../../../logic/ed-global";
|
||||
|
||||
export const edMonacoDefaultVal = (p: PG, adv: FNAdv, mitem: MItem) => {
|
||||
let val = "";
|
||||
|
||||
if (p.ui.popup.script.type === "item") {
|
||||
const mode = p.ui.popup.script.mode;
|
||||
val = (typeof adv[mode] === "string" ? adv[mode] : "") as any;
|
||||
|
||||
if (val === "") {
|
||||
if (mode === "js") {
|
||||
val = `<div {...props}>{children}</div>`;
|
||||
} else if (mode === "css") {
|
||||
val = `\
|
||||
& {
|
||||
display: flex;
|
||||
|
||||
// &.mobile {}
|
||||
// &.desktop {}
|
||||
// &:hover {}
|
||||
}`;
|
||||
}
|
||||
}
|
||||
} else if (
|
||||
p.ui.popup.script.type === "prop-master" ||
|
||||
p.ui.popup.script.type === "prop-instance"
|
||||
) {
|
||||
const mprops = mitem?.get("component")?.get("props");
|
||||
if (mprops) {
|
||||
const mprop = mprops.get(p.ui.popup.script.prop_name);
|
||||
if (mprop) {
|
||||
const kind = p.ui.popup.script.prop_kind;
|
||||
if (kind === "value") {
|
||||
val = mprop.get("value");
|
||||
} else if (kind === "gen") {
|
||||
val =
|
||||
mprop.get("gen") ||
|
||||
`\
|
||||
async () => {
|
||||
return \`""\`;
|
||||
}`;
|
||||
} else if (kind === "visible") {
|
||||
val = mprop.get("visible") || "true";
|
||||
} else if (kind === "option") {
|
||||
val =
|
||||
mprop.get("meta")?.get("options") ||
|
||||
`\
|
||||
[
|
||||
{
|
||||
label: "yes",
|
||||
value: "y"
|
||||
},
|
||||
{
|
||||
label: "no",
|
||||
value: "n"
|
||||
},
|
||||
]`;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return val;
|
||||
};
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
import type { Monaco, OnMount } from "@monaco-editor/react";
|
||||
import { createStore } from "idb-keyval";
|
||||
import trim from "lodash.trim";
|
||||
import { useEffect } from "react";
|
||||
import { FC, useEffect } from "react";
|
||||
import { compress } from "wasm-gzip";
|
||||
import { useGlobal, useLocal } from "web-utils";
|
||||
import { jscript } from "../../../../../utils/script/jscript";
|
||||
|
|
@ -10,6 +10,7 @@ import { monacoTypings } from "../../../../../utils/script/typings";
|
|||
import { EDGlobal, IMeta, active } from "../../../logic/ed-global";
|
||||
import { getMetaById } from "../../../logic/tree/build";
|
||||
import { declareScope } from "./scope";
|
||||
import { edMonacoDefaultVal } from "./default-val";
|
||||
|
||||
const scriptEdit = {
|
||||
timeout: null as any,
|
||||
|
|
@ -17,7 +18,7 @@ const scriptEdit = {
|
|||
|
||||
const encode = new TextEncoder();
|
||||
export type MonacoEditor = Parameters<OnMount>[0];
|
||||
export const ScriptMonaco = () => {
|
||||
export const EdScriptMonaco: FC<{}> = () => {
|
||||
const p = useGlobal(EDGlobal, "EDITOR");
|
||||
const local = useLocal({
|
||||
editor: null as null | MonacoEditor,
|
||||
|
|
@ -26,6 +27,7 @@ export const ScriptMonaco = () => {
|
|||
init: false,
|
||||
value: "",
|
||||
historyOpen: false,
|
||||
mode: "",
|
||||
idbstore: createStore(`prasi-page-${p.page.cur.id}`, "script-history"),
|
||||
});
|
||||
|
||||
|
|
@ -53,6 +55,11 @@ export const ScriptMonaco = () => {
|
|||
const monaco = local.monaco;
|
||||
|
||||
if (monaco && editor) {
|
||||
if (local.mode !== p.ui.popup.script.mode) {
|
||||
local.init = false;
|
||||
local.mode = p.ui.popup.script.mode;
|
||||
}
|
||||
|
||||
if (!local.init) {
|
||||
if (p.ui.popup.script.mode === "js") {
|
||||
monaco.editor.getModels().forEach((model) => {
|
||||
|
|
@ -101,7 +108,7 @@ export const ScriptMonaco = () => {
|
|||
}
|
||||
}
|
||||
})();
|
||||
}, [active.item_id, local.monaco, local.editor]);
|
||||
}, [active.item_id, local.monaco, local.editor, p.ui.popup.script.mode]);
|
||||
|
||||
if (!meta) return null;
|
||||
|
||||
|
|
@ -110,41 +117,45 @@ export const ScriptMonaco = () => {
|
|||
item.adv = adv;
|
||||
|
||||
const doEdit = async (newval: string, all?: boolean) => {
|
||||
if (local.editor && jscript.prettier.standalone) {
|
||||
const text = trim(
|
||||
await jscript.prettier.standalone.format(
|
||||
all
|
||||
? newval
|
||||
: local.editor?.getValue().replace(/\{\s*children\s*\}/gi, newval)
|
||||
),
|
||||
"; \n"
|
||||
);
|
||||
if (local.editor) {
|
||||
const prettier = jscript.prettier.standalone;
|
||||
const prettier_ts = jscript.prettier.ts;
|
||||
const prettier_estree = jscript.prettier.estree;
|
||||
|
||||
local.editor.executeEdits(null, [
|
||||
{
|
||||
range: {
|
||||
startLineNumber: 0,
|
||||
startColumn: 0,
|
||||
endColumn: Number.MAX_SAFE_INTEGER,
|
||||
endLineNumber: Number.MAX_SAFE_INTEGER,
|
||||
if (prettier && prettier_estree && prettier_ts) {
|
||||
const text = trim(
|
||||
await prettier.format(
|
||||
all
|
||||
? newval
|
||||
: local.editor
|
||||
?.getValue()
|
||||
.replace(/\{\s*children\s*\}/gi, newval),
|
||||
{
|
||||
parser: "typescript",
|
||||
plugins: [prettier_ts, prettier_estree],
|
||||
}
|
||||
),
|
||||
"; \n"
|
||||
);
|
||||
|
||||
local.editor.executeEdits(null, [
|
||||
{
|
||||
range: {
|
||||
startLineNumber: 0,
|
||||
startColumn: 0,
|
||||
endColumn: Number.MAX_SAFE_INTEGER,
|
||||
endLineNumber: Number.MAX_SAFE_INTEGER,
|
||||
},
|
||||
text,
|
||||
},
|
||||
text,
|
||||
},
|
||||
]);
|
||||
]);
|
||||
}
|
||||
}
|
||||
};
|
||||
p.script.do_edit = doEdit;
|
||||
|
||||
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 <div>no mitem</div>;
|
||||
|
|
@ -155,44 +166,7 @@ export const ScriptMonaco = () => {
|
|||
}
|
||||
}
|
||||
|
||||
if (
|
||||
p.ui.popup.script.type === "prop-master" ||
|
||||
p.ui.popup.script.type === "prop-instance"
|
||||
) {
|
||||
const mprops = mitem?.get("component")?.get("props");
|
||||
if (mprops) {
|
||||
const mprop = mprops.get(p.ui.popup.script.prop_name);
|
||||
if (mprop) {
|
||||
const kind = p.ui.popup.script.prop_kind;
|
||||
if (kind === "value") {
|
||||
val = mprop.get("value");
|
||||
} else if (kind === "gen") {
|
||||
val =
|
||||
mprop.get("gen") ||
|
||||
`\
|
||||
async () => {
|
||||
return \`""\`;
|
||||
}`;
|
||||
} else if (kind === "visible") {
|
||||
val = mprop.get("visible") || "true";
|
||||
} else if (kind === "option") {
|
||||
val =
|
||||
mprop.get("meta")?.get("options") ||
|
||||
`\
|
||||
[
|
||||
{
|
||||
label: "yes",
|
||||
value: "y"
|
||||
},
|
||||
{
|
||||
label: "no",
|
||||
value: "n"
|
||||
},
|
||||
]`;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
val = edMonacoDefaultVal(p, adv, mitem);
|
||||
|
||||
return (
|
||||
<Editor
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import { Loading } from "../../../../../utils/ui/loading";
|
|||
import { Modal } from "../../../../../utils/ui/modal";
|
||||
import { EDGlobal } from "../../../logic/ed-global";
|
||||
import { propPopover } from "../../side/prop-master/prop-form";
|
||||
import { ScriptWorkbench } from "./workbench";
|
||||
import { EdScriptWorkbench } from "./workbench";
|
||||
|
||||
export const EdPopScript = () => {
|
||||
const p = useGlobal(EDGlobal, "EDITOR");
|
||||
|
|
@ -80,7 +80,7 @@ export const EdPopScript = () => {
|
|||
)}
|
||||
>
|
||||
{!jscript.editor && <Loading note={"js-editor"} backdrop={false} />}
|
||||
{jscript.editor && <ScriptWorkbench />}
|
||||
{jscript.editor && <EdScriptWorkbench />}
|
||||
</div>
|
||||
</div>
|
||||
</Modal>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,46 @@
|
|||
import { FC } from "react";
|
||||
import { Button } from "../../../../../utils/ui/form/Button";
|
||||
import { useGlobal } from "web-utils";
|
||||
import { EDGlobal } from "../../../logic/ed-global";
|
||||
|
||||
export const EdScriptSnippet: FC<{}> = ({}) => {
|
||||
const p = useGlobal(EDGlobal, "EDITOR");
|
||||
|
||||
return (
|
||||
<div className="flex items-center space-x-1 pl-2 border-l">
|
||||
<Button
|
||||
className={cx(css`
|
||||
width: auto !important;
|
||||
padding-left: 5px;
|
||||
padding-right: 5px;
|
||||
font-size: 12px;
|
||||
`)}
|
||||
onClick={() => {
|
||||
console.log(p.script.do_edit);
|
||||
p.script.do_edit(
|
||||
`\
|
||||
<div {...props}>
|
||||
<Local
|
||||
name="local"
|
||||
value={
|
||||
{
|
||||
//local object
|
||||
}
|
||||
}
|
||||
effect={async (local) => {
|
||||
//local effect
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</Local>
|
||||
</div>
|
||||
`,
|
||||
true
|
||||
);
|
||||
}}
|
||||
>
|
||||
<Local/>
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
@ -1,53 +1,57 @@
|
|||
import { useGlobal } from "web-utils";
|
||||
import { ScriptMonaco } from "./monaco";
|
||||
import { EdScriptMonaco } from "./monaco";
|
||||
import { EDGlobal, active } from "../../../logic/ed-global";
|
||||
import { IItem } from "../../../../../utils/types/item";
|
||||
import { EdScriptSnippet } from "./snippet";
|
||||
|
||||
export const ScriptWorkbench = () => {
|
||||
export const EdScriptWorkbench = () => {
|
||||
const p = useGlobal(EDGlobal, "EDITOR");
|
||||
return (
|
||||
<div className="flex flex-1 items-stretch">
|
||||
<div className="flex flex-1 flex-col ">
|
||||
<div className="flex p-2 border-b space-x-2">
|
||||
<div className="flex border-b">
|
||||
{p.ui.popup.script.type === "prop-master" ? (
|
||||
<CompTitle />
|
||||
) : (
|
||||
<>
|
||||
{[
|
||||
{ type: "js", color: "#e9522c" },
|
||||
{ type: "css", color: "#188228" },
|
||||
{ type: "html", color: "#2c3e83" },
|
||||
].map((e) => {
|
||||
return (
|
||||
<div
|
||||
key={e.type}
|
||||
className={cx(
|
||||
css`
|
||||
color: ${e.color};
|
||||
border: 1px solid ${e.color};
|
||||
`,
|
||||
"uppercase text-white text-[12px] cursor-pointer transition-all hover:opacity-100 w-[40px] text-center",
|
||||
p.ui.popup.script.mode === e.type
|
||||
? css`
|
||||
background: ${e.color};
|
||||
color: white;
|
||||
`
|
||||
: "opacity-30"
|
||||
)}
|
||||
onClick={() => {
|
||||
p.ui.popup.script.mode = e.type as any;
|
||||
p.render();
|
||||
}}
|
||||
>
|
||||
{e.type}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
<div className="flex p-2 space-x-1">
|
||||
{[
|
||||
{ type: "js", color: "#e9522c" },
|
||||
{ type: "css", color: "#188228" },
|
||||
{ type: "html", color: "#2c3e83" },
|
||||
].map((e) => {
|
||||
return (
|
||||
<div
|
||||
key={e.type}
|
||||
className={cx(
|
||||
css`
|
||||
color: ${e.color};
|
||||
border: 1px solid ${e.color};
|
||||
`,
|
||||
"uppercase text-white text-[12px] cursor-pointer flex items-center justify-center transition-all hover:opacity-100 w-[40px] text-center",
|
||||
p.ui.popup.script.mode === e.type
|
||||
? css`
|
||||
background: ${e.color};
|
||||
color: white;
|
||||
`
|
||||
: "opacity-30"
|
||||
)}
|
||||
onClick={() => {
|
||||
p.ui.popup.script.mode = e.type as any;
|
||||
p.render();
|
||||
}}
|
||||
>
|
||||
{e.type}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
{p.ui.popup.script.mode === "js" && <EdScriptSnippet />}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
<div className="relative flex flex-1">
|
||||
<ScriptMonaco />
|
||||
<EdScriptMonaco />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -26,7 +26,15 @@ export const EdSidePropComp: FC<{ meta: IMeta }> = ({ meta }) => {
|
|||
const TypedTree = DNDTree<PropItem>;
|
||||
|
||||
let filtered = [] as NodeModel<PropItem>[];
|
||||
const mprops = meta.mitem?.get("component")?.get("props");
|
||||
let mprops = meta.mitem?.get("component")?.get("props");
|
||||
if (!mprops) {
|
||||
const mcomp = meta.mitem?.get("component");
|
||||
if (mcomp) {
|
||||
mcomp.set("props", new Y.Map() as any);
|
||||
mprops = mcomp.get("props");
|
||||
}
|
||||
}
|
||||
|
||||
if (mprops && meta.mitem) {
|
||||
mprops.forEach((m, key) => {
|
||||
filtered.push({
|
||||
|
|
@ -139,13 +147,13 @@ export const EdSidePropComp: FC<{ meta: IMeta }> = ({ meta }) => {
|
|||
/>
|
||||
</DndProvider>
|
||||
<div
|
||||
className="m-1 border border-blue-200 px-2 self-start text-[13px] hover:bg-blue-100 cursor-pointer"
|
||||
className="m-1 border border-blue-200 px-2 self-start text-[13px] hover:bg-blue-100 cursor-pointer select-none"
|
||||
onClick={() => {
|
||||
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 name = `prop_${indexes.length === 0 ? 1 : idx + 1}`;
|
||||
const map = new Y.Map() as FMCompDef;
|
||||
syncronize(map, {
|
||||
idx: idx,
|
||||
|
|
|
|||
|
|
@ -13,10 +13,11 @@ export const propPopover = {
|
|||
name: "",
|
||||
};
|
||||
|
||||
export const EdPropPopoverForm: FC<{ mprop: FMCompDef; name: string }> = ({
|
||||
mprop,
|
||||
name,
|
||||
}) => {
|
||||
export const EdPropPopoverForm: FC<{
|
||||
mprop: FMCompDef;
|
||||
name: string;
|
||||
closing: boolean;
|
||||
}> = ({ mprop, name, closing }) => {
|
||||
const p = useGlobal(EDGlobal, "EDITOR");
|
||||
const mmeta = mprop.get("meta");
|
||||
const local = useLocal({
|
||||
|
|
@ -28,7 +29,8 @@ export const EdPropPopoverForm: FC<{ mprop: FMCompDef; name: string }> = ({
|
|||
return (
|
||||
<div
|
||||
className={cx(
|
||||
"flex text-sm flex-col items-stretch space-y-1 py-1 w-[300px]"
|
||||
"flex text-sm flex-col items-stretch space-y-1 py-1 w-[300px]",
|
||||
closing && "hidden"
|
||||
)}
|
||||
>
|
||||
<div className="px-2 py-1 flex space-x-1">
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import { FMCompDef, FNCompDef } from "../../../../../utils/types/meta-fn";
|
|||
import { Popover } from "../../../../../utils/ui/popover";
|
||||
import { EdPropPopoverForm, propPopover } from "./prop-form";
|
||||
import { TypedMap } from "yjs-types";
|
||||
import { useLocal } from "web-utils";
|
||||
|
||||
export type PropItem = {
|
||||
name: string;
|
||||
|
|
@ -18,6 +19,7 @@ export const EdPropCompTreeItem: FC<{
|
|||
params: Parameters<NodeRender<PropItem>>[1];
|
||||
render: () => void;
|
||||
}> = ({ node, params, render }) => {
|
||||
const local = useLocal({ closing: false });
|
||||
if (node.id === "root") {
|
||||
return <></>;
|
||||
}
|
||||
|
|
@ -51,14 +53,24 @@ export const EdPropCompTreeItem: FC<{
|
|||
popoverClassName="bg-white shadow-lg border border-slate-300"
|
||||
onOpenChange={(open) => {
|
||||
if (!open) {
|
||||
propPopover.name = "";
|
||||
local.closing = true;
|
||||
local.render();
|
||||
setTimeout(() => {
|
||||
propPopover.name = "";
|
||||
render();
|
||||
});
|
||||
} else {
|
||||
local.closing = false;
|
||||
propPopover.name = node.text;
|
||||
render();
|
||||
}
|
||||
render();
|
||||
}}
|
||||
content={
|
||||
<EdPropPopoverForm mprop={node.data.mprop} name={node.text} />
|
||||
<EdPropPopoverForm
|
||||
closing={local.closing}
|
||||
mprop={node.data.mprop}
|
||||
name={node.text}
|
||||
/>
|
||||
}
|
||||
className="flex-1 pl-1 hover:bg-blue-100 cursor-pointer items-center flex"
|
||||
>
|
||||
|
|
|
|||
|
|
@ -15,6 +15,24 @@ type CompilerOptions = Parameters<
|
|||
|
||||
export const jsMount = async (editor: MonacoEditor, monaco: Monaco, p?: PG) => {
|
||||
const m = monaco as any;
|
||||
|
||||
if (editor.getModel()) {
|
||||
const jsxHgController = new MonacoJsxSyntaxHighlight(getWorker(), monaco);
|
||||
const { highlighter } = jsxHgController.highlighterBuilder({
|
||||
editor: editor,
|
||||
});
|
||||
|
||||
if (typeof editor.getModel === "function") {
|
||||
highlighter();
|
||||
}
|
||||
editor.onDidChangeModelContent(() => {
|
||||
if (typeof editor.getModel === "function") {
|
||||
try {
|
||||
highlighter();
|
||||
} catch (e) {}
|
||||
}
|
||||
});
|
||||
}
|
||||
if (!m.customJSMounted) {
|
||||
m.customJSMounted = true;
|
||||
} else {
|
||||
|
|
@ -267,24 +285,6 @@ export const jsMount = async (editor: MonacoEditor, monaco: Monaco, p?: PG) => {
|
|||
);
|
||||
|
||||
setTimeout(() => {
|
||||
if (editor.getModel()) {
|
||||
const jsxHgController = new MonacoJsxSyntaxHighlight(getWorker(), monaco);
|
||||
const { highlighter } = jsxHgController.highlighterBuilder({
|
||||
editor: editor,
|
||||
});
|
||||
|
||||
if (typeof editor.getModel === "function") {
|
||||
highlighter();
|
||||
}
|
||||
editor.onDidChangeModelContent(() => {
|
||||
if (typeof editor.getModel === "function") {
|
||||
try {
|
||||
highlighter();
|
||||
} catch (e) {}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
editor.getAction("editor.action.formatDocument")?.run();
|
||||
}, 100);
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in New Issue