@lexriver/dome 2.0.1 → 2.0.3
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/out/index.cjs +802 -0
- package/out/index.mjs +1987 -0
- package/out/src/AnimatedArray.d.ts +29 -0
- package/out/src/AnimatedTable.d.mts +2 -1
- package/out/src/AnimatedTable.d.ts +39 -0
- package/out/src/AnimatedTable.mjs +2 -1
- package/out/src/AnimatedText.d.mts +1 -1
- package/out/src/AnimatedText.d.ts +13 -0
- package/out/src/AnimatedText.mjs +1 -1
- package/out/src/Animation.d.ts +4 -0
- package/out/src/Dome.d.ts +9 -0
- package/out/src/Dome.mjs +1 -1
- package/out/src/DomeComponent.d.mts +4 -1
- package/out/src/DomeComponent.d.ts +25 -0
- package/out/src/DomeComponent.mjs +24 -3
- package/out/src/DomeManipulator.d.mts +4 -0
- package/out/src/DomeManipulator.d.ts +52 -0
- package/out/src/DomeManipulator.mjs +24 -13
- package/out/src/DomeRouter.console-test.d.ts +1 -0
- package/out/src/DomeRouter.d.ts +32 -0
- package/out/src/LongestCommonSubsequence.d.ts +15 -0
- package/out/src/concurrent-updates.test.d.mts +1 -0
- package/out/src/concurrent-updates.test.d.ts +1 -0
- package/out/src/concurrent-updates.test.mjs +203 -0
- package/out/src/index.d.ts +11 -0
- package/out/src/temp-test.d.ts +1 -0
- package/package.json +20 -3
- package/out/vitest.config.d.ts +0 -2
- package/out/vitest.config.js +0 -9
- package/src/AnimatedArray.mts +0 -74
- package/src/AnimatedTable.mts +0 -120
- package/src/AnimatedText.mts +0 -30
- package/src/Animation.mts +0 -4
- package/src/Dome.mts +0 -346
- package/src/DomeComponent.mts +0 -63
- package/src/DomeManipulator.mts +0 -380
- package/src/DomeRouter.console-test.mts +0 -52
- package/src/DomeRouter.mts +0 -287
- package/src/LongestCommonSubsequence.mts +0 -201
- package/src/index.mts +0 -12
- package/src/temp-test.mts +0 -23
- package/tsconfig.json +0 -59
- package/vitest.config.ts +0 -10
package/package.json
CHANGED
|
@@ -1,13 +1,28 @@
|
|
|
1
1
|
{
|
|
2
2
|
"sideEffects": false,
|
|
3
3
|
"name": "@lexriver/dome",
|
|
4
|
-
"version": "2.0.
|
|
4
|
+
"version": "2.0.3",
|
|
5
5
|
"description": "DOM manipulator",
|
|
6
6
|
"type": "module",
|
|
7
|
-
"
|
|
7
|
+
"types": "./out/src/index.d.ts",
|
|
8
|
+
"main": "./out/index.cjs",
|
|
9
|
+
"module": "./out/index.mjs",
|
|
10
|
+
"exports": {
|
|
11
|
+
".": {
|
|
12
|
+
"types": "./out/src/index.d.mts",
|
|
13
|
+
"import": "./out/src/index.mjs",
|
|
14
|
+
"require": "./out/index.cjs",
|
|
15
|
+
"default": "./out/src/index.mjs"
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
"files": [
|
|
19
|
+
"out",
|
|
20
|
+
"README.md"
|
|
21
|
+
],
|
|
8
22
|
"scripts": {
|
|
9
23
|
"test": "vitest",
|
|
10
|
-
"build": "rimraf out && tsc"
|
|
24
|
+
"build": "rimraf out && tsc && node scripts/build-compat.mjs",
|
|
25
|
+
"test:compat": "npm run build && npm --prefix compatibility/ts39-webpack4 install && npm --prefix compatibility/ts39-webpack4 run build"
|
|
11
26
|
},
|
|
12
27
|
"keywords": [
|
|
13
28
|
"typescript",
|
|
@@ -24,6 +39,7 @@
|
|
|
24
39
|
"license": "MIT",
|
|
25
40
|
"devDependencies": {
|
|
26
41
|
"@types/node": "^22.7.0",
|
|
42
|
+
"esbuild": "^0.21.5",
|
|
27
43
|
"rimraf": "^6.0.1",
|
|
28
44
|
"typescript": "^5.6.2",
|
|
29
45
|
"vitest": "^2.1.1"
|
|
@@ -32,6 +48,7 @@
|
|
|
32
48
|
"@lexriver/async": "^3.0.1",
|
|
33
49
|
"@lexriver/data-types": "^3.0.5",
|
|
34
50
|
"@lexriver/observable": "^3.0.0",
|
|
51
|
+
"@lexriver/type-event": "^2.0.0",
|
|
35
52
|
"svg-tag-names": "^3.0.1",
|
|
36
53
|
"ts-debounce": "^4.0.0"
|
|
37
54
|
}
|
package/out/vitest.config.d.ts
DELETED
package/out/vitest.config.js
DELETED
package/src/AnimatedArray.mts
DELETED
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
import { Animation } from './Animation.mjs'
|
|
2
|
-
import { DomeManipulator } from "./DomeManipulator.mjs"
|
|
3
|
-
import { LongestCommonSubsequence } from "./LongestCommonSubsequence.mjs"
|
|
4
|
-
|
|
5
|
-
interface KeyToElementPair{
|
|
6
|
-
key:string
|
|
7
|
-
element:HTMLElement
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export class AnimatedArray<T>{
|
|
11
|
-
arrayOfKeyToElement:KeyToElementPair[] = []
|
|
12
|
-
|
|
13
|
-
constructor(protected params:{
|
|
14
|
-
parentElement?:HTMLElement,
|
|
15
|
-
array?:T[],
|
|
16
|
-
getKey:(o:T)=>string,
|
|
17
|
-
getHtmlElement:(o:T)=>HTMLElement,
|
|
18
|
-
animationShow?:Animation
|
|
19
|
-
animationHide?:Animation
|
|
20
|
-
//renderEmptyList?:()=>HTMLElement
|
|
21
|
-
emptyList?:HTMLElement
|
|
22
|
-
}){
|
|
23
|
-
if(params.array && params.parentElement){
|
|
24
|
-
this.update(params.array)
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
get size():number{
|
|
29
|
-
return this.arrayOfKeyToElement.length
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
update(array:T[], parentElement?:HTMLElement|Element){
|
|
33
|
-
parentElement = parentElement || this.params.parentElement
|
|
34
|
-
if(!parentElement){
|
|
35
|
-
console.warn('AnimatedArray unable to update, no parentElement')
|
|
36
|
-
return
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
if(array.length == 0 && this.params.emptyList){
|
|
40
|
-
DomeManipulator.replaceAllChildrenAsync(parentElement, this.params.emptyList)
|
|
41
|
-
return
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
if(array.length > 0 && this.params.emptyList){
|
|
45
|
-
DomeManipulator.removeElementAsync(this.params.emptyList, this.params.animationHide)
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
//let arrayOfKeyToElement:KeyToElementPair[] = []
|
|
49
|
-
let newArrayOfKeys = array.map((item:T) => this.params.getKey(item))
|
|
50
|
-
let oldArrayOfKeys = this.arrayOfKeyToElement.map(x => x.key)
|
|
51
|
-
LongestCommonSubsequence.getPatchOrdered({
|
|
52
|
-
oldArray: oldArrayOfKeys,
|
|
53
|
-
newArray: newArrayOfKeys,
|
|
54
|
-
onAdd:(index:number, key:string) => {
|
|
55
|
-
if(!parentElement) throw new Error('no parent element') //TODO: remove this
|
|
56
|
-
let itemIndex = newArrayOfKeys.indexOf(key)
|
|
57
|
-
if(itemIndex == -1) throw new Error('no itemIndex') //TODO: remove this
|
|
58
|
-
let item = array[itemIndex]
|
|
59
|
-
let element = this.params.getHtmlElement(item)
|
|
60
|
-
this.arrayOfKeyToElement.splice(index,0,{key, element})
|
|
61
|
-
DomeManipulator.insertByIndexAsync(element, index, parentElement, this.params.animationShow)
|
|
62
|
-
//this.insertNewElementWithAnimation(element, index, parentElement)
|
|
63
|
-
|
|
64
|
-
},
|
|
65
|
-
onRemove: (index:number, key:string) => {
|
|
66
|
-
DomeManipulator.removeElementAsync(this.arrayOfKeyToElement[index].element, this.params.animationHide)
|
|
67
|
-
this.arrayOfKeyToElement.splice(index,1)
|
|
68
|
-
}
|
|
69
|
-
})
|
|
70
|
-
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
}
|
package/src/AnimatedTable.mts
DELETED
|
@@ -1,120 +0,0 @@
|
|
|
1
|
-
import { ObservableVariable } from '@lexriver/observable'
|
|
2
|
-
import { Animation } from './Animation.mjs'
|
|
3
|
-
import { DomeManipulator } from "./DomeManipulator.mjs"
|
|
4
|
-
import { AnimatedArray, DomeComponent } from "./index.mjs"
|
|
5
|
-
|
|
6
|
-
interface Attrs<T>{
|
|
7
|
-
isLoadingO?:ObservableVariable<boolean>
|
|
8
|
-
itemsO:ObservableVariable<T[]>
|
|
9
|
-
animationShowRow:Animation
|
|
10
|
-
animationHideRow:Animation
|
|
11
|
-
animationHideTable?:Animation
|
|
12
|
-
animationShowTable?:Animation
|
|
13
|
-
animationHideEmptyList?:Animation
|
|
14
|
-
animationShowEmptyList?:Animation
|
|
15
|
-
animationShowLoading?:Animation
|
|
16
|
-
animationHideLoading?:Animation
|
|
17
|
-
getKey:(item:T)=>string
|
|
18
|
-
rootElement?:HTMLElement
|
|
19
|
-
tableElement?:HTMLElement
|
|
20
|
-
tableBody?:HTMLElement
|
|
21
|
-
renderTableHead?:(items:T[])=>HTMLElement
|
|
22
|
-
renderTableRow:(item:T)=>HTMLElement
|
|
23
|
-
renderTableFooter?:(items:T[]) => HTMLElement
|
|
24
|
-
renderEmptyList:()=>HTMLElement
|
|
25
|
-
renderLoading?:()=>HTMLElement
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export class AnimatedTable<T> extends DomeComponent<Attrs<T>>{
|
|
29
|
-
// rootElement
|
|
30
|
-
// table
|
|
31
|
-
// thead
|
|
32
|
-
// tbody
|
|
33
|
-
// tfooter
|
|
34
|
-
// emptyList
|
|
35
|
-
refRoot:HTMLElement = this.attrs.rootElement || document.createElement('div')
|
|
36
|
-
refTable:HTMLElement = this.attrs.tableElement || document.createElement('table')
|
|
37
|
-
refTableHead:Element = this.attrs.renderTableHead ? this.attrs.renderTableHead(this.attrs.itemsO.get()) : document.createElement('thead')
|
|
38
|
-
refTableBody:HTMLElement = this.attrs.tableBody || document.createElement('tbody')
|
|
39
|
-
refTableFooter:Element = this.attrs.renderTableFooter ? this.attrs.renderTableFooter(this.attrs.itemsO.get()) : document.createElement('tfoot')
|
|
40
|
-
refEmptyList:Element = this.attrs.renderEmptyList ? this.attrs.renderEmptyList() : document.createElement('div')
|
|
41
|
-
refLoading:Element = this.attrs.renderLoading ? this.attrs.renderLoading() : document.createElement('div')
|
|
42
|
-
|
|
43
|
-
animatedArray = new AnimatedArray<T>({
|
|
44
|
-
animationHide: this.attrs.animationHideRow,
|
|
45
|
-
animationShow: this.attrs.animationShowRow,
|
|
46
|
-
array: [],
|
|
47
|
-
getKey: this.attrs.getKey,
|
|
48
|
-
getHtmlElement: this.attrs.renderTableRow
|
|
49
|
-
})
|
|
50
|
-
|
|
51
|
-
render(){
|
|
52
|
-
// refRoot
|
|
53
|
-
// refTable
|
|
54
|
-
// refTableHead
|
|
55
|
-
// refTableBody
|
|
56
|
-
// refTableFooter
|
|
57
|
-
// refEmptyListEl
|
|
58
|
-
// refLoading
|
|
59
|
-
|
|
60
|
-
this.refRoot.appendChild(this.refTable)
|
|
61
|
-
this.refRoot.appendChild(this.refEmptyList)
|
|
62
|
-
this.refRoot.appendChild(this.refLoading)
|
|
63
|
-
if(this.refTableHead) this.refTable.appendChild(this.refTableHead)
|
|
64
|
-
if(this.refTableBody) this.refTable.appendChild(this.refTableBody)
|
|
65
|
-
if(this.refTableFooter) this.refTable.appendChild(this.refTableFooter)
|
|
66
|
-
console.log('AnimatedTable render()', 'refRoot=', this.refRoot)
|
|
67
|
-
return this.refRoot
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
afterRender(){
|
|
71
|
-
this.updateAsync()
|
|
72
|
-
//this.animatedArray.update(this.attrs.items, this.el)
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
async updateAsync(){
|
|
76
|
-
try {
|
|
77
|
-
if(this.attrs.renderLoading){
|
|
78
|
-
this.refLoading = await DomeManipulator.replaceAsync(this.refLoading, this.attrs.renderLoading())
|
|
79
|
-
}
|
|
80
|
-
if(this.attrs.isLoadingO && this.attrs.isLoadingO.get()){
|
|
81
|
-
// show loading
|
|
82
|
-
await DomeManipulator.unhideElementAsync(this.refLoading, this.attrs.animationShowLoading)
|
|
83
|
-
} else {
|
|
84
|
-
// hide loading
|
|
85
|
-
await DomeManipulator.hideElementAsync(this.refLoading, this.attrs.animationHideLoading)
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
const items = this.attrs.itemsO.get()
|
|
89
|
-
const currentCount = items.length
|
|
90
|
-
|
|
91
|
-
if(currentCount == 0){
|
|
92
|
-
// render empty list
|
|
93
|
-
await DomeManipulator.hideElementAsync(this.refTable, this.attrs.animationHideTable)
|
|
94
|
-
if(this.attrs.renderEmptyList){
|
|
95
|
-
this.refEmptyList = await DomeManipulator.replaceAsync(this.refEmptyList, this.attrs.renderEmptyList())
|
|
96
|
-
}
|
|
97
|
-
await DomeManipulator.unhideElementAsync(this.refEmptyList, this.attrs.animationShowEmptyList)
|
|
98
|
-
|
|
99
|
-
} else {
|
|
100
|
-
|
|
101
|
-
// render list with items
|
|
102
|
-
await DomeManipulator.hideElementAsync(this.refEmptyList, this.attrs.animationHideEmptyList)
|
|
103
|
-
if(this.attrs.renderTableHead){
|
|
104
|
-
this.refTableHead = await DomeManipulator.replaceAsync(this.refTableHead, this.attrs.renderTableHead(items))
|
|
105
|
-
}
|
|
106
|
-
if(this.attrs.renderTableFooter){
|
|
107
|
-
this.refTableFooter = await DomeManipulator.replaceAsync(this.refTableFooter, this.attrs.renderTableFooter(items))
|
|
108
|
-
}
|
|
109
|
-
await DomeManipulator.unhideElementAsync(this.refTable, this.attrs.animationShowTable)
|
|
110
|
-
|
|
111
|
-
this.animatedArray.update(items, this.refTableBody)
|
|
112
|
-
}
|
|
113
|
-
} catch(x){
|
|
114
|
-
console.error('AnimatedTable update failed', x)
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
}
|
|
120
|
-
}
|
package/src/AnimatedText.mts
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import { ObservableVariable } from "@lexriver/observable";
|
|
2
|
-
import { CssClass, DomeManipulator } from "./DomeManipulator.mjs";
|
|
3
|
-
import { DomeComponent } from "./index.mjs";
|
|
4
|
-
|
|
5
|
-
interface Attrs{
|
|
6
|
-
textO:ObservableVariable<string>
|
|
7
|
-
tag?:string
|
|
8
|
-
class?:CssClass
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export class AnimatedText extends DomeComponent<Attrs>{
|
|
12
|
-
render(){
|
|
13
|
-
//const result = this.attrs.tag ? document.createElement(this.attrs.tag) : document.createElement('span')
|
|
14
|
-
const result = document.createElement(this.attrs.tag || 'span')
|
|
15
|
-
//console.log('AnimatedText', 'this.attrs.class=',this.attrs.class)
|
|
16
|
-
if(this.attrs.class){
|
|
17
|
-
DomeManipulator.setCssClasses(result, this.attrs.class)
|
|
18
|
-
}
|
|
19
|
-
result.append(this.attrs.textO.get())
|
|
20
|
-
return result
|
|
21
|
-
}
|
|
22
|
-
async updateAsync(){
|
|
23
|
-
if(!this.rootElement) return
|
|
24
|
-
try {
|
|
25
|
-
this.rootElement = await DomeManipulator.replaceAsync(this.rootElement, this.render(), this.attrs.onHideAnimation, this.attrs.onShowAnimation)
|
|
26
|
-
} catch(x){
|
|
27
|
-
console.error('AnimatedText update failed', x)
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
}
|
package/src/Animation.mts
DELETED
package/src/Dome.mts
DELETED
|
@@ -1,346 +0,0 @@
|
|
|
1
|
-
// inspiration: https://github.com/vadimdemedes/dom-chef/blob/master/index.js
|
|
2
|
-
const svgTagNames = require('svg-tag-names')
|
|
3
|
-
import { DataTypes } from '@lexriver/data-types'
|
|
4
|
-
import { ObservableVariable, checkIfObservable } from '@lexriver/observable'
|
|
5
|
-
import { DomeComponent } from './DomeComponent.mjs'
|
|
6
|
-
import { DomeManipulator } from './DomeManipulator.mjs'
|
|
7
|
-
|
|
8
|
-
const filename = '[Dome]: '
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
interface OnEventObject{
|
|
12
|
-
eventName:string
|
|
13
|
-
eventParams:Object
|
|
14
|
-
eventReaction:(eventParams:Object)=>void
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
//const mountFunctionByNode = new Map<Node, (ref:any)=>void>()
|
|
20
|
-
|
|
21
|
-
// https://github.com/jonschlinkert/arr-flatten/blob/master/index.js
|
|
22
|
-
function flattenArray(arr:any[], res:any[] = []){
|
|
23
|
-
var i = 0, cur;
|
|
24
|
-
var len = arr.length;
|
|
25
|
-
for (; i < len; i++) {
|
|
26
|
-
cur = arr[i];
|
|
27
|
-
Array.isArray(cur) ? flattenArray(cur, res) : res.push(cur);
|
|
28
|
-
}
|
|
29
|
-
return res;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
function checkIfNonDimensionalCssName(name:string){
|
|
34
|
-
// Copied from Preact
|
|
35
|
-
const IS_NON_DIMENSIONAL = /acit|ex(?:s|g|n|p|$)|rph|ows|mnc|ntw|ine[ch]|zoo|^ord/i
|
|
36
|
-
return IS_NON_DIMENSIONAL.test(name)
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
const excludeSvgTags = [
|
|
41
|
-
'a',
|
|
42
|
-
'audio',
|
|
43
|
-
'canvas',
|
|
44
|
-
'iframe',
|
|
45
|
-
'script',
|
|
46
|
-
'video'
|
|
47
|
-
]
|
|
48
|
-
|
|
49
|
-
const svgTags = svgTagNames.filter(name => !excludeSvgTags.includes(name))
|
|
50
|
-
|
|
51
|
-
const isSVG = tagName => svgTags.includes(tagName)
|
|
52
|
-
|
|
53
|
-
const setCSSProps = (el, style:{[key:string]:string|number}) => {
|
|
54
|
-
if(DataTypes.isString(style)){
|
|
55
|
-
el.style = style
|
|
56
|
-
|
|
57
|
-
} else if(DataTypes.isObjectWithKeys(style)){
|
|
58
|
-
Object.keys(style).forEach(name => {
|
|
59
|
-
let value = style[name]
|
|
60
|
-
|
|
61
|
-
if (typeof value === 'number' && !checkIfNonDimensionalCssName(name)) {
|
|
62
|
-
value = `${value}px`
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
el.style[name] = value
|
|
66
|
-
})
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
const createElement = (tagName) => {
|
|
71
|
-
if (isSVG(tagName)) {
|
|
72
|
-
return document.createElementNS('http://www.w3.org/2000/svg', tagName)
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
if (tagName === DocumentFragment) {
|
|
76
|
-
return document.createDocumentFragment()
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
return document.createElement(tagName)
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
// function subscribeToEventByParam(x:OnEventObject, el:HTMLElement){
|
|
84
|
-
// if(
|
|
85
|
-
// !x.eventName ||
|
|
86
|
-
// Data.isString(x.eventName) == false ||
|
|
87
|
-
// !x.eventReaction ||
|
|
88
|
-
// Data.isFunction(x.eventReaction) == false
|
|
89
|
-
// ){
|
|
90
|
-
// console.error('x=', x, 'el=', el)
|
|
91
|
-
// throw new Error(`Please provide object of type {eventName:string, eventParams:Object, eventReaction:(eventParams, htmlElement)=>void}`)
|
|
92
|
-
// }
|
|
93
|
-
// //DomeEventDispatcher.subscribeToEvent(el, x.eventName, x.eventParams || {}, x.eventReaction)
|
|
94
|
-
// DomeEventDispatcher.subscribeToEvent({
|
|
95
|
-
// eventName: x.eventName,
|
|
96
|
-
// eventParamsFilter: x.eventParams || {},
|
|
97
|
-
// action: x.eventReaction,
|
|
98
|
-
// unsubscribeWhen: () => DomeManipulator.isInDom(el) == false
|
|
99
|
-
// })
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
// }
|
|
103
|
-
|
|
104
|
-
const build = (tagName, attrs, children:DocumentFragment) => {
|
|
105
|
-
if(!tagName) {
|
|
106
|
-
console.trace()
|
|
107
|
-
throw new Error('tagName='+tagName)
|
|
108
|
-
}
|
|
109
|
-
// if(children && typeof children !== 'object'){
|
|
110
|
-
// //console.log('tagName=', tagName, 'attrs=',attrs, 'children=', children)
|
|
111
|
-
// console.log('tagName=', tagName, 'children=', children, 'typeof children=', typeof children)
|
|
112
|
-
// }
|
|
113
|
-
if(tagName == DocumentFragment){
|
|
114
|
-
//console.warn(filename, 'isDocumentFragment!')
|
|
115
|
-
const el = createElement(tagName)
|
|
116
|
-
el.appendChild(children)
|
|
117
|
-
return el
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
//console.log(filename, 'instaceof=', tagName instanceof DomeComponent)
|
|
121
|
-
//console.log(filename, 'has render=', tagName.render)
|
|
122
|
-
//console.log(filename, 'instanceof Object=', tagName instanceof Object)
|
|
123
|
-
|
|
124
|
-
if(tagName.prototype && tagName.prototype['__DomeComponent']){
|
|
125
|
-
// we have a DomeComponent
|
|
126
|
-
//console.warn('DomeComponent!')
|
|
127
|
-
try {
|
|
128
|
-
const instance = new tagName(attrs, children) as DomeComponent<any>
|
|
129
|
-
//console.log('instance=', instance)
|
|
130
|
-
if(instance['render'] && DataTypes.isFunction(instance['render'])){
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
//#region make ref points to instance, not element
|
|
134
|
-
if(attrs.ref && DataTypes.isFunction(attrs.ref)){
|
|
135
|
-
attrs.ref(instance)
|
|
136
|
-
}
|
|
137
|
-
//#endregion
|
|
138
|
-
|
|
139
|
-
instance['init']()
|
|
140
|
-
|
|
141
|
-
instance.rootElement = instance['render']()
|
|
142
|
-
|
|
143
|
-
//#region subscribe to observable attribute
|
|
144
|
-
for(let attribute of Object.values(attrs)){
|
|
145
|
-
if(checkIfObservable(attribute)){
|
|
146
|
-
attribute.eventOnChange.subscribe(() => {
|
|
147
|
-
//this.update()
|
|
148
|
-
instance.scheduleUpdate()
|
|
149
|
-
})
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
//#endregion
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
//requestAnimationFrame(() => {
|
|
156
|
-
instance['afterRender']()
|
|
157
|
-
//})
|
|
158
|
-
|
|
159
|
-
return instance.rootElement
|
|
160
|
-
}
|
|
161
|
-
} catch(error){
|
|
162
|
-
console.error('error while creating DomeComponent class', error)
|
|
163
|
-
}
|
|
164
|
-
return;
|
|
165
|
-
|
|
166
|
-
}
|
|
167
|
-
if(DataTypes.isFunction(tagName)){
|
|
168
|
-
// call functional component
|
|
169
|
-
return tagName(attrs, children)
|
|
170
|
-
|
|
171
|
-
} else if(DataTypes.isString(tagName)){
|
|
172
|
-
const el = createElement(tagName)
|
|
173
|
-
//console.log('lex-dome', 'creating element', el)
|
|
174
|
-
|
|
175
|
-
Object.keys(attrs).forEach(name => {
|
|
176
|
-
const value = attrs[name]
|
|
177
|
-
|
|
178
|
-
if (name === 'class' || name === 'className' || name === 'cssClasses') {
|
|
179
|
-
//DomeManipulator.setCssClasses(el, value)
|
|
180
|
-
assignDynamicCssClasses(name, value, el)
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
} else if (name === 'style') {
|
|
185
|
-
setCSSProps(el, value)
|
|
186
|
-
|
|
187
|
-
} else if(['disabled', 'autocomplete', 'selected', 'checked'].indexOf(name) >= 0){
|
|
188
|
-
if(attrs[name]){
|
|
189
|
-
DomeManipulator.setAttribute(el, name, name)
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
} else if(name === 'onCreate' || name === 'ref'){
|
|
193
|
-
if(DataTypes.isFunction(value) == false) throw new Error(`Please provide function <${tagName} ${name}={ref => myRef=ref} />`)
|
|
194
|
-
value(el)
|
|
195
|
-
|
|
196
|
-
// } else if(name === 'onEvent'){ //TODO: remove this!?
|
|
197
|
-
// // <div onEvent={{eventName:'myCumstomEvent', eventParams:{any:'params',can:'be',here:true}, eventReaction:()=>{}}}>some text for div</div>
|
|
198
|
-
// //#region is Object
|
|
199
|
-
// if(Data.isObjectWithKeys(value)){
|
|
200
|
-
// subscribeToEventByParam(value as OnEventObject, el)
|
|
201
|
-
// return
|
|
202
|
-
// }
|
|
203
|
-
// //#endregion
|
|
204
|
-
|
|
205
|
-
// //#region is Array
|
|
206
|
-
// if(Data.isArray(value)){
|
|
207
|
-
// for(let x of value){
|
|
208
|
-
// subscribeToEventByParam(x as OnEventObject, el)
|
|
209
|
-
// }
|
|
210
|
-
// }
|
|
211
|
-
// //#endregion
|
|
212
|
-
|
|
213
|
-
} else if(name == 'visibleIf'){ //TODO: remove this!?
|
|
214
|
-
if(checkIfObservable(value) == false) {
|
|
215
|
-
console.error('value=', value)
|
|
216
|
-
throw new Error('Please provide Observable<boolean> as argument for visibleIf')
|
|
217
|
-
}
|
|
218
|
-
let obs = value as ObservableVariable<boolean>
|
|
219
|
-
obs.eventOnChange.subscribe((isVisible) => {
|
|
220
|
-
if(isVisible){
|
|
221
|
-
DomeManipulator.unhideElementAsync(el)
|
|
222
|
-
} else {
|
|
223
|
-
DomeManipulator.hideElementAsync(el)
|
|
224
|
-
}
|
|
225
|
-
})
|
|
226
|
-
|
|
227
|
-
setTimeout(() => { //TODO: hack to trigger event on mount to DOM
|
|
228
|
-
obs.eventOnChange.triggerAsync(obs.get())
|
|
229
|
-
}, 1)
|
|
230
|
-
|
|
231
|
-
} else if (name.indexOf('on') === 0 && value) {
|
|
232
|
-
const eventName = name.slice(2).toLowerCase()
|
|
233
|
-
if(DataTypes.isFunction(value) == false) {
|
|
234
|
-
console.error('unable to subscribe for event', eventName, 'listener is not a function', 'element=', el, 'listener=', value)
|
|
235
|
-
return
|
|
236
|
-
}
|
|
237
|
-
//console.log('adding event listener for', el, 'eventName=', eventName, 'value=', value)
|
|
238
|
-
el.addEventListener(eventName, value)
|
|
239
|
-
|
|
240
|
-
} else if (name === 'innerHtml') {
|
|
241
|
-
el.innerHTML = value
|
|
242
|
-
|
|
243
|
-
} else if (name !== 'key' && value !== false) {
|
|
244
|
-
DomeManipulator.setAttribute(el, name, value === true ? '' : value)
|
|
245
|
-
}
|
|
246
|
-
})
|
|
247
|
-
|
|
248
|
-
if (!attrs.innerHtml) {
|
|
249
|
-
el.appendChild(children)
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
return el
|
|
253
|
-
|
|
254
|
-
} else throw new Error("not implemented")
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
/**
|
|
260
|
-
*
|
|
261
|
-
* @param value
|
|
262
|
-
* @param name
|
|
263
|
-
* @param element
|
|
264
|
-
*/
|
|
265
|
-
function assignDynamicCssClasses(name: string, value: {[key:string]:boolean|ObservableVariable<boolean>}, element: any) {
|
|
266
|
-
if (DataTypes.isObjectWithKeys(value) == false){
|
|
267
|
-
DomeManipulator.setCssClasses(element, value)
|
|
268
|
-
return
|
|
269
|
-
//throw new Error(`Please provide object for ${name}, ex: {class1:true, class2:myVarO}`)
|
|
270
|
-
}
|
|
271
|
-
let resultArray: string[] = []
|
|
272
|
-
for (let [k, v] of Object.entries(value)) {
|
|
273
|
-
if(v === undefined){
|
|
274
|
-
//skip
|
|
275
|
-
|
|
276
|
-
} else if (DataTypes.isBoolean(v)) {
|
|
277
|
-
if(v){
|
|
278
|
-
resultArray.push(k)
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
} else if (checkIfObservable(v)) {
|
|
282
|
-
let o = v as ObservableVariable<boolean>
|
|
283
|
-
o.eventOnChange.subscribe((showThiCssClass) => {
|
|
284
|
-
if(!DomeManipulator.isInDom(element)) return {unsubscribe:true} //TODO: test it
|
|
285
|
-
// reassign whole attribute
|
|
286
|
-
DomeManipulator.setCssClasses(element, value)
|
|
287
|
-
})
|
|
288
|
-
if (o.get()) {
|
|
289
|
-
resultArray.push(k)
|
|
290
|
-
}
|
|
291
|
-
} else {
|
|
292
|
-
console.error(`Please provide classNames as a keys and boolean or Observable<boolean> for values., ex: {class1:true, class2:myVarO}`, 'name=', name, 'value=', value, 'typeof value =', typeof value)
|
|
293
|
-
throw new Error('Wrong value for `class` attribute')
|
|
294
|
-
}
|
|
295
|
-
}
|
|
296
|
-
DomeManipulator.setCssClasses(element, resultArray) // yes, array of classes is ok here
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
export function h(tagName, attrs, ...childrenArgs) {
|
|
300
|
-
// eslint-disable-next-line prefer-rest-params
|
|
301
|
-
//const childrenArgs = [].slice.apply(arguments, [2])
|
|
302
|
-
const children = document.createDocumentFragment()
|
|
303
|
-
//const childArray:any[] = []
|
|
304
|
-
|
|
305
|
-
// console.log(filename, 'childrenArgs=', childrenArgs)
|
|
306
|
-
// console.log(filename, 'childrenO=', childrenO)
|
|
307
|
-
// if(tagName === 'hoho'){
|
|
308
|
-
// console.warn(filename, tagName, attrs, ...childrenArgs)
|
|
309
|
-
// }
|
|
310
|
-
|
|
311
|
-
flattenArray(childrenArgs).forEach(child => {
|
|
312
|
-
//(childrenArgs).forEach(child => {
|
|
313
|
-
// if(tagName === 'hoho'){
|
|
314
|
-
// console.warn(filename, 'child=', child)
|
|
315
|
-
// }
|
|
316
|
-
if (child instanceof Node) {
|
|
317
|
-
children.appendChild(child)
|
|
318
|
-
//childArray.push(child)
|
|
319
|
-
|
|
320
|
-
// const mountFunction = mountFunctionByNode.get(child)
|
|
321
|
-
// if(mountFunction){
|
|
322
|
-
// mountFunction(child)
|
|
323
|
-
// mountFunctionByNode.delete(child)// delete after execution
|
|
324
|
-
// }
|
|
325
|
-
|
|
326
|
-
} else if (typeof child !== 'boolean' && typeof child !== 'undefined' && child !== null) {
|
|
327
|
-
//console.log('[Dome] child=', child)
|
|
328
|
-
//console.warn(filename, 'text? child=', child)
|
|
329
|
-
children.appendChild(document.createTextNode(child))
|
|
330
|
-
//childArray.push(document.createTextNode(child))
|
|
331
|
-
}
|
|
332
|
-
})
|
|
333
|
-
|
|
334
|
-
//return build(tagName, attrs || {}, children)
|
|
335
|
-
return build(tagName, attrs || {}, children)
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
// Improve TypeScript support for DocumentFragment
|
|
339
|
-
// https://github.com/Microsoft/TypeScript/issues/20469
|
|
340
|
-
export const React = {
|
|
341
|
-
createElement: h,
|
|
342
|
-
Fragment: typeof DocumentFragment === 'function' ? DocumentFragment : () => {}
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
export default React
|
|
346
|
-
|