UNPKG

ovsjs

Version:

OVS Runtime - A declarative UI syntax similar to Flutter and SwiftUI

182 lines (179 loc) 5.27 kB
import { defineComponent, h, isReactive, isRef, markRaw, reactive, unref } from "vue"; //#region src/core.ts function ensureReactiveProps(obj) { return isReactive(obj) ? obj : reactive(obj); } function isDefineComponent(value) { if (!value || typeof value !== "object") return false; const v = value; return "render" in v || "setup" in v || v.__isOvsComponent === true; } function mapChildrenToVNodes(children) { if (children == null) return void 0; if (isRef(children)) return mapChildrenToVNodes(unref(children)); if (Array.isArray(children)) return children.map(mapChildrenToVNodes); if (isDefineComponent(children)) return h(children); return children; } /** * 定义 OVS 组件 */ function defineOvsComponent(factory) { const component = defineComponent((props) => { const result = factory(props); if (isDefineComponent(result)) return () => h(result); if (typeof result === "function") return result; return () => result; }); component.__isOvsComponent = true; return markRaw(component); } /** * 创建组件 VNode */ function createComponentVNode(componentFn, props = {}, children = null) { const component = defineComponent((componentProps) => { const state = reactive({ type: componentFn, props: { ...ensureReactiveProps(props), ...componentProps }, children }); return () => { if (typeof state.type === "function") return h(state.type(state)); return h(state.type, state.props, mapChildrenToVNodes(state.children)); }; }); component.__isOvsComponent = true; return markRaw(component); } /** * 创建元素 VNode */ function createElementVNode(type, props = {}, children = null) { const component = defineComponent((componentProps) => { const state = reactive({ type, props: { ...ensureReactiveProps(props), ...componentProps }, children }); return () => h(state.type, state.props, mapChildrenToVNodes(state.children)); }); component.__isOvsComponent = true; return markRaw(component); } //#endregion //#region src/elements.ts /** * HTML 元素命名空间 * * 使用 $OvsHtmlTag.div() 避免与用户变量冲突 */ function createElement(tag) { return (props, children) => createElementVNode(tag, props, children); } /** * HTML 标签命名空间 * 使用方式: $OvsHtmlTag.div({ class: 'x' }, [...]) */ const $OvsHtmlTag = { html: createElement("html"), head: createElement("head"), body: createElement("body"), title: createElement("title"), meta: createElement("meta"), link: createElement("link"), style: createElement("style"), script: createElement("script"), div: createElement("div"), span: createElement("span"), p: createElement("p"), section: createElement("section"), article: createElement("article"), aside: createElement("aside"), header: createElement("header"), footer: createElement("footer"), nav: createElement("nav"), main: createElement("main"), h1: createElement("h1"), h2: createElement("h2"), h3: createElement("h3"), h4: createElement("h4"), h5: createElement("h5"), h6: createElement("h6"), strong: createElement("strong"), em: createElement("em"), b: createElement("b"), i: createElement("i"), u: createElement("u"), small: createElement("small"), code: createElement("code"), pre: createElement("pre"), blockquote: createElement("blockquote"), br: createElement("br"), hr: createElement("hr"), ul: createElement("ul"), ol: createElement("ol"), li: createElement("li"), dl: createElement("dl"), dt: createElement("dt"), dd: createElement("dd"), table: createElement("table"), thead: createElement("thead"), tbody: createElement("tbody"), tfoot: createElement("tfoot"), tr: createElement("tr"), th: createElement("th"), td: createElement("td"), caption: createElement("caption"), colgroup: createElement("colgroup"), col: createElement("col"), form: createElement("form"), input: createElement("input"), textarea: createElement("textarea"), button: createElement("button"), select: createElement("select"), option: createElement("option"), optgroup: createElement("optgroup"), label: createElement("label"), fieldset: createElement("fieldset"), legend: createElement("legend"), img: createElement("img"), video: createElement("video"), audio: createElement("audio"), source: createElement("source"), track: createElement("track"), canvas: createElement("canvas"), svg: createElement("svg"), a: createElement("a"), iframe: createElement("iframe"), object: createElement("object"), embed: createElement("embed"), details: createElement("details"), summary: createElement("summary"), dialog: createElement("dialog"), progress: createElement("progress"), meter: createElement("meter"), output: createElement("output"), mark: createElement("mark"), time: createElement("time"), address: createElement("address"), figure: createElement("figure"), figcaption: createElement("figcaption"), cite: createElement("cite"), q: createElement("q"), abbr: createElement("abbr"), dfn: createElement("dfn"), kbd: createElement("kbd"), samp: createElement("samp"), var: createElement("var"), sup: createElement("sup"), sub: createElement("sub") }; //#endregion export { $OvsHtmlTag, createComponentVNode, createElementVNode, defineOvsComponent, mapChildrenToVNodes };