This commit is contained in:
Rizky 2024-04-15 11:13:57 +07:00
parent 36b0dcc5f1
commit 2f5cdc1747
5 changed files with 56 additions and 193 deletions

View File

@ -1,26 +1,20 @@
import { FC } from "react";
import { useGlobal } from "web-utils";
import { useGlobal, useLocal } from "web-utils";
import { IItem } from "../../../../../../utils/types/item";
import { FNAdv } from "../../../../../../utils/types/meta-fn";
import { ISection } from "../../../../../../utils/types/section";
import { IText } from "../../../../../../utils/types/text";
import { Popover } from "../../../../../../utils/ui/popover";
import { EDGlobal } from "../../../../logic/ed-global";
import { SimpleMonaco } from "../../simple-monaco";
import { Button } from "../ui/Button";
import { getActiveMeta } from "../../../../logic/active/get-meta";
type AdvUpdate = {
adv?: FNAdv;
};
export const PanelAdv: FC<{
value: ISection | IItem | IText;
mode: "desktop" | "mobile";
update: <T extends keyof AdvUpdate>(key: T, val: AdvUpdate[T]) => void;
update: <T extends "typings">(key: T, val: string) => void;
}> = ({ value, update }) => {
const p = useGlobal(EDGlobal, "EDITOR");
const meta = getActiveMeta(p);
const adv = meta?.mitem?.get("adv")?.toJSON() || ({} as any);
const local = useLocal({ openTypings: false, typings: "" });
return (
<>
<div
@ -33,21 +27,52 @@ export const PanelAdv: FC<{
`
)}
>
<div
<Popover
content={
<div
className={cx(css`
width: 700px;
height: 500px;
margin: 5px 0px;
`)}
>
<SimpleMonaco
onChange={(value) => {
local.typings = value;
local.render();
}}
value={local.typings}
lang="typescript"
/>
</div>
}
open={local.openTypings}
onOpenChange={(open) => {
try {
if (open) {
local.typings =
value.typings ||
`\
const typings = {
_raw: {
}
}`;
} else {
update("typings", local.typings);
}
} catch (e) {
console.log(e);
}
local.openTypings = open;
local.render();
}}
className={cx(
"bg-white p-[2px] border flex flex-1 border-gray-300",
css`
> * {
flex: 1;
}
`,
!!adv.css &&
css`
button {
background: #e8ffe8;
border-bottom: solid green !important;
}
`
`
)}
>
<Button
@ -56,64 +81,9 @@ export const PanelAdv: FC<{
}}
appearance="subtle"
>
CSS
Typings
</Button>
</div>
<div
className={cx(
"bg-white p-[2px] border flex flex-1 border-gray-300",
css`
> * {
flex: 1;
}
`,
!!adv.html && [
css`
button {
background: #e8f5ff;
border-bottom: 2px solid blue !important;
}
`,
]
)}
>
<Button
onClick={() => {
p.render();
}}
appearance="subtle"
>
HTML
</Button>
</div>
<div
className={cx(
"bg-white p-[2px] border flex flex-1 border-gray-300",
css`
> * {
flex: 1;
}
`,
!!adv.js && [
css`
button {
background: #fff4e8;
border-bottom: 2px solid orange !important;
}
`,
]
)}
>
<Button
appearance="subtle"
className="js"
onClick={() => {
p.render();
}}
>
JS
</Button>
</div>
</Popover>
</div>
</>
);

View File

