This commit is contained in:
Rizky 2023-12-07 18:38:07 +07:00
parent 5699d37453
commit 77a527447c
9 changed files with 123 additions and 83 deletions

View File

@ -16,6 +16,7 @@ export const user = {
site_id: string;
page_id: string;
comp_id?: string;
client_id: string;
select: "" | "comp" | "item" | "section" | "text";
},
"client_id"

View File

@ -12,6 +12,7 @@
"@minoru/react-dnd-treeview": "^3.4.4",
"@monaco-editor/react": "^4.6.0",
"@paralleldrive/cuid2": "2.2.2",
"react-contenteditable": "^3.3.7",
"@parcel/packager-wasm": "^2.10.3",
"@parcel/service-worker": "^2.10.3",
"recast": "^0.23.4",

View File

@ -64,7 +64,7 @@ const target = {
};
export const active = {
hover_id: "",
text: { id: "", content: "" },
text: { id: "", content: "", timeout: null as any, el: null as any },
get item_id() {
if (target.active_id === false) {
target.active_id = localStorage.getItem("prasi-active-id") || "";

View File

@ -1,10 +1,11 @@
import { useGlobal } from "web-utils";
import { useGlobal, useLocal } from "web-utils";
import { Loading } from "../../../../utils/ui/loading";
import { View } from "../../../view/view";
import { EDGlobal, active } from "../../logic/ed-global";
import { getMetaById } from "../../logic/tree/build";
import { loadComponent } from "../../logic/tree/sync-walk";
import { code } from "../popup/code/code";
import { useEffect } from "react";
export const EdMain = () => {
const p = useGlobal(EDGlobal, "EDITOR");
@ -51,10 +52,11 @@ export const EdMain = () => {
const item = meta.item;
if (active.comp_id) {
if (meta.parent_mcomp) {
const p = meta.parent_mcomp;
if (p) {
if (
meta.parent_mcomp?.mcomp.get("component")?.get("id") !==
active.comp_id
p.mitem.get("id") !== active.instance.item_id ||
p.mcomp.get("component")?.get("id") !== active.comp_id
)
return false;
}
@ -112,15 +114,16 @@ export const EdMain = () => {
const item = meta.item;
if (active.comp_id) {
if (meta.parent_mcomp) {
const p = meta.parent_mcomp;
if (p) {
if (
meta.parent_mcomp?.mcomp.get("component")?.get("id") !==
active.comp_id
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
@ -194,46 +197,74 @@ export const EdMain = () => {
p.page.render();
focus();
},
text(meta) {
text({ meta }) {
const { item } = meta;
useEffect(() => {
return () => {
active.text.id = "";
p.render();
};
}, []);
const updateWithTimeout = (timeout: number) => {
return new Promise<void>((resolve) => {
const saving = {
id: active.text.id,
content: active.text.content,
};
clearTimeout(active.text.timeout);
active.text.timeout = setTimeout(() => {
const meta = getMetaById(p, saving.id);
if (meta && meta.mitem) {
meta.mitem.set("html", saving.content);
}
resolve();
}, timeout);
});
};
if (active.text.id !== item.id) {
clearTimeout(active.text.timeout);
active.text.id = item.id;
active.text.content = item.html || "";
active.text.el = (
<div
className={cx(
`v-text-${item.id} v-text-${item.originalId} outline-none`
)}
ref={(ref) => {
if (ref !== document.activeElement && ref) {
const renaming =
document.querySelector(".rename-item");
const modals = document.querySelectorAll(
"[data-floating-ui-portal]"
);
if (modals.length === 0 && !renaming) {
ref.focus();
setEndOfContenteditable(ref);
}
}
}}
onPointerDownCapture={(e) => {
e.stopPropagation();
}}
contentEditable
spellCheck={false}
onInput={(e) => {
const val = e.currentTarget.innerHTML;
item.html = val;
active.text.id = item.id;
active.text.content = val;
updateWithTimeout(100);
}}
dangerouslySetInnerHTML={{ __html: item.html || "" }}
></div>
);
}
return (
<div
className={cx(
`v-text-${item.id} v-text-${item.originalId} outline-none`
)}
ref={(ref) => {
if (ref !== document.activeElement && ref) {
const renaming = document.querySelector(".rename-item");
const modals = document.querySelectorAll(
"[data-floating-ui-portal]"
);
if (modals.length === 0 && !renaming) {
ref.focus();
setEndOfContenteditable(ref);
}
}
}}
contentEditable
spellCheck={false}
onInput={(e) => {
const val = e.currentTarget.innerHTML;
active.text.id = item.id;
active.text.content = val;
}}
onBlur={() => {
const meta = getMetaById(p, item.id);
if (meta && meta.mitem && active.text.id === item.id) {
meta.mitem.set("html", active.text.content);
}
}}
dangerouslySetInnerHTML={{ __html: item.html || "" }}
></div>
);
return active.text.el;
},
}}
/>

View File

@ -29,7 +29,7 @@ export const EdPropInstanceText: FC<{
if (val) {
try {
eval(`local.value = ${valBuilt}`);
} catch (e) { }
} catch (e) {}
} else {
local.value = "";
}
@ -41,7 +41,7 @@ export const EdPropInstanceText: FC<{
{name}
</div>
);
return (
<div className="flex items-center">
{name.length > 8 ? (
@ -52,7 +52,7 @@ export const EdPropInstanceText: FC<{
label
)}
<AutoHeightTextarea
className="flex-1 outline-none border-l p-1 ml-1 overflow-hidden"
className="flex-1 outline-none border-l p-1 ml-1 overflow-hidden focus:bg-blue-50"
value={local.value}
spellCheck={false}
onChange={(e) => {

View File

@ -25,7 +25,7 @@ export const ViewGlobal = {
| {
get: (meta: EdMeta) => boolean;
set: (meta: EdMeta) => void;
text?: (meta: EdMeta) => ReactNode;
text?: (arg: { meta: EdMeta }) => ReactNode;
},
hover: undefined as
| undefined

View File

@ -1,42 +1,48 @@
import { FC, Fragment, ReactNode } from "react";
import { useGlobal } from "web-utils";
import { useGlobal, useLocal } from "web-utils";
import { EdMeta } from "../../../ed/logic/ed-global";
import { ViewGlobal } from "../../logic/global";
import { ViewMeta } from "./meta";
export const ViewMetaChildren: FC<{
meta: EdMeta,
className?: string
}> = ({
meta,
className
}) => {
const v = useGlobal(ViewGlobal, "VIEW");
const children: Record<string, ReactNode> = {};
const item = meta.item;
if (item.type !== "text") {
for (const child of item.childs) {
if (child.id) {
children[child.id] = (<ViewMeta id={child.id} key={child.id} />);
}
}
} else {
if (item.id) {
if (v.view.active?.text && v.view.active?.get(meta)) {
children[item.id] = <Fragment key={item.id}>
{v.view.active.text(meta)}
</Fragment>;
} else {
children[item.id] = <span
key={item.id}
dangerouslySetInnerHTML={{ __html: item.html || '&nbsp;' }
}>
</span >;
}
meta: EdMeta;
className?: string;
}> = ({ meta, className }) => {
const v = useGlobal(ViewGlobal, "VIEW");
const children: Record<string, ReactNode> = {};
const item = meta.item;
if (item.type !== "text") {
for (const child of item.childs) {
if (child.id) {
children[child.id] = <ViewMeta id={child.id} key={child.id} />;
}
}
} else {
if (item.id) {
if (v.view.active?.text && v.view.active?.get(meta)) {
const ActiveText = v.view.active.text;
children[item.id] = (
<Fragment key={item.id}>
<ActiveText meta={meta} />
</Fragment>
);
} else {
children[item.id] = (
<span
key={item.id}
dangerouslySetInnerHTML={{ __html: item.html || "&nbsp;" }}
></span>
);
}
}
}
return <>
{/* <div className={"text-[9px] text-gray-500 -mt-1"}>{item.id} - {item.originalId}</div> */}
{Object.values(children)}</>;
};
return (
<>
{/* <div className={"text-[9px] text-gray-500 -mt-1"}>
{item.id} - {item.originalId}
</div> */}
{Object.values(children)}
</>
);
};

View File

@ -26,7 +26,7 @@ type ViewProp = {
active?: {
get: (item: EdMeta) => boolean;
set: (item: EdMeta) => void;
text?: (item: EdMeta) => ReactNode
text?: (arg: { meta: EdMeta }) => ReactNode;
};
};
@ -59,8 +59,9 @@ const BoxedView: FC<ViewProp> = ({
v.script.api_url = api_url;
if (hidden) v.view.hidden = hidden;
if (hover) v.view.hover = hover;
if (active) v.view.active = active;
if (hover && !v.view.hover) v.view.hover = hover;
if (active && !v.view.active) v.view.active = active;
if (v.current.page_id !== page_id || v.current.site_id !== site_id) {
v.status = "init";
}

BIN
bun.lockb

Binary file not shown.