This commit is contained in:
Rizky 2023-12-26 08:36:41 +07:00
parent 63b86d5346
commit c2c68a8a32
19 changed files with 132 additions and 54 deletions

View File

@ -38,6 +38,7 @@ export const code_edit: SAction["code"]["edit"] = async function (
if (root) { if (root) {
const mitem = findId(root, item_id); const mitem = findId(root, item_id);
if (mitem) { if (mitem) {
if (arg.type === "adv") { if (arg.type === "adv") {
const mode = arg.mode; const mode = arg.mode;
@ -78,6 +79,7 @@ export const code_edit: SAction["code"]["edit"] = async function (
.get("component") .get("component")
?.get("props") ?.get("props")
?.get(arg.prop_name); ?.get(arg.prop_name);
if (mprop) { if (mprop) {
try { try {
const res = await transform(`return ${src}`, { const res = await transform(`return ${src}`, {
@ -137,7 +139,6 @@ export const code_edit: SAction["code"]["edit"] = async function (
} }
} }
} }
return false; return false;
}; };

View File

@ -211,7 +211,7 @@ export const EdScriptMonaco: FC<{}> = () => {
}); });
} else if (p.ui.popup.script.type === "prop-instance") { } else if (p.ui.popup.script.type === "prop-instance") {
scope = await p.sync.code.edit({ scope = await p.sync.code.edit({
type: "adv", type: "prop-instance",
mode: type, mode: type,
prop_name: p.ui.popup.script.prop_name, prop_name: p.ui.popup.script.prop_name,
item_id: active.item_id, item_id: active.item_id,

View File

@ -65,14 +65,6 @@ const map_childs = (
for (const m of childs) { for (const m of childs) {
const meta = metas[m.id]; const meta = metas[m.id];
if (meta) { if (meta) {
if (
meta.item.type === "item" &&
meta.item.component?.id &&
meta.item.component?.id !== active.comp_id
) {
continue;
}
let cur: null | IMeta[] = null; let cur: null | IMeta[] = null;
for (const path of paths) { for (const path of paths) {
if (path[path.length - 1] === parent) { if (path[path.length - 1] === parent) {
@ -88,8 +80,16 @@ const map_childs = (
} }
if (cur) { if (cur) {
if (Array.isArray(meta.item.childs)) { if (
map_childs(metas, meta.item.childs, paths, cur, meta); meta.item.type === "item" &&
meta.item.component?.id &&
meta.item.component?.id !== active.comp_id
) {
continue;
} else {
if (Array.isArray(meta.item.childs)) {
map_childs(metas, meta.item.childs, paths, cur, meta);
}
} }
} }
} }

View File

@ -46,9 +46,7 @@ effect={async (local) => {
onClick={() => { onClick={() => {
p.script.do_edit( p.script.do_edit(
`\ `\
<PassProp idx={0}> <PassProp idx={0} children={children} />
{children}
</PassProp>
`, `,
false false
); );
@ -63,9 +61,9 @@ effect={async (local) => {
`\ `\
<div {...props}> <div {...props}>
{(local.list || []).map((item, idx) => ( {(local.list || []).map((item, idx) => (
<PassProp item={item} key={idx}> <Fragment key={idx}>
{children} <PassProp item={item} children={children} />
</PassProp> </Fragment>
))} ))}
</div> </div>
`, `,

View File

@ -68,6 +68,9 @@ const CompTitleInstance = () => {
const props = item.component.props; const props = item.component.props;
return ( return (
<div className="flex text-xs p-2 space-x-1 items-center"> <div className="flex text-xs p-2 space-x-1 items-center">
<div className="bg-blue-700 text-white text-[11px] px-1 mr-1">
INSTANCE
</div>
<div>{item.name}</div> <div>{item.name}</div>
<ArrowRight /> <ArrowRight />
<div>{p.ui.popup.script.prop_name}</div> <div>{p.ui.popup.script.prop_name}</div>
@ -91,6 +94,9 @@ const CompTitleMaster = () => {
const props = item.component.props; const props = item.component.props;
return ( return (
<div className="flex text-xs p-2 space-x-1 items-center"> <div className="flex text-xs p-2 space-x-1 items-center">
<div className="bg-purple-700 text-white text-[11px] px-1 mr-1">
MASTER
</div>
<div>{item.name}</div> <div>{item.name}</div>
<ArrowRight /> <ArrowRight />
<div>{p.ui.popup.script.prop_name}</div> <div>{p.ui.popup.script.prop_name}</div>

View File

@ -1,4 +1,4 @@
import { FC } from "react"; import { FC, MouseEvent } from "react";
import { useGlobal, useLocal } from "web-utils"; import { useGlobal, useLocal } from "web-utils";
import { IItem } from "../../../../utils/types/item"; import { IItem } from "../../../../utils/types/item";
import { FMCompDef } from "../../../../utils/types/meta-fn"; import { FMCompDef } from "../../../../utils/types/meta-fn";
@ -8,12 +8,13 @@ import { EdPropInstanceCode } from "./prop-instance/prop-code";
import { EdPropInstanceOptions } from "./prop-instance/prop-option"; import { EdPropInstanceOptions } from "./prop-instance/prop-option";
import { reset } from "./prop-instance/prop-reset"; import { reset } from "./prop-instance/prop-reset";
import { EdPropInstanceText } from "./prop-instance/prop-text"; import { EdPropInstanceText } from "./prop-instance/prop-text";
import { createEditScript } from "./prop-instance/edit-script";
export const EdSidePropInstance: FC<{ meta: IMeta }> = ({ meta }) => { export const EdSidePropInstance: FC<{ meta: IMeta }> = ({ meta }) => {
const p = useGlobal(EDGlobal, "EDITOR"); const p = useGlobal(EDGlobal, "EDITOR");
const local = useLocal({ const local = useLocal({
rightClickEvent: null as any, rightClickEvent: null as any,
reset: { mprop: null as any, name: "" }, pick: { mprop: null as any, name: "" },
showJSX: false, showJSX: false,
}); });
@ -125,12 +126,20 @@ export const EdSidePropInstance: FC<{ meta: IMeta }> = ({ meta }) => {
<MenuItem <MenuItem
label="Reset" label="Reset"
onClick={() => { onClick={() => {
if (local.reset.name) { if (local.pick.name) {
reset(p, comp_id, local.reset.mprop, local.reset.name); reset(p, comp_id, local.pick.mprop, local.pick.name);
} }
}} }}
/> />
<MenuItem label={"Edit Code"} onClick={() => {}} /> <MenuItem
label={"Edit Code"}
onClick={createEditScript(
p,
"value",
local.pick.mprop,
local.pick.name
)}
/>
</Menu> </Menu>
)} )}
{filtered.length === 0 && ( {filtered.length === 0 && (
@ -143,35 +152,52 @@ export const EdSidePropInstance: FC<{ meta: IMeta }> = ({ meta }) => {
let hasCode = false; let hasCode = false;
const value = mprop.get("value") || ""; const value = mprop.get("value") || "";
if (!!value && ![`"`, "'", "`"].includes(value[0])) { if (
!!value &&
(![`"`, "'", "`"].includes(value[0]) ||
![`"`, "'", "`"].includes(value[value.length - 1]))
) {
hasCode = true; hasCode = true;
} }
if (value.length > 100) { if (value.length > 100) {
hasCode = true; hasCode = true;
} }
const labelClick = (e: MouseEvent<HTMLDivElement>) => {
e.preventDefault();
local.pick = { mprop, name };
local.rightClickEvent = e;
local.render();
};
return ( return (
<div <div
key={name} key={name}
className="border-b text-[13px] relative" className="border-b text-[13px] relative hover:bg-orange-100 cursor-default"
onContextMenu={(e) => { onContextMenu={labelClick}
e.preventDefault();
local.reset = { mprop, name };
local.rightClickEvent = e;
local.render();
}}
> >
{hasCode ? ( {hasCode ? (
<> <>
<EdPropInstanceCode mprop={mprop} name={name} /> <EdPropInstanceCode
mprop={mprop}
name={name}
labelClick={labelClick}
/>
</> </>
) : ( ) : (
<> <>
{type === "text" && ( {type === "text" && (
<EdPropInstanceText mprop={mprop} name={name} /> <EdPropInstanceText
mprop={mprop}
name={name}
labelClick={labelClick}
/>
)} )}
{type === "option" && ( {type === "option" && (
<EdPropInstanceOptions mprop={mprop} name={name} /> <EdPropInstanceOptions
mprop={mprop}
name={name}
labelClick={labelClick}
/>
)} )}
{type === "content-element" && ( {type === "content-element" && (
<div className="min-h-[28px] px-1 flex items-center"> <div className="min-h-[28px] px-1 flex items-center">

View File

@ -0,0 +1,25 @@
import { MouseEventHandler } from "react";
import { FMCompDef } from "../../../../../utils/types/meta-fn";
import { PG, PropFieldKind } from "../../../logic/ed-global";
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-instance";
p.ui.popup.script.prop_kind = kind;
p.ui.popup.script.prop_name = name;
p.render();
}
}) as MouseEventHandler<HTMLButtonElement>;
};

View File

@ -7,11 +7,12 @@ import { EDGlobal, active } from "../../../logic/ed-global";
export const EdPropInstanceCode: FC<{ export const EdPropInstanceCode: FC<{
name: string; name: string;
mprop: FMCompDef; mprop: FMCompDef;
}> = ({ name, mprop }) => { labelClick?: React.MouseEventHandler<HTMLDivElement> | undefined;
}> = ({ name, labelClick }) => {
const p = useGlobal(EDGlobal, "EDITOR"); const p = useGlobal(EDGlobal, "EDITOR");
return ( return (
<div className="flex items-center min-h-[28px]"> <div className="flex items-center min-h-[28px]">
<EdPropLabel name={name} /> <EdPropLabel name={name} labelClick={labelClick} />
<div className="flex-1 flex justify-end pr-1"> <div className="flex-1 flex justify-end pr-1">
<div <div
className="m-1 px-1 bg-white cursor-pointer hover:bg-blue-500 hover:text-white hover:border-blue-500 font-mono border border-slate-300 text-[11px] select-none" className="m-1 px-1 bg-white cursor-pointer hover:bg-blue-500 hover:text-white hover:border-blue-500 font-mono border border-slate-300 text-[11px] select-none"

View File

@ -1,10 +1,13 @@
import { FC } from "react"; import { FC } from "react";
import { Tooltip } from "../../../../../utils/ui/tooltip"; import { Tooltip } from "../../../../../utils/ui/tooltip";
export const EdPropLabel: FC<{ name: string }> = ({ name }) => { export const EdPropLabel: FC<{
name: string;
labelClick?: React.MouseEventHandler<HTMLDivElement> | undefined;
}> = ({ name, labelClick }) => {
const label = ( const label = (
<div className="px-1 flex items-center"> <div className="px-1 flex items-center" onClick={labelClick}>
<div className=" w-[70px] overflow-hidden text-ellipsis whitespace-nowrap flex items-center"> <div className="select-none w-[70px] overflow-hidden text-ellipsis whitespace-nowrap flex items-center">
{name} {name}
</div> </div>
</div> </div>

View File

@ -10,7 +10,8 @@ import { EdPropLabel } from "./prop-label";
export const EdPropInstanceOptions: FC<{ export const EdPropInstanceOptions: FC<{
name: string; name: string;
mprop: FMCompDef; mprop: FMCompDef;
}> = ({ name, mprop }) => { labelClick?: React.MouseEventHandler<HTMLDivElement> | undefined;
}> = ({ name, mprop, labelClick }) => {
const prop = mprop.toJSON() as FNCompDef; const prop = mprop.toJSON() as FNCompDef;
const local = useLocal({ const local = useLocal({
codeEditing: false, codeEditing: false,
@ -85,7 +86,7 @@ else metaOptions = resOpt;
if (!mode) mode = "button"; if (!mode) mode = "button";
return ( return (
<div className="flex items-stretch min-h-[28px]"> <div className="flex items-stretch min-h-[28px]">
<EdPropLabel name={name} /> <EdPropLabel name={name} labelClick={labelClick} />
<div className="flex flex-1 justify-end"> <div className="flex flex-1 justify-end">
{mode === "dropdown" && ( {mode === "dropdown" && (
<> <>

View File

@ -12,7 +12,8 @@ import { EdPropLabel } from "./prop-label";
export const EdPropInstanceText: FC<{ export const EdPropInstanceText: FC<{
name: string; name: string;
mprop: FMCompDef; mprop: FMCompDef;
}> = ({ name, mprop }) => { labelClick?: React.MouseEventHandler<HTMLDivElement> | undefined;
}> = ({ name, mprop, labelClick }) => {
const val = mprop.get("value"); const val = mprop.get("value");
const local = useLocal({ const local = useLocal({
@ -28,7 +29,7 @@ export const EdPropInstanceText: FC<{
return ( return (
<div className="flex items-center min-h-[28px]"> <div className="flex items-center min-h-[28px]">
<EdPropLabel name={name} /> <EdPropLabel name={name} labelClick={labelClick} />
<AutoHeightTextarea <AutoHeightTextarea
className="flex-1 outline-none border-l p-1 overflow-hidden focus:bg-blue-50" className="flex-1 outline-none border-l p-1 overflow-hidden focus:bg-blue-50"
value={local.value || ""} value={local.value || ""}

View File

@ -31,6 +31,10 @@ export const genComp = (p: GenMetaP, arg: GenMetaArg) => {
ids: instance, ids: instance,
}); });
if (item.component) {
item.component.loaded = true;
}
let smeta = p.comps[item.component.id].smeta; let smeta = p.comps[item.component.id].smeta;
if (smeta) { if (smeta) {
smeta = applySMeta(smeta, instance); smeta = applySMeta(smeta, instance);

View File

@ -34,9 +34,11 @@ export const viParts = (
const childs = meta.item.childs; const childs = meta.item.childs;
let children = undefined; let children = undefined;
if ((meta.item as IContent).type === "text") { if ((meta.item as IContent).type === "text") {
children = <HTMLChild props={text_props} />; children = <HTMLChild props={text_props} />;
} else { } else {
children = children =
Array.isArray(childs) && Array.isArray(childs) &&
childs?.map((item) => { childs?.map((item) => {

View File

@ -13,6 +13,7 @@ export const ViRender: FC<{
}> = ({ meta, children, passprop }) => { }> = ({ meta, children, passprop }) => {
if (!meta) return null; if (!meta) return null;
if (meta.item.hidden) return null; if (meta.item.hidden) return null;
if (meta.item.adv?.js || meta.item.component?.id) { if (meta.item.adv?.js || meta.item.component?.id) {

View File

@ -22,8 +22,8 @@ export const ViScript: FC<{
} }
if (meta.item.adv?.js) { if (meta.item.adv?.js) {
viEvalScript(vi, meta, _pass); const mhash = viEvalScript(vi, meta, _pass);
if (meta.script) return meta.script.result; if (meta.script && meta.script[mhash]) return meta.script[mhash].result;
} }
return ( return (

View File

@ -7,6 +7,7 @@ import { viScriptArg } from "./arg";
import { updatePropScope } from "./eval-prop"; import { updatePropScope } from "./eval-prop";
import { createViLocal } from "./local"; import { createViLocal } from "./local";
import { createViPassProp } from "./passprop"; import { createViPassProp } from "./passprop";
import hash_sum from "hash-sum";
export const viEvalScript = ( export const viEvalScript = (
vi: { vi: {
@ -21,8 +22,11 @@ export const viEvalScript = (
if (vi.visit) vi.visit(meta, parts); if (vi.visit) vi.visit(meta, parts);
if (!meta.script) { const mhash = hash_sum(passprop);
meta.script = {
if (!meta.script) meta.script = {};
if (!meta.script[mhash]) {
meta.script[mhash] = {
result: null, result: null,
Local: createViLocal( Local: createViLocal(
vi.meta, vi.meta,
@ -33,7 +37,7 @@ export const viEvalScript = (
PassProp: createViPassProp(vi, meta, passprop), PassProp: createViPassProp(vi, meta, passprop),
}; };
} }
const script = meta.script; const script = meta.script[mhash];
const exports = (window as any).exports; const exports = (window as any).exports;
const arg = { const arg = {
@ -61,4 +65,5 @@ ${meta.item.adv?.jsBuilt || ""}
fn(...Object.values(arg)); fn(...Object.values(arg));
updatePropScope(meta, passprop); updatePropScope(meta, passprop);
return mhash;
}; };

View File

@ -32,6 +32,7 @@ const modify = (el: ReactNode, arg: any, passprop?: any) => {
if (isValidElement(el)) { if (isValidElement(el)) {
const passarg = { ...arg }; const passarg = { ...arg };
delete passarg.children; delete passarg.children;
return { return {
...el, ...el,
props: { ...el.props, passprop: { ...passprop, ...passarg } }, props: { ...el.props, passprop: { ...passprop, ...passarg } },

View File

@ -59,11 +59,14 @@ export type IMeta = {
comp_id: string; comp_id: string;
is_root: boolean; is_root: boolean;
}; };
script?: { script?: Record<
result: ReactNode; string,
Local: ReturnType<typeof createViLocal>; {
PassProp: ReturnType<typeof createViPassProp>; result: ReactNode;
}; Local: ReturnType<typeof createViLocal>;
PassProp: ReturnType<typeof createViPassProp>;
}
>;
scope: { scope: {
def?: ReturnType<typeof parseJs>; def?: ReturnType<typeof parseJs>;
}; };

View File

@ -22,7 +22,7 @@ export type FMAdv = TypedMap<FNAdv>;
export type FNComponent = { export type FNComponent = {
id: string; id: string;
name?: string; name?: string;
updated_at?: number; loaded?: boolean;
props: Record<string, FNCompDef>; props: Record<string, FNCompDef>;
ref_ids?: Record<string, string>; ref_ids?: Record<string, string>;
}; };