diff --git a/app/web/src/nova/ed/logic/ed-global.ts b/app/web/src/nova/ed/logic/ed-global.ts index 4f993652..a47c77c5 100644 --- a/app/web/src/nova/ed/logic/ed-global.ts +++ b/app/web/src/nova/ed/logic/ed-global.ts @@ -146,9 +146,9 @@ export const EDGlobal = { on_update?: (bin: Uint8Array, origin: any) => Promise; } >, - scope: {} as IScope, building: false, meta: {} as Record, + smeta: {} as Record, entry: [] as string[], tree: [] as NodeModel[], render: () => {}, diff --git a/app/web/src/nova/ed/logic/ed-route.ts b/app/web/src/nova/ed/logic/ed-route.ts index 4865ff8e..50a61372 100644 --- a/app/web/src/nova/ed/logic/ed-route.ts +++ b/app/web/src/nova/ed/logic/ed-route.ts @@ -56,6 +56,7 @@ export const reloadPage = async (p: PG, page_id: string, note: string) => { } p.page.entry = remotePage.entry; + p.page.smeta = remotePage.meta; p.page.cur = remotePage; if (remotePage.snapshot) { diff --git a/app/web/src/nova/ed/logic/tree/build.tsx b/app/web/src/nova/ed/logic/tree/build.tsx index 22e6a7bd..20561a9e 100644 --- a/app/web/src/nova/ed/logic/tree/build.tsx +++ b/app/web/src/nova/ed/logic/tree/build.tsx @@ -1,7 +1,6 @@ import { IItem, MItem } from "../../../../utils/types/item"; -import { viEvalComp } from "../../../vi/render/comp"; -import { ViRender } from "../../../vi/render/render"; -import { ViScript } from "../../../vi/render/script"; +import { viEvalProps } from "../../../vi/render/comp"; +import { viEvalScript } from "../../../vi/render/script"; import { genMeta } from "../../../view/logic/meta/meta"; import { PG, active } from "../ed-global"; import { pushTreeNode } from "./build/push-tree"; @@ -34,29 +33,27 @@ export const treeRebuild = async (p: PG, arg?: { note?: string }) => { for (const mitem of mitems) { const item = mitem.toJSON() as IItem; if (item) { + p.page; genMeta( { comps: p.comp.loaded, meta, - on: !is_layout - ? { - visit(meta) { - pushTreeNode(p, meta); + smeta: p.page.smeta, + on: { + async visit(meta) { + if (!is_layout) { + pushTreeNode(p, meta); - if (!meta.item.adv?.js && !meta.item.component?.id) { - meta.fc = ViRender; - } else { - if (meta.item.component?.id) { - viEvalComp(meta); - } + if (meta.item.component?.props) { + viEvalProps({ meta: p.page.meta, tick: 0 }, meta); + } - if (meta.item.adv?.js) { - meta.fc = ViScript; - } - } - }, + if (meta.item.adv?.jsBuilt) { + viEvalScript({ meta: p.page.meta, tick: 0 }, meta); + } } - : undefined, + }, + }, }, { item, mitem } ); diff --git a/app/web/src/nova/ed/panel/main/main.tsx b/app/web/src/nova/ed/panel/main/main.tsx index ef7e985a..46c67fe3 100644 --- a/app/web/src/nova/ed/panel/main/main.tsx +++ b/app/web/src/nova/ed/panel/main/main.tsx @@ -1,16 +1,11 @@ -import { ReactNode, useEffect } from "react"; -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 { IMeta } from "../../../view/logic/meta/types"; +import { useGlobal } from "web-utils"; +import { Vi } from "../../../vi/vi"; +import { EDGlobal } from "../../logic/ed-global"; export const EdMain = () => { - return
; - // const p = useGlobal(EDGlobal, "EDITOR"); + const p = useGlobal(EDGlobal, "EDITOR"); + return ; + // const local = useLocal({ // el: null as ReactNode, // }); diff --git a/app/web/src/nova/vi/render/comp.tsx b/app/web/src/nova/vi/render/comp.tsx index 0f897e2e..e70758b1 100644 --- a/app/web/src/nova/vi/render/comp.tsx +++ b/app/web/src/nova/vi/render/comp.tsx @@ -1,3 +1,9 @@ import { IMeta } from "../../ed/logic/ed-global"; +import { ViContext } from "./parts"; -export const viEvalComp = (meta: IMeta) => {}; +export const viEvalProps = async (ctx: ViContext, meta: IMeta) => { + if (meta.item.component?.props) { + for (const [k, v] of Object.entries(meta.item.component.props)) { + } + } +}; diff --git a/app/web/src/nova/vi/render/parts.tsx b/app/web/src/nova/vi/render/parts.tsx new file mode 100644 index 00000000..c571f855 --- /dev/null +++ b/app/web/src/nova/vi/render/parts.tsx @@ -0,0 +1,39 @@ +import { produceCSS } from "../../../utils/css/gen"; +import { IContent } from "../../../utils/types/general"; +import { IMeta } from "../../ed/logic/ed-global"; + +export type ViContext = { + meta: Record; + tick: number; +}; +export type ViParts = { + mode: "mobile" | "desktop"; + hover?: boolean; + active?: boolean; +}; + +export const viParts = (meta: IMeta, arg?: ViParts) => { + const item = meta.item; + const content = meta.item as unknown as IContent; + + const props: React.DetailedHTMLProps< + React.HTMLAttributes, + HTMLDivElement + > = {}; + + let shouldRenderChild = true; + if (content.type === "text") { + props.dangerouslySetInnerHTML = { __html: item.html || "" }; + shouldRenderChild = false; + } + + return { + className: produceCSS(item, { + mode: arg?.mode || "desktop", + hover: arg?.hover, + active: arg?.active, + }), + shouldRenderChild, + props, + }; +}; diff --git a/app/web/src/nova/vi/render/render.tsx b/app/web/src/nova/vi/render/render.tsx index 30af683f..29935496 100644 --- a/app/web/src/nova/vi/render/render.tsx +++ b/app/web/src/nova/vi/render/render.tsx @@ -1,6 +1,35 @@ -import { FC } from "react"; +import { FC, ReactNode } from "react"; import { IMeta } from "../../ed/logic/ed-global"; +import { ViContext, viParts } from "./parts"; +import { ViScript } from "./script"; -export const ViRender: FC<{ meta: IMeta }> = () => { - return
; +export const ViRender: FC<{ + ctx: ViContext; + meta: IMeta; + children?: ReactNode; +}> = ({ meta, children, ctx }) => { + if (!meta) return null; + + if (meta.item.adv?.js || meta.item.component?.id) { + return ; + } + + const parts = viParts(meta); + let renderChild = undefined; + + if (parts.shouldRenderChild) { + renderChild = children + ? children + : meta.item.childs?.map((item) => { + if (!item) return null; + const { id } = item; + return ; + }); + } + + return ( +
+ {renderChild} +
+ ); }; diff --git a/app/web/src/nova/vi/render/script.tsx b/app/web/src/nova/vi/render/script.tsx index 56800eeb..b82ef09b 100644 --- a/app/web/src/nova/vi/render/script.tsx +++ b/app/web/src/nova/vi/render/script.tsx @@ -1,6 +1,29 @@ import { FC } from "react"; import { IMeta } from "../../ed/logic/ed-global"; +import { ViContext, viParts } from "./parts"; +import { ViRender } from "./render"; -export const ViScript: FC<{ meta: IMeta }> = () => { - return
; +export const ViScript: FC<{ ctx: ViContext; meta: IMeta }> = ({ + ctx, + meta, +}) => { + const childs = meta.item.childs; + const parts = viParts(meta); + + let renderChild = undefined; + if (parts.shouldRenderChild) { + renderChild = + Array.isArray(childs) && + childs.map(({ id }) => { + return ; + }); + } + + return ( +
+ {renderChild} +
+ ); }; + +export const viEvalScript = async (ctx: ViContext, meta: IMeta) => {}; diff --git a/app/web/src/nova/vi/root.tsx b/app/web/src/nova/vi/root.tsx new file mode 100644 index 00000000..f53a746d --- /dev/null +++ b/app/web/src/nova/vi/root.tsx @@ -0,0 +1,26 @@ +import { FC } from "react"; +import { ViContext } from "./render/parts"; +import { ViRender } from "./render/render"; +import { useLocal } from "web-utils"; + +export const ViRoot: FC<{ + ctx: ViContext; + entry: string[]; +}> = ({ ctx, entry }) => { + const local = useLocal({ tick: Date.now() }); + ctx.tick = local.tick; + + return ( +
+ {entry.map((id) => { + const meta = ctx.meta[id]; + if (meta) { + if (Element) { + return ; + } + } + return null; + })} +
+ ); +}; diff --git a/app/web/src/nova/vi/utils/error-box.tsx b/app/web/src/nova/vi/utils/error-box.tsx new file mode 100644 index 00000000..41721f02 --- /dev/null +++ b/app/web/src/nova/vi/utils/error-box.tsx @@ -0,0 +1,56 @@ +import { useErrorBoundary, withErrorBoundary } from "react-use-error-boundary"; +import { useLocal } from "web-utils"; +import { IMeta } from "../../ed/logic/ed-global"; + +export const ErrorBox = withErrorBoundary( + ({ + children, + meta, + id, + silent, + }: { + children: any; + meta?: IMeta; + id?: string; + silent?: boolean; + }) => { + const local = useLocal({ retrying: false }); + const [error, resetError] = useErrorBoundary((error, errorInfo) => { + if (silent !== true) console.warn(error); + }); + + let _meta = meta; + + if (error) { + return ( +
+
+ ERROR {_meta?.item.name ? "[" + _meta.item.name + "]:" : ""} +
+

+ {!local.retrying ? <>{(error as any).message} : <>Retrying...} +

+
+ +
+
+ ); + } + + return children; + } +); diff --git a/app/web/src/nova/vi/vi.tsx b/app/web/src/nova/vi/vi.tsx new file mode 100644 index 00000000..02364526 --- /dev/null +++ b/app/web/src/nova/vi/vi.tsx @@ -0,0 +1,13 @@ +import { Suspense } from "react"; +import { ViRoot } from "./root"; +import { ErrorBox } from "./utils/error-box"; + +export const Vi: typeof ViRoot = (props) => { + return ( + + + + + + ); +}; diff --git a/app/web/src/nova/view/logic/meta/types.ts b/app/web/src/nova/view/logic/meta/types.ts index 1128e4c6..901b02f3 100644 --- a/app/web/src/nova/view/logic/meta/types.ts +++ b/app/web/src/nova/view/logic/meta/types.ts @@ -1,6 +1,8 @@ -import { FC } from "react"; +import { FC, ReactNode } from "react"; import { IContent, MContent } from "../../../../utils/types/general"; import { IItem, MItem } from "../../../../utils/types/item"; +import { ViContext } from "../../../vi/render/parts"; +import { ViRender } from "../../../vi/render/render"; export type GenMetaP = { meta: Record; @@ -59,7 +61,6 @@ export type IMeta = { name: string; is_root: boolean; }; - fc?: FC<{ meta: IMeta }>; scope: { val?: any; def?: {