@ -1,111 +0,0 @@
import {
FC,
TextareaHTMLAttributes,
useCallback,
useEffect,
useRef,
} from "react";
import { useLocal } from "web-utils";
import { IItem } from "../../../../../../utils/types/item";
import { FNLinkTag } from "../../../../../../utils/types/meta-fn";
import { ISection } from "../../../../../../utils/types/section";
import { IText } from "../../../../../../utils/types/text";
import { responsiveVal } from "../tools/responsive-val";
type LinkTagUpdate = {
linktag: FNLinkTag;
};
export const PanelLink: FC<{
value: ISection | IItem | IText;
mode: "desktop" | "mobile";
update: <T extends keyof LinkTagUpdate>(
key: T,
val: LinkTagUpdate[T]
) => void;
}> = ({ value, update, mode }) => {
const linktag = responsiveVal<FNLinkTag>(value, "linktag", mode, {});
const local = useLocal({ link: linktag.link });
useEffect(() => {
local.link = linktag.link;
local.render();
}, [linktag.link]);
return (
<>
<AutoHeightTextarea
spellCheck={false}
minRows={1}
className={cx("flex-1 border border-slate-300 p-1 h-[25px]")}
value={local.link || ""}
placeholder="Link Href"
onChange={(e) => {
local.link = e.currentTarget.value;
local.render();
}}
onBlur={() => {
update("linktag", { ...linktag, link: local.link });
}}
/>
</>
);
};
export function AutoHeightTextarea({
minRows = 1,
...props
}: TextareaHTMLAttributes<HTMLTextAreaElement> & { minRows?: number }) {
const ref = useRef<HTMLTextAreaElement>(null);
const calculateAndSetHeight = useCallback(() => {
if (!ref.current) {
return;
}
const {
borderBottomWidth,
borderTopWidth,
boxSizing,
lineHeight,
paddingBottom,
paddingTop,
} = window.getComputedStyle(ref.current);
ref.current.style.height = lineHeight; // set height temporarily to a single row to obtain scrollHeight, disregarding empty space after text (otherwise, scrollHeight would be equal to the height of the element) - this solves auto-shrinking of the textarea (it's not needed for auto-growing it)
const { scrollHeight } = ref.current; // scrollHeight = content height + padding top + padding bottom
if (boxSizing === "border-box") {
const minHeight =
parseFloat(lineHeight) * minRows +
parseFloat(paddingTop) +
parseFloat(paddingBottom) +
parseFloat(borderTopWidth) +
parseFloat(borderBottomWidth);
const allTextHeight =
scrollHeight +
parseFloat(borderTopWidth) +
parseFloat(borderBottomWidth);
ref.current.style.height = `${Math.max(minHeight, allTextHeight)}px`;
} else if (boxSizing === "content-box") {
const minHeight = parseFloat(lineHeight) * minRows;
const allTextHeight =
scrollHeight - parseFloat(paddingTop) - parseFloat(paddingBottom);
ref.current.style.height = `${Math.max(minHeight, allTextHeight)}px`;
} else {
console.error("Unknown box-sizing value.");
}
}, [minRows]);
useEffect(() => {
calculateAndSetHeight();
}, [calculateAndSetHeight]);
const handleChange: React.ChangeEventHandler<HTMLTextAreaElement> = (e) => {
calculateAndSetHeight();
if (props.onChange) {
props.onChange(e);
}
};
calculateAndSetHeight();
return <textarea {...props} onChange={handleChange} ref={ref} />;
}

View File

@ -8,7 +8,6 @@ import { PanelBackground } from "./panel/background";
import { PanelBorder } from "./panel/border";
import { PanelDimension } from "./panel/dimension";
import { PanelFont } from "./panel/font";
import { PanelLink } from "./panel/link";
import { PanelPadding } from "./panel/padding";
import { SideBox } from "./ui/SideBox";
import { SideLabel } from "./ui/SideLabel";
@ -86,6 +85,8 @@ export const EdStyleAll: FC<{ as_child?: boolean }> = ({ as_child }) => {
} else {
nprop = new Y.Map();
}
} else {
nprop = value;
}
if (mitem) {
mitem.set(key, nprop);
@ -94,7 +95,11 @@ export const EdStyleAll: FC<{ as_child?: boolean }> = ({ as_child }) => {
}
if (prop) {
syncronize(prop, value);
if (typeof value === "object") {
syncronize(prop, value);
} else if (mitem) {
mitem.set(key, value);
}
}
}
});
@ -149,7 +154,6 @@ export const EdStyleAll: FC<{ as_child?: boolean }> = ({ as_child }) => {
</SideBox>
<SideLabel>ADVANCED</SideLabel>
<SideBox>
<PanelLink value={item} mode={p.mode} update={update} />
<PanelAdv value={item} mode={p.mode} update={update} />
</SideBox>
</>

View File

@ -100,7 +100,7 @@ export const ESide = () => {
local.lastActive = null;
}
if (compItem && !compItem.props) {
const comp = mitem?.get("component");
const comp = (mitem as MItem)?.get("component");
if (comp) {
comp.set("props", new Y.Map() as any);
}
@ -204,7 +204,6 @@ export const ESide = () => {
</SideBox>
<SideLabel>ADVANCED</SideLabel>
<SideBox>
<PanelLink value={active} mode={p.mode} update={update} />
<PanelAdv value={active} mode={p.mode} update={update} />
</SideBox>
</>

View File

@ -34,6 +34,7 @@ export type BasicItem = {
border?: FNBorder;
script?: ReturnType<typeof parseJs>;
script_keyed?: Record<string, ReturnType<typeof parseJs>>;
typings?: string;
};
export type MBasicItem = {