deno.land / x / nano_jsx@v0.1.0 / customElementsMode.ts

customElementsMode.ts
نووسراو ببینە
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
import { h, isSSR, render, _render } from './core.ts'
const defineAsCustomElementsSSR = ( component: any, componentName: string, _publicProps: string[] = [], _options: any = {}) => { if (!/^[a-zA-Z0-9]+-[a-zA-Z0-9]+$/.test(componentName)) console.log(`Error: WebComponent name "${componentName}" is invalid.`) else _nano.customElements.set(componentName, component)}
export const defineAsCustomElements: ( component: any, componentName: string, publicProps: string[], shadow?: ShadowRootInit) => void = function (component, componentName, publicProps, shadow) { if (isSSR()) { defineAsCustomElementsSSR(component, componentName, publicProps) return }
customElements.define( componentName, class extends HTMLElement { component: any $root: ShadowRoot | HTMLElement private isFunctionalComponent: boolean private functionalComponentsProps: any
constructor() { super()
if (shadow) { this.attachShadow(shadow) this.$root = this.shadowRoot as ShadowRoot } else { this.$root = this }
let ref
const el = this.buildEl( _render({ component, props: { ref: (r: any) => (ref = r), children: Array.from(this.children).map(c => render(c)) } }) )
// ------------------------------ first render this.component = ref this.isFunctionalComponent = !component.isClass this.functionalComponentsProps = {} this.appendEl(el) // ------------------------------------------
if (!this.isFunctionalComponent) { this.component.updatePropsValue = (name: string, value: any) => { // @ts-ignore if (!this.component.props) this.component.props = {} this.component.props[name] = value this.component[name] = value } } }
static get observedAttributes() { return publicProps }
private buildEl(contents: any) { // because nano-jsx update needs parentElement, we need // to wrap the element in a div when using shadow mode return h(this.shadowRoot ? 'div' : 'template', null, contents) }
private appendEl(el: any) { if (this.shadowRoot) { // el.dataset.wcRoot = true this.$root.append(el) } else { this.$root.append(...el.childNodes) } }
private removeChildren() { if (this.$root) { const children = Array.from(this.$root?.children) || [] for (const el of children) { el.remove() } } }
attributeChangedCallback(name: string, _: any, newValue: any) { if (!this.isFunctionalComponent) { this.component.updatePropsValue(name, newValue) this.component.update() } else { this.removeChildren() this.functionalComponentsProps[name] = newValue
const el = this.buildEl( _render({ component, props: { children: [], ref: (r: any) => (this.component = r), ...this.functionalComponentsProps } }) )
this.appendEl(el) } } } )}
nano_jsx

Version Info

Tagged at
8 months ago