jmx-runtime 0.0.14 → 0.0.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/base.ts ADDED
@@ -0,0 +1,25 @@
1
+ export function rebind(o: Record<string, any>) {
2
+ Object.entries(Object.getOwnPropertyDescriptors(Object.getPrototypeOf(o)))
3
+ .filter(([name, p]) => name != 'constructor' && p.value instanceof Function)
4
+ .forEach(([name]) => o[name] = o[name].bind(o))
5
+ return o
6
+ }
7
+
8
+ export function mount(o: Record<string, any>) { Object.assign(globalThis, o) }
9
+
10
+ export const loggedmethodsex = <T extends Record<string, any>>(o: T, logger: (name: string, args: any[], result: any) => void) => new Proxy(o, {
11
+ get(target, name: string, receiver) {
12
+ if (typeof target[name] === "function") {
13
+ return function (this: T, ...args: any[]) {
14
+
15
+ logger(name, args, undefined)
16
+ let r = target[name].apply(this, args)
17
+ return r
18
+ }
19
+ }
20
+ return Reflect.get(target, name, receiver)
21
+ },
22
+ })
23
+
24
+ export const loggedmethods = <T extends Record<string, any>>(o: T ): T => loggedmethodsex(o, (name, args, result) => console.log("%c" + name, "background:#585059;color:white;padding:2px;font-weight:bold", args))
25
+ export const loggedmethodscolored = <T extends Record<string, any>>(bgcolor: string, o: T ): T => loggedmethodsex(o, (name, args, result) => console.log("%c" + name, `background:${bgcolor};color:white;padding:2px;font-weight:bold`, args))
package/dist/jmx.js CHANGED
@@ -54,7 +54,7 @@ function sync(p, i, h) {
54
54
  const props = evaluate(h.p);
55
55
  if (iselement(h)) {
56
56
  let n;
57
- if (c?.tagName != h.tag) {
57
+ if (c?.tagName.toLowerCase() != h.tag.toLowerCase()) {
58
58
  n = createElement(h.tag);
59
59
  c ? c.replaceWith(n) : p.appendChild(n);
60
60
  setprops(n, props);
package/dist/jmx.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"jmx.js","sourceRoot":"./","sources":["jmx.ts"],"names":[],"mappings":"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","sourcesContent":["import { rebind } from './base'\r\nimport { Expr, FComponent, H, HComp, HCompClass, HElement, HFragment, IClassComponent, Props } from './h'\r\n\r\n// config\r\nexport function createElement(tag: string) {\r\n let ns = window.jmx?.getnamespace?.(tag)\r\n return ns ? document.createElementNS(ns, tag) : document.createElement(tag)\r\n}\r\n\r\nconst enum NodeType { // vaporizes (but for that must be in this file, otherwise not)\r\n TextNode = 3,\r\n}\r\n\r\nlet evaluate = <T>(expr: Expr<T>): T => (expr instanceof Function ? expr() : expr)\r\nlet removeexcesschildren = (n: Element, i: number) => {\r\n let c: ChildNode\r\n while ((c = n.childNodes[i])) {\r\n c.remove()\r\n }\r\n}\r\nlet iswebcomponent = (h: HElement) => (h.tag as string).includes('-')\r\nlet isclasscomponent = (h: HComp): h is HCompClass => (h.tag as any)?.prototype?.view\r\nlet iselement = (h: any): h is HElement => typeof h.tag == 'string'\r\nlet isfragment = (h: any): h is HFragment => {\r\n return h.tag == undefined && h.cn != undefined\r\n}\r\nlet isobject = (o: any): o is object => typeof o === 'object'\r\n\r\nlet isproperty = (name: string, value: any) =>\r\n ['value', 'checked', 'disabled', 'className', 'style', 'href', 'src', 'selected', 'readOnly', 'tabIndex'].includes(\r\n name\r\n ) ||\r\n value instanceof Object ||\r\n value instanceof Function\r\n\r\nlet setprops = (e: Element, newprops: Props = {}) => {\r\n let oldprops = evaluate(e.h?.p) ?? {}\r\n for (let p in oldprops)\r\n !(p in newprops) && isproperty(p, oldprops[p]) ? ((e as any)[p] = null) : e.removeAttribute(p)\r\n for (let p in newprops) isproperty(p, newprops[p]) ? ((e as any)[p] = newprops[p]) : e.setAttribute(p, newprops[p])\r\n}\r\n\r\n/** syncs at position i of p. returns the number of the element past the last added element.\r\n * if no element was added (eg when h=null) then it returns i\r\n * if a fragment with 5 nodes was added, it returns i + 5\r\n * when a single element or component is added, it is i+1 since they always create exactly 1 node\r\n */\r\nfunction sync(p: Element, i: number, h: Expr<H | undefined>): number {\r\n // console.log('%csync', \"background:orange\", p.tagName, i, h, 'html = ' + document.body.outerHTML)\r\n\r\n h = evaluate(h)\r\n if (h === null || h === undefined) return i // skip this element. not that !!h would forbid to render the number 0 or the boolean value false\r\n\r\n let c = p.childNodes[i] // is often null, eg during fresh creation\r\n\r\n function synctextnode(text: string) {\r\n if (c && c.nodeType == NodeType.TextNode) {\r\n if (c.textContent != text) c.textContent = text // firefox updates even equal text, loosing an existing text selection\r\n } else {\r\n let tn = document.createTextNode(text)\r\n c ? c.replaceWith(tn) : p.appendChild(tn)\r\n }\r\n }\r\n\r\n if (isobject(h)) {\r\n // element nodes\r\n\r\n /** synchronizes children starting at the i-th element. returns the index of the last child synchronized */\r\n function syncchildren(p: Element, h: HElement | HComp | HFragment, i: number): number {\r\n evaluate(h.cn)\r\n ?.flat()\r\n .forEach(hc => (i = sync(p, i, hc)))\r\n return i\r\n }\r\n\r\n if (isfragment(h)) return syncchildren(p, h, i)\r\n\r\n const props = evaluate(h.p)\r\n\r\n if (iselement(h)) {\r\n let n: Element\r\n\r\n if ((<Element>c)?.tagName != h.tag) {\r\n n = createElement(h.tag)\r\n c ? c.replaceWith(n) : p.appendChild(n)\r\n setprops(n, props)\r\n props?.mounted?.(n)\r\n } else {\r\n n = c as Element\r\n setprops(n, props)\r\n if (props?.update?.(c, globaluc)) return i + 1\r\n }\r\n\r\n // if only components shall be updateable (advantage: close variables inside component functions are always fresh materialized, avoids surprises), comment this out\r\n n.h = h\r\n\r\n if (!globaluc.patchElementOnly && !iswebcomponent(h as HElement)) {\r\n // tbd: make \"island\" attribute\r\n const j = syncchildren(n, h, 0)\r\n removeexcesschildren(n, j)\r\n }\r\n return i + 1\r\n }\r\n\r\n switch (typeof h.tag) {\r\n case 'function':\r\n let isupdate = c?.h?.tag == h.tag\r\n\r\n let ci: IClassComponent | undefined\r\n\r\n if (isclasscomponent(h)) {\r\n h.i = ci = (c?.h as HCompClass)?.i ?? rebind(new h.tag(props))\r\n ci.props = props\r\n\r\n // if component instance returns truthy for update(), then syncing is susbstituted by the component\r\n if (isupdate && ci.update(globaluc)) return i + 1\r\n }\r\n\r\n // materialize the component\r\n // we run compoents view() and fun code often, we do not compare properties to avoid their computation\r\n // this means that the inner hr (h resolved) is run often\r\n let hr = ci?.view() ?? (h.tag as FComponent)(props, evaluate(h.cn))\r\n\r\n // a component can return undefined or null if it has no elements to show\r\n if (hr === undefined || hr == null) return i\r\n\r\n let j = sync(p, i, hr)\r\n\r\n let cn = p.childNodes[i]!\r\n cn.h = h // attach h onto the materialized component node\r\n // ;(cn as HTMLElement).setAttribute?.('comp', '')\r\n\r\n if (ci) ci.element = cn\r\n if (!isupdate) ci?.mounted?.()\r\n\r\n return j\r\n\r\n case 'object':\r\n return sync(p, i, h.tag) // tbd: type of h is not correct, h.tag == never\r\n }\r\n }\r\n // text nodes\r\n synctextnode(h as string)\r\n return i + 1\r\n}\r\n\r\nlet globaluc: IUpdateContext = {}\r\n\r\nexport function patch(e: Node | null, h: Expr<H>) {\r\n if (!e) return\r\n if (globaluc.replace) (e as HTMLElement).replaceChildren()\r\n const p = e.parentElement as HTMLElement\r\n const i = [].indexOf.call<any, any, any>(p.childNodes, e)\r\n // always called deferred, because removing elements can trigger events and their handlers (like blur)\r\n sync(p, i, h)\r\n}\r\n\r\n// Overload signatures\r\ntype Selector = string | Node | undefined | null\r\ntype Selectors = Selector[]\r\n\r\nexport function updateviewuc(uc: IUpdateContext, ...sels: Selectors): void {\r\n {\r\n globaluc = uc\r\n updateviewinternal(...sels)\r\n }\r\n}\r\nexport function updateview(...sels: Selectors): void {\r\n {\r\n globaluc = {}\r\n updateviewinternal(...sels)\r\n }\r\n}\r\n\r\nfunction updateviewinternal(...sels: Selector[]): void {\r\n if (!sels.length) sels.push('body')\r\n sels.flatMap(s => (typeof s == 'string' ? [...document.querySelectorAll(s)] : s ? [s] : [])).forEach(e => {\r\n if (!e?.h) throw 'jmx: no h exists on the node'\r\n patch(e, e.h)\r\n })\r\n}\r\n"]}
1
+ {"version":3,"file":"jmx.js","sourceRoot":"./","sources":["jmx.ts"],"names":[],"mappings":"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","sourcesContent":["import { rebind } from './base'\r\nimport { Expr, FComponent, H, HComp, HCompClass, HElement, HFragment, IClassComponent, Props } from './h'\r\n\r\n// config\r\nexport function createElement(tag: string) {\r\n let ns = window.jmx?.getnamespace?.(tag)\r\n return ns ? document.createElementNS(ns, tag) : document.createElement(tag)\r\n}\r\n\r\nconst enum NodeType { // vaporizes (but for that must be in this file, otherwise not)\r\n TextNode = 3,\r\n}\r\n\r\nlet evaluate = <T>(expr: Expr<T>): T => (expr instanceof Function ? expr() : expr)\r\nlet removeexcesschildren = (n: Element, i: number) => {\r\n let c: ChildNode\r\n while ((c = n.childNodes[i])) {\r\n c.remove()\r\n }\r\n}\r\nlet iswebcomponent = (h: HElement) => (h.tag as string).includes('-')\r\nlet isclasscomponent = (h: HComp): h is HCompClass => (h.tag as any)?.prototype?.view\r\nlet iselement = (h: any): h is HElement => typeof h.tag == 'string'\r\nlet isfragment = (h: any): h is HFragment => {\r\n return h.tag == undefined && h.cn != undefined\r\n}\r\nlet isobject = (o: any): o is object => typeof o === 'object'\r\n\r\nlet isproperty = (name: string, value: any) =>\r\n ['value', 'checked', 'disabled', 'className', 'style', 'href', 'src', 'selected', 'readOnly', 'tabIndex'].includes(\r\n name\r\n ) ||\r\n value instanceof Object ||\r\n value instanceof Function\r\n\r\nlet setprops = (e: Element, newprops: Props = {}) => {\r\n let oldprops = evaluate(e.h?.p) ?? {}\r\n for (let p in oldprops)\r\n !(p in newprops) && isproperty(p, oldprops[p]) ? ((e as any)[p] = null) : e.removeAttribute(p)\r\n for (let p in newprops) isproperty(p, newprops[p]) ? ((e as any)[p] = newprops[p]) : e.setAttribute(p, newprops[p])\r\n}\r\n\r\n/** syncs at position i of p. returns the number of the element past the last added element.\r\n * if no element was added (eg when h=null) then it returns i\r\n * if a fragment with 5 nodes was added, it returns i + 5\r\n * when a single element or component is added, it is i+1 since they always create exactly 1 node\r\n */\r\nfunction sync(p: Element, i: number, h: Expr<H | undefined>): number {\r\n // console.log('%csync', \"background:orange\", p.tagName, i, h, 'html = ' + document.body.outerHTML)\r\n\r\n h = evaluate(h)\r\n if (h === null || h === undefined) return i // skip this element. not that !!h would forbid to render the number 0 or the boolean value false\r\n\r\n let c = p.childNodes[i] // is often null, eg during fresh creation\r\n\r\n function synctextnode(text: string) {\r\n if (c && c.nodeType == NodeType.TextNode) {\r\n if (c.textContent != text) c.textContent = text // firefox updates even equal text, loosing an existing text selection\r\n } else {\r\n let tn = document.createTextNode(text)\r\n c ? c.replaceWith(tn) : p.appendChild(tn)\r\n }\r\n }\r\n\r\n if (isobject(h)) {\r\n // element nodes\r\n\r\n /** synchronizes children starting at the i-th element. returns the index of the last child synchronized */\r\n function syncchildren(p: Element, h: HElement | HComp | HFragment, i: number): number {\r\n evaluate(h.cn)\r\n ?.flat()\r\n .forEach(hc => (i = sync(p, i, hc)))\r\n return i\r\n }\r\n\r\n if (isfragment(h)) return syncchildren(p, h, i)\r\n\r\n const props = evaluate(h.p)\r\n\r\n if (iselement(h)) {\r\n let n: Element\r\n\r\n if ((<Element>c)?.tagName.toLowerCase() != h.tag.toLowerCase()) {\r\n n = createElement(h.tag)\r\n c ? c.replaceWith(n) : p.appendChild(n)\r\n setprops(n, props)\r\n props?.mounted?.(n)\r\n } else {\r\n n = c as Element\r\n setprops(n, props)\r\n if (props?.update?.(c, globaluc)) return i + 1\r\n }\r\n\r\n // if only components shall be updateable (advantage: close variables inside component functions are always fresh materialized, avoids surprises), comment this out\r\n n.h = h\r\n\r\n if (!globaluc.patchElementOnly && !iswebcomponent(h as HElement)) {\r\n // tbd: make \"island\" attribute\r\n const j = syncchildren(n, h, 0)\r\n removeexcesschildren(n, j)\r\n }\r\n return i + 1\r\n }\r\n\r\n switch (typeof h.tag) {\r\n case 'function':\r\n let isupdate = c?.h?.tag == h.tag\r\n\r\n let ci: IClassComponent | undefined\r\n\r\n if (isclasscomponent(h)) {\r\n h.i = ci = (c?.h as HCompClass)?.i ?? rebind(new h.tag(props))\r\n ci.props = props\r\n\r\n // if component instance returns truthy for update(), then syncing is susbstituted by the component\r\n if (isupdate && ci.update(globaluc)) return i + 1\r\n }\r\n\r\n // materialize the component\r\n // we run compoents view() and fun code often, we do not compare properties to avoid their computation\r\n // this means that the inner hr (h resolved) is run often\r\n let hr = ci?.view() ?? (h.tag as FComponent)(props, evaluate(h.cn))\r\n\r\n // a component can return undefined or null if it has no elements to show\r\n if (hr === undefined || hr == null) return i\r\n\r\n let j = sync(p, i, hr)\r\n\r\n let cn = p.childNodes[i]!\r\n cn.h = h // attach h onto the materialized component node\r\n // ;(cn as HTMLElement).setAttribute?.('comp', '')\r\n\r\n if (ci) ci.element = cn\r\n if (!isupdate) ci?.mounted?.()\r\n\r\n return j\r\n\r\n case 'object':\r\n return sync(p, i, h.tag) // tbd: type of h is not correct, h.tag == never\r\n }\r\n }\r\n // text nodes\r\n synctextnode(h as string)\r\n return i + 1\r\n}\r\n\r\nlet globaluc: IUpdateContext = {}\r\n\r\nexport function patch(e: Node | null, h: Expr<H>) {\r\n if (!e) return\r\n if (globaluc.replace) (e as HTMLElement).replaceChildren()\r\n const p = e.parentElement as HTMLElement\r\n const i = [].indexOf.call<any, any, any>(p.childNodes, e)\r\n // always called deferred, because removing elements can trigger events and their handlers (like blur)\r\n sync(p, i, h)\r\n}\r\n\r\n// Overload signatures\r\ntype Selector = string | Node | undefined | null\r\ntype Selectors = Selector[]\r\n\r\nexport function updateviewuc(uc: IUpdateContext, ...sels: Selectors): void {\r\n {\r\n globaluc = uc\r\n updateviewinternal(...sels)\r\n }\r\n}\r\nexport function updateview(...sels: Selectors): void {\r\n {\r\n globaluc = {}\r\n updateviewinternal(...sels)\r\n }\r\n}\r\n\r\nfunction updateviewinternal(...sels: Selector[]): void {\r\n if (!sels.length) sels.push('body')\r\n sels.flatMap(s => (typeof s == 'string' ? [...document.querySelectorAll(s)] : s ? [s] : [])).forEach(e => {\r\n if (!e?.h) throw 'jmx: no h exists on the node'\r\n patch(e, e.h)\r\n })\r\n}\r\n"]}
package/h.ts ADDED
@@ -0,0 +1,88 @@
1
+ // jmx internal types - hopst
2
+ // the following types describe the js expression we get from tsx after conversion be our jmx plugin
3
+ // they can be useful for users as well, components might return them.
4
+
5
+ type Func<T> = () => T
6
+ export type Expr<T> = T | Func<T>
7
+
8
+ export type Props = Record<string, any>
9
+
10
+ export type FComponent = (props: Props | undefined, children?: ChildrenH) => HElement // show an example for usage of children
11
+
12
+ export type FComponentT<P> = (pcn: P, cn?: Children) => H | void
13
+
14
+ export interface IClassComponent {
15
+ element: Node
16
+ props?: Record<string, any>
17
+ view(): H
18
+ update(uc: IUpdateContext): boolean | void
19
+ mounted?(): void
20
+ }
21
+
22
+ interface CComponent {
23
+ new (props: any): IClassComponent // while a real component expresses its interface via props pass to the ctor, internally we assign props after construction with new()
24
+ }
25
+
26
+ export type ChildrenH = (H | undefined)[]
27
+ export type Children = Expr<ChildrenH>
28
+
29
+ type HText =
30
+ | string // text node
31
+ | number // text node
32
+ | boolean // do not allow boolean, that
33
+
34
+ export type HFragment = {
35
+ cn: Children
36
+ }
37
+
38
+ export type HElement = {
39
+ tag: string
40
+ p?: Expr<Props>
41
+ cn: Children
42
+ i?: any
43
+ }
44
+
45
+ type HCompFun = {
46
+ tag: FComponent
47
+ p?: Expr<Props>
48
+ cn?: Children
49
+ }
50
+
51
+ export type HCompClass = {
52
+ tag: CComponent
53
+ p?: Expr<Props>
54
+ cn: Children
55
+ i: IClassComponent
56
+ }
57
+
58
+ export type HComp = HCompFun | HCompClass
59
+
60
+ export type H = // a hyperscript atom that describes a ...
61
+
62
+ | HText
63
+ | HElement // a tag, like p, div with attributes and children
64
+ | HComp // a dynamic component computing any other HNode
65
+ | HFragment
66
+
67
+ declare global {
68
+ interface Node {
69
+ h?: HElement | HCompFun | HCompClass
70
+ }
71
+ export interface IUpdateContext {
72
+ patchElementOnly?: boolean
73
+ replace?: boolean
74
+ }
75
+
76
+ export interface Window {
77
+ jmx?: {
78
+ getnamespace: (tag: string) => string | undefined
79
+ }
80
+ }
81
+ }
82
+
83
+ export function jsx(): HElement {
84
+ throw 'jmx plugin not configured'
85
+ } // dumy function for app code - jmx-plugin removes calls to this function, minifyer then removes it
86
+ export function jsxf(): HElement {
87
+ throw 'jmx plugin not configured'
88
+ } // dumy function for app code - jmx-plugin removes calls to this function, minifyer then removes it
package/index.ts ADDED
@@ -0,0 +1,5 @@
1
+ export * from './jmx';
2
+ export * from './lib';
3
+ export * from './base';
4
+ export * from './h';
5
+ export * from './jsx';
package/jmx.ts ADDED
@@ -0,0 +1,181 @@
1
+ import { rebind } from './base'
2
+ import { Expr, FComponent, H, HComp, HCompClass, HElement, HFragment, IClassComponent, Props } from './h'
3
+
4
+ // config
5
+ export function createElement(tag: string) {
6
+ let ns = window.jmx?.getnamespace?.(tag)
7
+ return ns ? document.createElementNS(ns, tag) : document.createElement(tag)
8
+ }
9
+
10
+ const enum NodeType { // vaporizes (but for that must be in this file, otherwise not)
11
+ TextNode = 3,
12
+ }
13
+
14
+ let evaluate = <T>(expr: Expr<T>): T => (expr instanceof Function ? expr() : expr)
15
+ let removeexcesschildren = (n: Element, i: number) => {
16
+ let c: ChildNode
17
+ while ((c = n.childNodes[i])) {
18
+ c.remove()
19
+ }
20
+ }
21
+ let iswebcomponent = (h: HElement) => (h.tag as string).includes('-')
22
+ let isclasscomponent = (h: HComp): h is HCompClass => (h.tag as any)?.prototype?.view
23
+ let iselement = (h: any): h is HElement => typeof h.tag == 'string'
24
+ let isfragment = (h: any): h is HFragment => {
25
+ return h.tag == undefined && h.cn != undefined
26
+ }
27
+ let isobject = (o: any): o is object => typeof o === 'object'
28
+
29
+ let isproperty = (name: string, value: any) =>
30
+ ['value', 'checked', 'disabled', 'className', 'style', 'href', 'src', 'selected', 'readOnly', 'tabIndex'].includes(
31
+ name
32
+ ) ||
33
+ value instanceof Object ||
34
+ value instanceof Function
35
+
36
+ let setprops = (e: Element, newprops: Props = {}) => {
37
+ let oldprops = evaluate(e.h?.p) ?? {}
38
+ for (let p in oldprops)
39
+ !(p in newprops) && isproperty(p, oldprops[p]) ? ((e as any)[p] = null) : e.removeAttribute(p)
40
+ for (let p in newprops) isproperty(p, newprops[p]) ? ((e as any)[p] = newprops[p]) : e.setAttribute(p, newprops[p])
41
+ }
42
+
43
+ /** syncs at position i of p. returns the number of the element past the last added element.
44
+ * if no element was added (eg when h=null) then it returns i
45
+ * if a fragment with 5 nodes was added, it returns i + 5
46
+ * when a single element or component is added, it is i+1 since they always create exactly 1 node
47
+ */
48
+ function sync(p: Element, i: number, h: Expr<H | undefined>): number {
49
+ // console.log('%csync', "background:orange", p.tagName, i, h, 'html = ' + document.body.outerHTML)
50
+
51
+ h = evaluate(h)
52
+ if (h === null || h === undefined) return i // skip this element. not that !!h would forbid to render the number 0 or the boolean value false
53
+
54
+ let c = p.childNodes[i] // is often null, eg during fresh creation
55
+
56
+ function synctextnode(text: string) {
57
+ if (c && c.nodeType == NodeType.TextNode) {
58
+ if (c.textContent != text) c.textContent = text // firefox updates even equal text, loosing an existing text selection
59
+ } else {
60
+ let tn = document.createTextNode(text)
61
+ c ? c.replaceWith(tn) : p.appendChild(tn)
62
+ }
63
+ }
64
+
65
+ if (isobject(h)) {
66
+ // element nodes
67
+
68
+ /** synchronizes children starting at the i-th element. returns the index of the last child synchronized */
69
+ function syncchildren(p: Element, h: HElement | HComp | HFragment, i: number): number {
70
+ evaluate(h.cn)
71
+ ?.flat()
72
+ .forEach(hc => (i = sync(p, i, hc)))
73
+ return i
74
+ }
75
+
76
+ if (isfragment(h)) return syncchildren(p, h, i)
77
+
78
+ const props = evaluate(h.p)
79
+
80
+ if (iselement(h)) {
81
+ let n: Element
82
+
83
+ if ((<Element>c)?.tagName.toLowerCase() != h.tag.toLowerCase()) {
84
+ n = createElement(h.tag)
85
+ c ? c.replaceWith(n) : p.appendChild(n)
86
+ setprops(n, props)
87
+ props?.mounted?.(n)
88
+ } else {
89
+ n = c as Element
90
+ setprops(n, props)
91
+ if (props?.update?.(c, globaluc)) return i + 1
92
+ }
93
+
94
+ // if only components shall be updateable (advantage: close variables inside component functions are always fresh materialized, avoids surprises), comment this out
95
+ n.h = h
96
+
97
+ if (!globaluc.patchElementOnly && !iswebcomponent(h as HElement)) {
98
+ // tbd: make "island" attribute
99
+ const j = syncchildren(n, h, 0)
100
+ removeexcesschildren(n, j)
101
+ }
102
+ return i + 1
103
+ }
104
+
105
+ switch (typeof h.tag) {
106
+ case 'function':
107
+ let isupdate = c?.h?.tag == h.tag
108
+
109
+ let ci: IClassComponent | undefined
110
+
111
+ if (isclasscomponent(h)) {
112
+ h.i = ci = (c?.h as HCompClass)?.i ?? rebind(new h.tag(props))
113
+ ci.props = props
114
+
115
+ // if component instance returns truthy for update(), then syncing is susbstituted by the component
116
+ if (isupdate && ci.update(globaluc)) return i + 1
117
+ }
118
+
119
+ // materialize the component
120
+ // we run compoents view() and fun code often, we do not compare properties to avoid their computation
121
+ // this means that the inner hr (h resolved) is run often
122
+ let hr = ci?.view() ?? (h.tag as FComponent)(props, evaluate(h.cn))
123
+
124
+ // a component can return undefined or null if it has no elements to show
125
+ if (hr === undefined || hr == null) return i
126
+
127
+ let j = sync(p, i, hr)
128
+
129
+ let cn = p.childNodes[i]!
130
+ cn.h = h // attach h onto the materialized component node
131
+ // ;(cn as HTMLElement).setAttribute?.('comp', '')
132
+
133
+ if (ci) ci.element = cn
134
+ if (!isupdate) ci?.mounted?.()
135
+
136
+ return j
137
+
138
+ case 'object':
139
+ return sync(p, i, h.tag) // tbd: type of h is not correct, h.tag == never
140
+ }
141
+ }
142
+ // text nodes
143
+ synctextnode(h as string)
144
+ return i + 1
145
+ }
146
+
147
+ let globaluc: IUpdateContext = {}
148
+
149
+ export function patch(e: Node | null, h: Expr<H>) {
150
+ if (!e) return
151
+ if (globaluc.replace) (e as HTMLElement).replaceChildren()
152
+ const p = e.parentElement as HTMLElement
153
+ const i = [].indexOf.call<any, any, any>(p.childNodes, e)
154
+ // always called deferred, because removing elements can trigger events and their handlers (like blur)
155
+ sync(p, i, h)
156
+ }
157
+
158
+ // Overload signatures
159
+ type Selector = string | Node | undefined | null
160
+ type Selectors = Selector[]
161
+
162
+ export function updateviewuc(uc: IUpdateContext, ...sels: Selectors): void {
163
+ {
164
+ globaluc = uc
165
+ updateviewinternal(...sels)
166
+ }
167
+ }
168
+ export function updateview(...sels: Selectors): void {
169
+ {
170
+ globaluc = {}
171
+ updateviewinternal(...sels)
172
+ }
173
+ }
174
+
175
+ function updateviewinternal(...sels: Selector[]): void {
176
+ if (!sels.length) sels.push('body')
177
+ sels.flatMap(s => (typeof s == 'string' ? [...document.querySelectorAll(s)] : s ? [s] : [])).forEach(e => {
178
+ if (!e?.h) throw 'jmx: no h exists on the node'
179
+ patch(e, e.h)
180
+ })
181
+ }
package/jsx.ts ADDED
@@ -0,0 +1,748 @@
1
+ /* eslint-disable @typescript-eslint/no-empty-interface */
2
+ /* eslint-disable @typescript-eslint/ban-types */
3
+ // This code is based on react definition in DefinitelyTyped published under the MIT license.
4
+ // Repository: https://github.com/DefinitelyTyped/DefinitelyTyped
5
+ // Path in the repository: types/react/v15/index.d.ts
6
+ //
7
+ // Copyrights of original definition are:
8
+ // Asana <https://asana.com>
9
+ // AssureSign <http://www.assuresign.com>
10
+ // Microsoft <https://microsoft.com>
11
+ // John Reilly <https://github.com/johnnyreilly/>
12
+ // Benoit Benezech <https://github.com/bbenezech>
13
+ // Patricio Zavolinsky <https://github.com/pzavolinsky>
14
+ // Digiguru <https://github.com/digiguru>
15
+ // Eric Anderson <https://github.com/ericanderson>
16
+ // Albert Kurniawan <https://github.com/morcerf>
17
+ // Tanguy Krotoff <https://github.com/tkrotoff>
18
+ // Dovydas Navickas <https://github.com/DovydasNavickas>
19
+ // Stéphane Goetz <https://github.com/onigoetz>
20
+
21
+ declare global {
22
+ namespace JSX {
23
+ interface IntrinsicElements extends IntrinsicElementAttributes {
24
+ // additional attributes for selected elements
25
+ // label: HTMLAttributes & { bunny: number }
26
+ }
27
+ }
28
+ }
29
+
30
+ interface EventHandler<E extends Event> {
31
+ (event: E): void
32
+ }
33
+
34
+ export interface AdditionalElementAttributes {
35
+ mounted?: (n:Node) => void
36
+ update?: (n:Node, uc:IUpdateContext) => void
37
+ }
38
+
39
+ export interface HTMLAttributes extends AdditionalElementAttributes {
40
+ class?: string
41
+ style?: string
42
+ accesskey?: string
43
+ contenteditable?: boolean
44
+ contextmenu?: string
45
+ dir?: string
46
+ disabled?: boolean
47
+ draggable?: boolean
48
+ hidden?: boolean
49
+ id?: string
50
+ lang?: string
51
+ spellcheck?: boolean
52
+ tabindex?: number
53
+ title?: string
54
+ role?: string
55
+
56
+ // clipboard events
57
+ onCopy?: ClipboardEvent
58
+ onCut?: ClipboardEvent
59
+ onPaste?: ClipboardEvent
60
+
61
+ // composition events
62
+ onCompositionend?: CompositionEvent
63
+ onCompositionstart?: CompositionEvent
64
+ onCompositionupdate?: CompositionEvent
65
+
66
+ // drag drop events
67
+ ondrag?: EventHandler<DragEvent>
68
+ ondragend?: EventHandler<DragEvent>
69
+ ondragenter?: EventHandler<DragEvent>
70
+ ondragexit?: EventHandler<DragEvent>
71
+ ondragleave?: EventHandler<DragEvent>
72
+ ondragover?: EventHandler<DragEvent>
73
+ ondragstart?: EventHandler<DragEvent>
74
+ ondrop?: EventHandler<DragEvent>
75
+
76
+ // focus events
77
+ onfocus?: (ev: FocusEvent) => void
78
+ onfocusout?: (ev: FocusEvent) => void
79
+ onblur?: (ev: FocusEvent) => void
80
+
81
+ // form events
82
+ onchange?: EventHandler<Event>
83
+ oninput?: EventHandler<Event>
84
+ onreset?: EventHandler<Event>
85
+ onsubmit?: EventHandler<Event>
86
+ oninvalid?: EventHandler<Event>
87
+
88
+ // image events
89
+ onload?: EventHandler<Event>
90
+ onerror?: EventHandler<Event>
91
+
92
+ // keyboard events
93
+ onkeydown?: EventHandler<KeyboardEvent>
94
+ onkeypress?: EventHandler<KeyboardEvent>
95
+ onkeyup?: EventHandler<KeyboardEvent>
96
+
97
+ // mouse events
98
+ onclick?: EventHandler<MouseEvent>
99
+ oncontextmenu?: EventHandler<MouseEvent>
100
+ ondblclick?: EventHandler<MouseEvent>
101
+ onmousedown?: EventHandler<MouseEvent>
102
+ onmouseenter?: EventHandler<MouseEvent>
103
+ onmouseleave?: EventHandler<MouseEvent>
104
+ onmousemove?: EventHandler<MouseEvent>
105
+ onmouseout?: EventHandler<MouseEvent>
106
+ onmouseover?: EventHandler<MouseEvent>
107
+ onmouseup?: EventHandler<MouseEvent>
108
+
109
+ // media events
110
+ onAbort?: EventHandler<Event>
111
+ onCanplay?: EventHandler<Event>
112
+ onCanplaythrough?: EventHandler<Event>
113
+ onDurationchange?: EventHandler<Event>
114
+ onEmptied?: EventHandler<Event>
115
+ onEncrypted?: EventHandler<Event>
116
+ onEnded?: EventHandler<Event>
117
+ onLoadeddata?: EventHandler<Event>
118
+ onLoadedmetadata?: EventHandler<Event>
119
+ onLoadstart?: EventHandler<Event>
120
+ onPause?: EventHandler<Event>
121
+ onPlay?: EventHandler<Event>
122
+ onPlaying?: EventHandler<Event>
123
+ onProgress?: EventHandler<Event>
124
+ onRatechange?: EventHandler<Event>
125
+ onSeeked?: EventHandler<Event>
126
+ onSeeking?: EventHandler<Event>
127
+ onStalled?: EventHandler<Event>
128
+ onSuspend?: EventHandler<Event>
129
+ onTimeupdate?: EventHandler<Event>
130
+ onVolumechange?: EventHandler<Event>
131
+ onWaiting?: EventHandler<Event>
132
+
133
+ // selection events
134
+ onSelect?: EventHandler<Event>
135
+
136
+ // UI events
137
+ onScroll?: UIEvent
138
+
139
+ // touch events
140
+ onTouchcancel?: TouchEvent
141
+ onTouchend?: TouchEvent
142
+ onTouchmove?: TouchEvent
143
+ onTouchstart?: TouchEvent
144
+
145
+ // wheel events
146
+ onWheel?: WheelEvent
147
+
148
+ // animation events
149
+ onAnimationstart?: AnimationEvent
150
+ onAnimationend?: AnimationEvent
151
+ onAnimationiteration?: AnimationEvent
152
+
153
+ // transition events
154
+ onTransitionend?: TransitionEvent
155
+ onTransitionstart?: TransitionEvent
156
+ }
157
+
158
+ export interface AnchorHTMLAttributes extends HTMLAttributes {
159
+ download?: any
160
+ href?: string
161
+ hreflang?: string
162
+ media?: string
163
+ rel?: string
164
+ target?: string
165
+ }
166
+
167
+ export interface AreaHTMLAttributes extends HTMLAttributes {
168
+ alt?: string
169
+ coord?: string
170
+ download?: any
171
+ href?: string
172
+ hreflang?: string
173
+ media?: string
174
+ rel?: string
175
+ shape?: string
176
+ target?: string
177
+ }
178
+
179
+ export interface AudioHTMLAttributes extends MediaHTMLAttributes { }
180
+
181
+ export interface BaseHTMLAttributes extends HTMLAttributes {
182
+ href?: string
183
+ target?: string
184
+ }
185
+
186
+ export interface BlockquoteHTMLAttributes extends HTMLAttributes {
187
+ cite?: string
188
+ }
189
+
190
+ export interface ButtonHTMLAttributes extends HTMLAttributes {
191
+ autofocus?: boolean
192
+ disabled?: boolean
193
+ form?: string
194
+ formaction?: string
195
+ formenctype?: string
196
+ formmethod?: string
197
+ formnovalidate?: boolean
198
+ formtarget?: string
199
+ name?: string
200
+ type?: string
201
+ value?: string | string[] | number
202
+ }
203
+
204
+ export interface CanvasHTMLAttributes extends HTMLAttributes {
205
+ height?: number | string
206
+ width?: number | string
207
+ }
208
+
209
+ export interface ColHTMLAttributes extends HTMLAttributes {
210
+ span?: number
211
+ }
212
+
213
+ export interface ColgroupHTMLAttributes extends ColHTMLAttributes { }
214
+
215
+ export interface DetailsHTMLAttributes extends HTMLAttributes {
216
+ open?: boolean
217
+ }
218
+
219
+ export interface DelHTMLAttributes extends HTMLAttributes {
220
+ cite?: string
221
+ datetime?: string
222
+ }
223
+
224
+ export interface EmbedHTMLAttributes extends HTMLAttributes {
225
+ height?: number | string
226
+ src?: string
227
+ type?: string
228
+ width?: number | string
229
+ }
230
+
231
+ export interface FieldsetHTMLAttributes extends HTMLAttributes {
232
+ disabled?: boolean
233
+ form?: string
234
+ name?: string
235
+ }
236
+
237
+ export interface FormHTMLAttributes extends HTMLAttributes {
238
+ acceptcharset?: string
239
+ action?: string
240
+ autocomplete?: string
241
+ enctype?: string
242
+ method?: string
243
+ name?: string
244
+ novalidate?: boolean
245
+ target?: string
246
+ }
247
+
248
+ export interface HtmlHTMLAttributes extends HTMLAttributes {
249
+ manifest?: string
250
+ }
251
+
252
+ export interface IframeHTMLAttributes extends HTMLAttributes {
253
+ allowfullscreen?: boolean
254
+ allowtransparency?: boolean
255
+ frameborder?: number | string
256
+ height?: number | string
257
+ marginheight?: number
258
+ marginwidth?: number
259
+ name?: string
260
+ sandbox?: string
261
+ scrolling?: string
262
+ seamless?: boolean
263
+ src?: string
264
+ srcdoc?: string
265
+ width?: number | string
266
+ }
267
+
268
+ export interface ImgHTMLAttributes extends HTMLAttributes {
269
+ alt?: string
270
+ height?: number | string
271
+ sizes?: string
272
+ src?: string
273
+ srcset?: string
274
+ usemap?: string
275
+ width?: number | string
276
+ }
277
+
278
+ export interface InsHTMLAttributes extends HTMLAttributes {
279
+ cite?: string
280
+ datetime?: string
281
+ }
282
+
283
+ export interface InputHTMLAttributes extends HTMLAttributes {
284
+ accept?: string
285
+ alt?: string
286
+ autocomplete?: string
287
+ autofocus?: boolean
288
+ capture?: boolean // https://www.w3.org/tr/html-media-capture/#the-capture-attribute
289
+ checked?: boolean
290
+ crossorigin?: string
291
+ disabled?: boolean
292
+ form?: string
293
+ formaction?: string
294
+ formenctype?: string
295
+ formmethod?: string
296
+ formnovalidate?: boolean
297
+ formtarget?: string
298
+ height?: number | string
299
+ list?: string
300
+ max?: number | string
301
+ maxlength?: number
302
+ min?: number | string
303
+ minlength?: number
304
+ multiple?: boolean
305
+ name?: string
306
+ pattern?: string
307
+ placeholder?: string
308
+ readonly?: boolean
309
+ required?: boolean
310
+ size?: number
311
+ src?: string
312
+ step?: number | string
313
+ type?: string
314
+ value?: string | string[] | number
315
+ width?: number | string
316
+ }
317
+
318
+ export interface KeygenHTMLAttributes extends HTMLAttributes {
319
+ autofocus?: boolean
320
+ challenge?: string
321
+ disabled?: boolean
322
+ form?: string
323
+ keytype?: string
324
+ keyparams?: string
325
+ name?: string
326
+ }
327
+
328
+ export interface LabelHTMLAttributes extends HTMLAttributes {
329
+ form?: string
330
+ for?: string
331
+ }
332
+
333
+ export interface LiHTMLAttributes extends HTMLAttributes {
334
+ value?: string | string[] | number
335
+ }
336
+
337
+ export interface LinkHTMLAttributes extends HTMLAttributes {
338
+ href?: string
339
+ hreflang?: string
340
+ integrity?: string
341
+ media?: string
342
+ rel?: string
343
+ sizes?: string
344
+ type?: string
345
+ }
346
+
347
+ export interface MapHTMLAttributes extends HTMLAttributes {
348
+ name?: string
349
+ }
350
+
351
+ export interface MenuHTMLAttributes extends HTMLAttributes {
352
+ type?: string
353
+ }
354
+
355
+ export interface MediaHTMLAttributes extends HTMLAttributes {
356
+ autoplay?: boolean
357
+ controls?: boolean
358
+ crossorigin?: string
359
+ loop?: boolean
360
+ mediagroup?: string
361
+ muted?: boolean
362
+ preload?: string
363
+ src?: string
364
+ }
365
+
366
+ export interface MetaHTMLAttributes extends HTMLAttributes {
367
+ charset?: string
368
+ content?: string
369
+ httpequiv?: string
370
+ name?: string
371
+ }
372
+
373
+ export interface MeterHTMLAttributes extends HTMLAttributes {
374
+ form?: string
375
+ high?: number
376
+ low?: number
377
+ max?: number | string
378
+ min?: number | string
379
+ optimum?: number
380
+ value?: string | string[] | number
381
+ }
382
+
383
+ export interface QuoteHTMLAttributes extends HTMLAttributes {
384
+ cite?: string
385
+ }
386
+
387
+ export interface ObjectHTMLAttributes extends HTMLAttributes {
388
+ classid?: string
389
+ data?: string
390
+ form?: string
391
+ height?: number | string
392
+ name?: string
393
+ type?: string
394
+ usemap?: string
395
+ width?: number | string
396
+ wmode?: string
397
+ }
398
+
399
+ export interface OlHTMLAttributes extends HTMLAttributes {
400
+ reversed?: boolean
401
+ start?: number
402
+ }
403
+
404
+ export interface OptgroupHTMLAttributes extends HTMLAttributes {
405
+ disabled?: boolean
406
+ label?: string
407
+ }
408
+
409
+ export interface OptionHTMLAttributes extends HTMLAttributes {
410
+ disabled?: boolean
411
+ label?: string
412
+ selected?: boolean
413
+ value?: string | string[] | number
414
+ }
415
+
416
+ export interface OutputHTMLAttributes extends HTMLAttributes {
417
+ form?: string
418
+ htmlfor?: string
419
+ name?: string
420
+ }
421
+
422
+ export interface ParamHTMLAttributes extends HTMLAttributes {
423
+ name?: string
424
+ value?: string | string[] | number
425
+ }
426
+
427
+ export interface ProgressHTMLAttributes extends HTMLAttributes {
428
+ max?: number | string
429
+ value?: string | string[] | number
430
+ }
431
+
432
+ export interface ScriptHTMLAttributes extends HTMLAttributes {
433
+ async?: boolean
434
+ charset?: string
435
+ crossorigin?: string
436
+ defer?: boolean
437
+ integrity?: string
438
+ nonce?: string
439
+ src?: string
440
+ type?: string
441
+ }
442
+
443
+ export interface SelectHTMLAttributes extends HTMLAttributes {
444
+ autofocus?: boolean
445
+ disabled?: boolean
446
+ form?: string
447
+ multiple?: boolean
448
+ name?: string
449
+ required?: boolean
450
+ size?: number
451
+ value?: string | string[] | number
452
+ }
453
+
454
+ export interface SourceHTMLAttributes extends HTMLAttributes {
455
+ media?: string
456
+ sizes?: string
457
+ src?: string
458
+ srcset?: string
459
+ type?: string
460
+ }
461
+
462
+ export interface StyleHTMLAttributes extends HTMLAttributes {
463
+ media?: string
464
+ nonce?: string
465
+ scoped?: boolean
466
+ type?: string
467
+ }
468
+
469
+ export interface TableHTMLAttributes extends HTMLAttributes {
470
+ cellpadding?: number | string
471
+ cellspacing?: number | string
472
+ summary?: string
473
+ }
474
+
475
+ export interface TextareaHTMLAttributes extends HTMLAttributes {
476
+ autocomplete?: string
477
+ autofocus?: boolean
478
+ cols?: number
479
+ dirname?: string
480
+ disabled?: boolean
481
+ form?: string
482
+ maxlength?: number
483
+ minlength?: number
484
+ name?: string
485
+ placeholder?: string
486
+ readonly?: boolean
487
+ required?: boolean
488
+ rows?: number
489
+ value?: string | string[] | number
490
+ wrap?: string
491
+ }
492
+
493
+ export interface TdHTMLAttributes extends HTMLAttributes {
494
+ colspan?: number
495
+ headers?: string
496
+ rowspan?: number
497
+ }
498
+
499
+ export interface ThHTMLAttributes extends HTMLAttributes {
500
+ colspan?: number
501
+ headers?: string
502
+ rowspan?: number
503
+ scope?: string
504
+ }
505
+
506
+ export interface TimeHTMLAttributes extends HTMLAttributes {
507
+ datetime?: string
508
+ }
509
+
510
+ export interface TrackHTMLAttributes extends HTMLAttributes {
511
+ default?: boolean
512
+ kind?: string
513
+ label?: string
514
+ src?: string
515
+ srclang?: string
516
+ }
517
+
518
+ export interface VideoHTMLAttributes extends MediaHTMLAttributes {
519
+ height?: number | string
520
+ playsinline?: boolean
521
+ poster?: string
522
+ width?: number | string
523
+ }
524
+
525
+ export interface AllHTMLAttributes extends HTMLAttributes {
526
+ accept?: string
527
+ acceptcharset?: string
528
+ action?: boolean
529
+ allowfullscreen?: boolean
530
+ allowtransparency?: boolean
531
+ alt?: string
532
+ async?: boolean
533
+ autocomplete?: string
534
+ autofocus?: boolean
535
+ autoplay?: boolean
536
+ capture?: boolean // https://www.w3.org/tr/html-media-capture/#the-capture-attribute
537
+ cellpadding?: number | string
538
+ cellspacing?: number | string
539
+ challenge?: string
540
+ charset?: string
541
+ checked?: boolean
542
+ cite?: string
543
+ classid?: string
544
+ cols?: number
545
+ colspan?: number
546
+ content?: string
547
+ controls?: boolean
548
+ coord?: string
549
+ crossorigin?: string
550
+ data?: string
551
+ datetime?: string
552
+ default?: boolean
553
+ defer?: boolean
554
+ dirname?: string
555
+ disabled?: boolean
556
+ download?: any
557
+ enctype?: string
558
+ form?: string
559
+ formaction?: string
560
+ formenctype?: string
561
+ formmethod?: string
562
+ formnovalidate?: boolean
563
+ formtarget?: string
564
+ frameborder?: number | string
565
+ headers?: string
566
+ height?: number | string
567
+ high?: number
568
+ href?: string
569
+ hreflang?: string
570
+ htmlfor?: string
571
+ httpequiv?: string
572
+ integrity?: string
573
+ keyparams?: string
574
+ keytype?: string
575
+ kind?: string
576
+ label?: string
577
+ list?: string
578
+ loop?: boolean
579
+ low?: number
580
+ manifest?: string
581
+ marginheight?: number
582
+ marginwidth?: number
583
+ max?: number | string
584
+ maxlength?: number
585
+ media?: string
586
+ mediagroup?: string
587
+ method?: string
588
+ min?: number | string
589
+ minlength?: number
590
+ multiple?: boolean
591
+ muted?: boolean
592
+ name?: string
593
+ nonce?: string
594
+ novalidate?: boolean
595
+ open?: boolean
596
+ optimum?: number
597
+ pattern?: string
598
+ placeholder?: string
599
+ playsinline?: boolean
600
+ poster?: string
601
+ preload?: string
602
+ readonly?: boolean
603
+ rel?: string
604
+ required?: boolean
605
+ reversed?: boolean
606
+ rows?: number
607
+ rowspan?: number
608
+ sandbox?: string
609
+ scope?: string
610
+ scoped?: boolean
611
+ scrolling?: string
612
+ seamless?: boolean
613
+ selected?: boolean
614
+ shape?: string
615
+ size?: number
616
+ sizes?: string
617
+ span?: number
618
+ src?: string
619
+ srcdoc?: string
620
+ srclang?: string
621
+ srcset?: string
622
+ start?: number
623
+ step?: number | string
624
+ summary?: string
625
+ target?: string
626
+ type?: string
627
+ usemap?: string
628
+ value?: string | string[] | number
629
+ width?: number | string
630
+ wmode?: string
631
+ wrap?: string
632
+ }
633
+
634
+ export interface IntrinsicElementAttributes {
635
+ a: AnchorHTMLAttributes
636
+ abbr: HTMLAttributes
637
+ address: HTMLAttributes
638
+ area: AreaHTMLAttributes
639
+ article: HTMLAttributes
640
+ aside: HTMLAttributes
641
+ audio: AudioHTMLAttributes
642
+ b: HTMLAttributes
643
+ base: BaseHTMLAttributes
644
+ bdi: HTMLAttributes
645
+ bdo: HTMLAttributes
646
+ big: HTMLAttributes
647
+ blockquote: BlockquoteHTMLAttributes
648
+ body: HTMLAttributes
649
+ br: HTMLAttributes
650
+ button: ButtonHTMLAttributes
651
+ canvas: CanvasHTMLAttributes
652
+ caption: HTMLAttributes
653
+ cite: HTMLAttributes
654
+ code: HTMLAttributes
655
+ col: ColHTMLAttributes
656
+ colgroup: ColgroupHTMLAttributes
657
+ data: HTMLAttributes
658
+ datalist: HTMLAttributes
659
+ dd: HTMLAttributes
660
+ del: DelHTMLAttributes
661
+ details: DetailsHTMLAttributes
662
+ dfn: HTMLAttributes
663
+ dialog: HTMLAttributes
664
+ div: HTMLAttributes
665
+ dl: HTMLAttributes
666
+ dt: HTMLAttributes
667
+ em: HTMLAttributes
668
+ embed: EmbedHTMLAttributes
669
+ fieldset: FieldsetHTMLAttributes
670
+ figcaption: HTMLAttributes
671
+ figure: HTMLAttributes
672
+ footer: HTMLAttributes
673
+ form: FormHTMLAttributes
674
+ h1: HTMLAttributes
675
+ h2: HTMLAttributes
676
+ h3: HTMLAttributes
677
+ h4: HTMLAttributes
678
+ h5: HTMLAttributes
679
+ h6: HTMLAttributes
680
+ head: HTMLAttributes
681
+ header: HTMLAttributes
682
+ hgroup: HTMLAttributes
683
+ hr: HTMLAttributes
684
+ html: HtmlHTMLAttributes
685
+ i: HTMLAttributes
686
+ iframe: IframeHTMLAttributes
687
+ img: ImgHTMLAttributes
688
+ input: InputHTMLAttributes
689
+ ins: InsHTMLAttributes
690
+ kbd: HTMLAttributes
691
+ keygen: KeygenHTMLAttributes
692
+ label: LabelHTMLAttributes
693
+ legend: HTMLAttributes
694
+ li: LiHTMLAttributes
695
+ link: LinkHTMLAttributes
696
+ main: HTMLAttributes
697
+ map: MapHTMLAttributes
698
+ mark: HTMLAttributes
699
+ menu: MenuHTMLAttributes
700
+ menuitem: HTMLAttributes
701
+ meta: MetaHTMLAttributes
702
+ meter: MeterHTMLAttributes
703
+ nav: HTMLAttributes
704
+ noscript: HTMLAttributes
705
+ object: ObjectHTMLAttributes
706
+ ol: OlHTMLAttributes
707
+ optgroup: OptgroupHTMLAttributes
708
+ option: OptionHTMLAttributes
709
+ output: OutputHTMLAttributes
710
+ p: HTMLAttributes
711
+ param: ParamHTMLAttributes
712
+ picture: HTMLAttributes
713
+ pre: HTMLAttributes
714
+ progress: ProgressHTMLAttributes
715
+ q: QuoteHTMLAttributes
716
+ rp: HTMLAttributes
717
+ rt: HTMLAttributes
718
+ ruby: HTMLAttributes
719
+ s: HTMLAttributes
720
+ samp: HTMLAttributes
721
+ script: ScriptHTMLAttributes
722
+ section: HTMLAttributes
723
+ select: SelectHTMLAttributes
724
+ small: HTMLAttributes
725
+ source: SourceHTMLAttributes
726
+ span: HTMLAttributes
727
+ strong: HTMLAttributes
728
+ style: StyleHTMLAttributes
729
+ sub: HTMLAttributes
730
+ summary: HTMLAttributes
731
+ sup: HTMLAttributes
732
+ table: TableHTMLAttributes
733
+ tbody: HTMLAttributes
734
+ td: TdHTMLAttributes
735
+ textarea: TextareaHTMLAttributes
736
+ tfoot: HTMLAttributes
737
+ th: ThHTMLAttributes
738
+ thead: HTMLAttributes
739
+ time: TimeHTMLAttributes
740
+ title: HTMLAttributes
741
+ tr: HTMLAttributes
742
+ track: TrackHTMLAttributes
743
+ u: HTMLAttributes
744
+ ul: HTMLAttributes
745
+ var: HTMLAttributes
746
+ video: VideoHTMLAttributes
747
+ wbr: HTMLAttributes
748
+ }
package/lib.ts ADDED
@@ -0,0 +1,28 @@
1
+ import { Props, IClassComponent, H, FComponentT, Children } from 'h'
2
+ import { updateview } from './jmx'
3
+
4
+ export type DeepReadonly<T> = { readonly [K in keyof T]: T[K] extends Record<string, unknown> ? DeepReadonly<T[K]> : T[K]; }
5
+
6
+ export const When = ({ cond }: { cond: boolean }, cn: Children) => cond ? { cn } : void 0;
7
+
8
+ export abstract class JMXComp<P extends Props = {}> implements IClassComponent {
9
+
10
+ // assigned by jmx framework
11
+ element!: HTMLElement
12
+
13
+ // we provide this ctor for jsx which uses ctor arguments as properties of class components.
14
+ // at runtime, we pass the props directly
15
+ constructor(public props: P) { }
16
+
17
+ // overrides
18
+ mounted() { }
19
+ update(uc?: IUpdateContext): boolean | void { }
20
+ abstract view(): H
21
+
22
+ // utility: updates the component's view
23
+ updateview() { updateview(this.element) }
24
+ }
25
+
26
+ export function cc(...namesOrObjects: (string | any)[]): string {
27
+ return namesOrObjects.flatMap(n => (n.trim ? n : Object.keys(n).filter(k => n[k]))).join(' ') // n.trim distinguishes strings from objects
28
+ }
package/package.json CHANGED
@@ -1,16 +1,13 @@
1
1
  {
2
2
  "name": "jmx-runtime",
3
3
  "author": "snupo",
4
- "version": "0.0.14",
4
+ "version": "0.0.16",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
8
8
  "type": "module",
9
9
  "main": "dist/index.js",
10
10
  "types": "./dist/index.d.ts",
11
- "files": [
12
- "dist"
13
- ],
14
11
  "scripts": {
15
12
  "build": "tsc"
16
13
  }
@@ -0,0 +1,31 @@
1
+ import typescript from "@rollup/plugin-typescript"
2
+ import clean from "rollup-plugin-cleanup"
3
+ import copy from 'rollup-plugin-copy'
4
+ //import { createPathTransform } from 'rollup-sourcemap-path-transform'
5
+
6
+ export default {
7
+ input: 'index.ts',
8
+ output: [
9
+ {
10
+ file: 'dist/index.js',
11
+ format: 'es',
12
+ sourcemap: true,
13
+ }
14
+ ],
15
+ // sourcemapPathTransform: createPathTransform({
16
+ // prefixes: {
17
+ // '*src/components/': '/compi/comps/',
18
+ // '/node_modules/': '/compi/deps/',
19
+ // "../../../../../../../jmxa": "hase"
20
+ // }
21
+ // }),
22
+ plugins: [
23
+ typescript(),
24
+ copy({
25
+ targets: [
26
+ { src: '*.ts', dest: 'dist' }, // Copy all .ts files to dist/src
27
+ ],
28
+ }),
29
+ clean()
30
+ ]
31
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,38 @@
1
+ /* Visit https://aka.ms/tsconfig.json to read more about this file */
2
+ {
3
+ "compilerOptions": {
4
+
5
+ "target": "ESNEXT", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */
6
+ "module": "ESNext", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */
7
+
8
+ "jsx": "react", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
9
+ "jsxFactory": "jsx",
10
+ "jsxFragmentFactory": "jsxf",
11
+
12
+ "declaration": true, /* Generates corresponding '.d.ts' file. */
13
+ // "declarationDir": "dist/types",
14
+ "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */
15
+
16
+ "sourceMap": true, /* Generates corresponding '.map' file. */
17
+ "inlineSources": true,
18
+
19
+ "outDir": "dist", /* Redirect output structure to the directory. */
20
+ "rootDir": ".", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
21
+
22
+ "removeComments": true, /* Do not emit comments to output. */
23
+
24
+ "strict": true, /* Enable all strict type-checking options. */
25
+ "strictNullChecks": true, /* Enable strict null checks. */
26
+ "noImplicitAny": true,
27
+
28
+ "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
29
+ "baseUrl": ".", /* Base directory to resolve non-absolute module names. */
30
+ //"typeRoots": ["types"], /* List of folders to include type definitions from. */
31
+ "esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
32
+ "sourceRoot": ".", /* Specify the location where debugger should locate TypeScript files instead of source locations. */
33
+ "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */
34
+ "skipLibCheck": true, /* Skip type checking of declaration files. */
35
+ "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */
36
+ },
37
+ "include": ["./index.ts"]
38
+ }