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

View File

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

View File

@ -65,14 +65,6 @@ const map_childs = (
for (const m of childs) {
const meta = metas[m.id];
if (meta) {
if (
meta.item.type === "item" &&
meta.item.component?.id &&
meta.item.component?.id !== active.comp_id
) {
continue;
}
let cur: null | IMeta[] = null;
for (const path of paths) {
if (path[path.length - 1] === parent) {
@ -88,8 +80,16 @@ const map_childs = (
}
if (cur) {
if (Array.isArray(meta.item.childs)) {
map_childs(metas, meta.item.childs, paths, cur, meta);
if (
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={() => {
p.script.do_edit(
`\
<PassProp idx={0}>
{children}
</PassProp>
<PassProp idx={0} children={children} />
`,
false
);
@ -63,9 +61,9 @@ effect={async (local) => {
`\
<div {...props}>
{(local.list || []).map((item, idx) => (
<PassProp item={item} key={idx}>
{children}
</PassProp>
<Fragment key={idx}>
<PassProp item={item} children={children} />
</Fragment>
))}
</div>
`,

View File

@ -68,6 +68,9 @@ const CompTitleInstance = () => {
const props = item.component.props;
return (
<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>
<ArrowRight />
<div>{p.ui.popup.script.prop_name}</div>
@ -91,6 +94,9 @@ const CompTitleMaster = () => {
const props = item.component.props;
return (
<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>
<ArrowRight />
<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 { IItem } from "../../../../utils/types/item";
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 { reset } from "./prop-instance/prop-reset";
import { EdPropInstanceText } from "./prop-instance/prop-text";
import { createEditScript } from "./prop-instance/edit-script";
export const EdSidePropInstance: FC<{ meta: IMeta }> = ({ meta }) => {
const p = useGlobal(EDGlobal, "EDITOR");
const local = useLocal({
rightClickEvent: null as any,
reset: { mprop: null as any, name: "" },
pick: { mprop: null as any, name: "" },
showJSX: false,
});
@ -125,12 +126,20 @@ export const EdSidePropInstance: FC<{ meta: IMeta }> = ({ meta }) => {
<MenuItem
label="Reset"
onClick={() => {
if (local.reset.name) {
reset(p, comp_id, local.reset.mprop, local.reset.name);
if (local.pick.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>
)}
{filtered.length === 0 && (
@ -143,35 +152,52 @@ export const EdSidePropInstance: FC<{ meta: IMeta }> = ({ meta }) => {
let hasCode = false;
const value = mprop.get("value") || "";
if (!!value && ![`"`, "'", "`"].includes(value[0])) {
if (
!!value &&
(![`"`, "'", "`"].includes(value[0]) ||
![`"`, "'", "`"].includes(value[value.length - 1]))
) {
hasCode = true;
}
if (value.length > 100) {
hasCode = true;
}
const labelClick = (e: MouseEvent<HTMLDivElement>) => {
e.preventDefault();
local.pick = { mprop, name };
local.rightClickEvent = e;
local.render();
};
return (
<div
key={name}
className="border-b text-[13px] relative"
onContextMenu={(e) => {
e.preventDefault();
local.reset = { mprop, name };
local.rightClickEvent = e;
local.render();
}}
className="border-b text-[13px] relative hover:bg-orange-100 cursor-default"
onContextMenu={labelClick}
>
{hasCode ? (
<>
<EdPropInstanceCode mprop={mprop} name={name} />
<EdPropInstanceCode
mprop={mprop}
name={name}
labelClick={labelClick}
/>
</>
) : (
<>
{type === "text" && (
<EdPropInstanceText mprop={mprop} name={name} />
<EdPropInstanceText
mprop={mprop}
name={name}
labelClick={labelClick}
/>
)}
{type === "option" && (
<EdPropInstanceOptions mprop={mprop} name={name} />
<EdPropInstanceOptions
mprop={mprop}
name={name}
labelClick={labelClick}
/>
)}
{type === "content-element" && (
<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<{
name: string;
mprop: FMCompDef;
}> = ({ name, mprop }) => {
labelClick?: React.MouseEventHandler<HTMLDivElement> | undefined;
}> = ({ name, labelClick }) => {
const p = useGlobal(EDGlobal, "EDITOR");
return (
<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="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 { 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 = (
<div className="px-1 flex items-center">
<div className=" w-[70px] overflow-hidden text-ellipsis whitespace-nowrap flex items-center">
<div className="px-1 flex items-center" onClick={labelClick}>
<div className="select-none w-[70px] overflow-hidden text-ellipsis whitespace-nowrap flex items-center">
{name}
</div>
</div>

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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