@domql/element 0.0.1

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/package.json ADDED
@@ -0,0 +1,6 @@
1
+ {
2
+ "name": "@domql/element",
3
+ "version": "0.0.1",
4
+ "main": "src/index.js",
5
+ "license": "MIT"
6
+ }
package/src/assign.js ADDED
@@ -0,0 +1,22 @@
1
+ 'use strict'
2
+
3
+ /**
4
+ * Receives child and parent nodes as parametes
5
+ * and assigns them into real DOM tree
6
+ */
7
+ export const appendNode = (node, parentNode) => {
8
+ parentNode.appendChild(node)
9
+ return node
10
+ }
11
+
12
+ /**
13
+ * Receives elements and assigns the first
14
+ * parameter as a child of the second one
15
+ */
16
+ export const assignNode = (element, parent, key) => {
17
+ parent[key || element.key] = element
18
+ if (element.tag !== 'shadow') {
19
+ appendNode(element.node, parent.node)
20
+ }
21
+ return element
22
+ }
package/src/create.js ADDED
@@ -0,0 +1,125 @@
1
+ 'use strict'
2
+
3
+ import { root } from '@domql/tree'
4
+ import { applyPrototype } from '@domql/proto'
5
+ import { createNode, NODE_REGISTRY, cacheNode } from '@domql/node'
6
+ import { createState } from '@domql/state'
7
+ import { createProps } from '@domql/props'
8
+ import { assignClass } from '@domql/mixins'
9
+ import * as on from '@domql/event/src/on'
10
+ import { isFunction, isNumber, isString, createID, isNode } from '@domql/utils'
11
+
12
+ import { appendNode, assignNode } from './assign'
13
+ import set from './set'
14
+ import update from './update'
15
+ import { remove, lookup, log, keys, parse, parseDeep } from './methods'
16
+
17
+ const ENV = process.env.NODE_ENV
18
+
19
+ /**
20
+ * Creating a domQL element using passed parameters
21
+ */
22
+ export const create = (element, parent, key, options = {}) => {
23
+ // if ELEMENT is not given
24
+ if (element === undefined) element = {}
25
+ if (element === null) return
26
+
27
+ // define KEY
28
+ const assignedKey = element.key || key || createID.next().value
29
+
30
+ // if PARENT is not given
31
+ // if (parent === null) parent = root
32
+ // if (parent === undefined) parent = root
33
+ if (!parent) parent = root
34
+ if (isNode(parent)) parent = root[`${key}_parent`] = { node: parent }
35
+
36
+ // if element is STRING
37
+ if (isString(element) || isNumber(element)) {
38
+ element = {
39
+ text: element,
40
+ tag: (!element.proto && parent.childProto && parent.childProto.tag) ||
41
+ ((NODE_REGISTRY.body.indexOf(key) > -1) && key) || 'string'
42
+ }
43
+ }
44
+
45
+ // enable STATE
46
+ element.state = createState(element, parent)
47
+
48
+ // create PROTOtypal inheritance
49
+ applyPrototype(element, parent, options)
50
+
51
+ // create and assign a KEY
52
+ element.key = assignedKey
53
+
54
+ // set the PATH
55
+ if (ENV === 'test' || ENV === 'development') {
56
+ if (!parent.path) parent.path = []
57
+ element.path = parent.path.concat(assignedKey)
58
+ }
59
+
60
+ // if it already HAS A NODE
61
+ if (element.node) {
62
+ return assignNode(element, parent, assignedKey)
63
+ }
64
+
65
+ // generate a CLASS name
66
+ assignClass(element)
67
+
68
+ // assign METHODS
69
+ element.set = set
70
+ element.update = update
71
+ element.remove = remove
72
+ element.lookup = lookup
73
+ if (ENV === 'test' || ENV === 'development') {
74
+ element.keys = keys
75
+ element.parse = parse
76
+ element.parseDeep = parseDeep
77
+ element.log = log
78
+ }
79
+
80
+ // run `on.init`
81
+ if (element.on && isFunction(element.on.init)) {
82
+ on.init(element.on.init, element, element.state)
83
+ }
84
+
85
+ // enable TRANSFORM in data
86
+ if (!element.transform) element.transform = {}
87
+
88
+ // enable CACHING
89
+ if (!element.__cached) element.__cached = {}
90
+
91
+ // enable EXEC
92
+ if (!element.__exec) element.__exec = {}
93
+
94
+ // enable CHANGES storing
95
+ if (!element.__changes) element.__changes = []
96
+
97
+ // enable CHANGES storing
98
+ const hasRoot = parent.parent && parent.parent.key === ':root'
99
+ if (!element.__root) element.__root = hasRoot ? parent : parent.__root
100
+
101
+ // apply props settings
102
+ createProps(element, parent)
103
+
104
+ // don't render IF in condition
105
+ if (isFunction(element.if) && !element.if(element, element.state)) {
106
+ // TODO: move as fragment
107
+ const ifFragment = cacheNode({ tag: 'fragment' })
108
+ element.__ifFragment = appendNode(ifFragment, parent.node)
109
+ element.__ifFalsy = true
110
+ return
111
+ }
112
+
113
+ // CREATE a real NODE
114
+ createNode(element)
115
+
116
+ // assign NODE
117
+ assignNode(element, parent, key)
118
+
119
+ // run `on.render`
120
+ if (element.on && isFunction(element.on.render)) {
121
+ on.render(element.on.render, element, element.state)
122
+ }
123
+
124
+ return element
125
+ }
package/src/index.js ADDED
@@ -0,0 +1,8 @@
1
+ 'use strict'
2
+
3
+ export * from './assign'
4
+ export * from './create'
5
+ export * from './iterate'
6
+ export * from './methods'
7
+ export * from './set'
8
+ export * from './update'
package/src/iterate.js ADDED
@@ -0,0 +1,80 @@
1
+ 'use strict'
2
+
3
+ import { exec, isFunction, isNumber, isString, overwrite } from '@domql/utils'
4
+ import { isMethod } from './methods'
5
+
6
+ export const applyEvents = element => {
7
+ const { node, on } = element
8
+ for (const param in on) {
9
+ if (
10
+ param === 'init' ||
11
+ param === 'render' ||
12
+ param === 'update'
13
+ ) continue
14
+
15
+ const appliedFunction = element.on[param]
16
+ if (isFunction(appliedFunction)) {
17
+ node.addEventListener(param, event =>
18
+ appliedFunction(event, element, element.state),
19
+ true)
20
+ }
21
+ }
22
+ }
23
+
24
+ export const throughInitialExec = element => {
25
+ for (const param in element) {
26
+ const prop = element[param]
27
+ if (isFunction(prop) && !isMethod(param)) {
28
+ element.__exec[param] = prop
29
+ element[param] = prop(element, element.state)
30
+ }
31
+ }
32
+ }
33
+
34
+ export const throughUpdatedExec = (element, options) => {
35
+ const { __exec } = element
36
+ const changes = {}
37
+
38
+ for (const param in __exec) {
39
+ const prop = element[param]
40
+ const newExec = __exec[param](element, element.state)
41
+
42
+ // if element is string
43
+ if (prop && prop.node && (isString(newExec) || isNumber(newExec))) {
44
+ overwrite(prop, { text: newExec }, options)
45
+ } else if (newExec !== prop) {
46
+ element.__cached[param] = changes[param] = prop
47
+ element[param] = newExec
48
+ }
49
+ }
50
+
51
+ return changes
52
+ }
53
+
54
+ export const throughInitialDefine = element => {
55
+ const { define } = element
56
+ for (const param in define) {
57
+ let prop = element[param]
58
+
59
+ if (isFunction(prop) && !isMethod(param)) {
60
+ element.__exec[param] = prop
61
+ element[param] = prop = exec(prop, element)
62
+ }
63
+
64
+ element.__cached[param] = prop
65
+ element[param] = define[param](prop, element, element.state)
66
+ }
67
+ return element
68
+ }
69
+
70
+ export const throughUpdatedDefine = element => {
71
+ const { define, __exec } = element
72
+ const changes = {}
73
+ for (const param in define) {
74
+ const execParam = __exec[param]
75
+ if (execParam) element.__cached[param] = execParam(element, element.state)
76
+ const cached = exec(element.__cached[param], element)
77
+ element[param] = define[param](cached, element, element.state)
78
+ }
79
+ return changes
80
+ }
package/src/methods.js ADDED
@@ -0,0 +1,96 @@
1
+ 'use strict'
2
+
3
+ import { isObject, isObjectLike } from '@domql/utils'
4
+ import { registry } from '@domql/mixins'
5
+
6
+ // TODO: update these files
7
+ export const lookup = function (key) {
8
+ const element = this
9
+ let { parent } = element
10
+
11
+ while (parent.key !== key) {
12
+ parent = parent.parent
13
+ if (!parent) return
14
+ }
15
+
16
+ return parent
17
+ }
18
+
19
+ export const remove = function (params) {
20
+ const element = this
21
+ element.node.remove()
22
+ delete element.parent[element.key]
23
+ }
24
+
25
+ export const get = function (param) {
26
+ const element = this
27
+ return element[param]
28
+ }
29
+
30
+ export const set = function () {
31
+ }
32
+
33
+ export const update = function () {
34
+ }
35
+
36
+ export const defineSetter = (element, key, get, set) =>
37
+ Object.defineProperty(element, key, { get, set })
38
+
39
+ export const keys = function () {
40
+ const element = this
41
+ const keys = []
42
+ for (const param in element) {
43
+ if (!isObject(registry[param])) {
44
+ keys.push(param)
45
+ }
46
+ }
47
+ return keys
48
+ }
49
+
50
+ export const parse = function () {
51
+ const element = this
52
+ const obj = {}
53
+ const keys = element.keys()
54
+ keys.forEach(v => (obj[v] = element[v]))
55
+ return obj
56
+ }
57
+
58
+ export const parseDeep = function (param) {
59
+ const element = this
60
+ const orig = param || element
61
+ const obj = {}
62
+ const keys = orig.keys && orig.keys()
63
+ if (!keys) return
64
+ keys.forEach(v => {
65
+ const prop = orig[v]
66
+ if (isObjectLike(prop)) parseDeep(prop)
67
+ else obj[v] = prop
68
+ })
69
+ return obj
70
+ }
71
+
72
+ export const log = function (...args) {
73
+ const element = this
74
+ console.group(element.key)
75
+ if (args.length) {
76
+ args.forEach(v => console.log(`%c${v}:\n`, 'font-weight: bold', element[v]))
77
+ } else {
78
+ console.log(element.path)
79
+ const keys = element.keys()
80
+ keys.forEach(v => console.log(`%c${v}:\n`, 'font-weight: bold', element[v]))
81
+ }
82
+ console.groupEnd(element.key)
83
+ return element
84
+ }
85
+
86
+ export const isMethod = function (param) {
87
+ return param === 'set' ||
88
+ param === 'update' ||
89
+ param === 'remove' ||
90
+ param === 'lookup' ||
91
+ param === 'keys' ||
92
+ param === 'parse' ||
93
+ param === 'parseDeep' ||
94
+ param === 'if' ||
95
+ param === 'log'
96
+ }
package/src/set.js ADDED
@@ -0,0 +1,46 @@
1
+ 'use strict'
2
+
3
+ import create from './create'
4
+
5
+ const removeContentElement = (params, element) => {
6
+ if (params && element.content) {
7
+ if (element.content.node) {
8
+ if (element.content.tag === 'fragment') element.node.innerHTML = ''
9
+ else element.node.removeChild(element.content.node)
10
+ }
11
+
12
+ if (element.__cached && element.__cached.content) {
13
+ if (element.__cached.content.tag === 'fragment') element.__cached.content.parent.node.innerHTML = ''
14
+ else element.__cached.content.remove()
15
+ }
16
+
17
+ delete element.content
18
+ }
19
+ }
20
+
21
+ const set = function (params, enter, leave) {
22
+ const element = this
23
+
24
+ removeContentElement(params, element)
25
+
26
+ if (params) {
27
+ const { childProto } = params
28
+ if (!childProto && element.childProto) params.childProto = element.childProto
29
+ create(params, element, 'content', {
30
+ ignoreChildProto: true
31
+ })
32
+ }
33
+
34
+ return element
35
+ }
36
+
37
+ export default set
38
+
39
+ // if (element.content && (isFunction(element.content) || element.content.node)) {
40
+ // // leave(element, () => {
41
+ // // console.log('remove', element.content)
42
+ // // element.content.remove()
43
+ // // element.content.update(params)
44
+ // // element.node.removeChild(element.content.node)
45
+ // // delete element.content
46
+ // }
package/src/update.js ADDED
@@ -0,0 +1,100 @@
1
+ 'use strict'
2
+
3
+ import { overwrite, isFunction, isObject, isString, isNumber, merge } from '@domql/utils'
4
+ import { registry } from '@domql/mixins'
5
+ import { updateProps } from '@domql/props'
6
+ import { createNode } from '@domql/node'
7
+ import * as on from '@domql/event/src/on'
8
+
9
+ import { isMethod } from './methods'
10
+ import { throughUpdatedDefine, throughUpdatedExec } from './iterate'
11
+ import { appendNode } from './assign'
12
+
13
+ const UPDATE_DEFAULT_OPTIONS = {
14
+ stackChanges: false,
15
+ cleanExec: true,
16
+ preventRecursive: false
17
+ }
18
+
19
+ const update = function (params = {}, options = UPDATE_DEFAULT_OPTIONS) {
20
+ const element = this
21
+ const { define, parent, node } = element
22
+
23
+ // console.groupCollapsed('Update:', element.path)
24
+ // console.log('params:')
25
+ // console.log(params)
26
+ // console.log('props:')
27
+ // console.log(element.props)
28
+ // console.log('element:')
29
+ // console.log(element)
30
+ // console.log('PARAMS.PROPS:')
31
+ // console.log(params.props)
32
+ // console.groupEnd('Update:')
33
+ // if params is string
34
+ if (isString(params) || isNumber(params)) {
35
+ params = { text: params }
36
+ }
37
+
38
+ if (element.on && isFunction(element.on.initUpdate)) {
39
+ on.initUpdate(element.on.initUpdate, element, element.state)
40
+ }
41
+
42
+ // console.log(element, parent)
43
+ updateProps(params.props, element, parent)
44
+ // // console.log(element.path)
45
+ // // console.log(element)
46
+
47
+ // console.groupCollapsed('UPDATE:')
48
+ // console.log(element)
49
+ // console.groupEnd('UPDATE:')
50
+
51
+ const overwriteChanges = overwrite(element, params, UPDATE_DEFAULT_OPTIONS)
52
+ const execChanges = throughUpdatedExec(element, UPDATE_DEFAULT_OPTIONS)
53
+ const definedChanges = throughUpdatedDefine(element)
54
+
55
+ if (UPDATE_DEFAULT_OPTIONS.stackChanges && element.__stackChanges) {
56
+ const stackChanges = merge(definedChanges, merge(execChanges, overwriteChanges))
57
+ element.__stackChanges.push(stackChanges)
58
+ }
59
+
60
+ if (isFunction(element.if)) {
61
+ // TODO: move as fragment
62
+ const ifPassed = element.if(element, element.state)
63
+ if (element.__ifFalsy && ifPassed) {
64
+ createNode(element)
65
+ appendNode(element.node, element.__ifFragment)
66
+ delete element.__ifFalsy
67
+ } else if (element.node && !ifPassed) {
68
+ element.node.remove()
69
+ element.__ifFalsy = true
70
+ }
71
+ }
72
+
73
+ // console.log(node)
74
+ // console.groupEnd('Update:')
75
+
76
+ if (!node || options.preventRecursive) return
77
+
78
+ for (const param in element) {
79
+ const prop = element[param]
80
+
81
+ if (isMethod(param) || isObject(registry[param]) || prop === undefined) continue
82
+
83
+ const hasDefined = define && define[param]
84
+ const ourParam = registry[param]
85
+
86
+ // // console.log(prop)
87
+
88
+ if (ourParam) {
89
+ if (isFunction(ourParam)) ourParam(prop, element, node)
90
+ } else if (prop && isObject(prop) && !hasDefined) {
91
+ update.call(prop, params[prop], UPDATE_DEFAULT_OPTIONS)
92
+ }
93
+ }
94
+
95
+ if (element.on && isFunction(element.on.update)) {
96
+ on.update(element.on.update, element, element.state)
97
+ }
98
+ }
99
+
100
+ export default update