material 0.9.21 → 0.9.23
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/index.js +1 -0
- package/package.json +1 -1
- package/src/class/app.js +10 -0
- package/src/class/component.js +16 -13
- package/src/class/control.js +24 -16
- package/src/class/form.js +7 -22
- package/src/class/view.js +18 -19
- package/src/colorpicker.js +356 -0
- package/src/form/cancel.js +1 -2
- package/src/form/controller.js +10 -18
- package/src/form/data.js +175 -47
- package/src/form/fetch.js +18 -25
- package/src/form/render.js +2 -2
- package/src/form/submit.js +9 -3
- package/src/form/update.js +27 -30
- package/src/list/build.js +6 -1
- package/src/list/status.js +5 -0
- package/src/list/update.js +2 -0
- package/src/list/virtual.js +1 -1
- package/src/module/emitter.js +45 -13
- package/src/module/extract.js +2 -2
- package/src/module/layout.js +14 -3
- package/src/module/request.js +49 -16
- package/src/selector.js +1 -1
- package/src/skin/material/control/colorpicker.sass +188 -0
- package/src/switch.js +1 -1
- package/src/switcher.js +11 -2
- package/src/textfield.js +4 -0
- package/src/slider-new.js +0 -341
package/src/form/data.js
CHANGED
|
@@ -1,82 +1,210 @@
|
|
|
1
1
|
import { byString } from '../module/object'
|
|
2
2
|
|
|
3
3
|
export default {
|
|
4
|
-
|
|
4
|
+
/**
|
|
5
|
+
* Initializes form data with fields and files
|
|
6
|
+
* @returns {FormData} Initialized form data
|
|
7
|
+
*/
|
|
5
8
|
initData () {
|
|
6
|
-
|
|
9
|
+
try {
|
|
10
|
+
const data = new FormData()
|
|
7
11
|
|
|
8
|
-
|
|
12
|
+
if (this.mode !== 'create') {
|
|
13
|
+
this.appendSysinfo(data)
|
|
14
|
+
}
|
|
9
15
|
|
|
10
|
-
|
|
11
|
-
|
|
16
|
+
return this.appendFiles(this.appendFields(data))
|
|
17
|
+
} catch (error) {
|
|
18
|
+
console.error('Error initializing form data:', error)
|
|
19
|
+
throw new Error('Failed to initialize form data')
|
|
12
20
|
}
|
|
21
|
+
},
|
|
13
22
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
23
|
+
/**
|
|
24
|
+
* Fetches and sets data for the form
|
|
25
|
+
* @param {Object} user - User data object
|
|
26
|
+
* @returns {Promise<void>}
|
|
27
|
+
*/
|
|
28
|
+
async getData () {
|
|
29
|
+
// console.log('getData')
|
|
30
|
+
Object.entries(this.field).forEach(([fieldName, field]) => {
|
|
31
|
+
console.log('fieldName', fieldName)
|
|
32
|
+
})
|
|
18
33
|
},
|
|
19
34
|
|
|
35
|
+
/**
|
|
36
|
+
* Appends system information to form data
|
|
37
|
+
* @param {FormData} data - FormData instance
|
|
38
|
+
* @returns {FormData} Updated FormData
|
|
39
|
+
*/
|
|
20
40
|
appendSysinfo (data) {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
let name = sys[i]
|
|
25
|
-
if (sys[i] === '_id') name = 'id'
|
|
26
|
-
|
|
27
|
-
data.append(name, this.info[sys[i]])
|
|
41
|
+
// console.log('appendSysinfo')
|
|
42
|
+
if (!Array.isArray(this.options?.sysinfo)) {
|
|
43
|
+
return data
|
|
28
44
|
}
|
|
29
45
|
|
|
46
|
+
this.options.sysinfo.forEach(field => {
|
|
47
|
+
const name = field === '_id' ? 'id' : field
|
|
48
|
+
const value = this.info?.[field]
|
|
49
|
+
|
|
50
|
+
if (value !== undefined) {
|
|
51
|
+
data.append(name, value)
|
|
52
|
+
}
|
|
53
|
+
})
|
|
54
|
+
|
|
30
55
|
return data
|
|
31
56
|
},
|
|
32
57
|
|
|
58
|
+
/**
|
|
59
|
+
* Appends form fields to FormData
|
|
60
|
+
* @param {FormData} data - FormData instance
|
|
61
|
+
* @returns {FormData} Updated FormData
|
|
62
|
+
*/
|
|
33
63
|
appendFields (data) {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
if (this.field.hasOwnProperty(field)) {
|
|
37
|
-
// console.log('check field', field)
|
|
38
|
-
const value = this.field[field].get()
|
|
39
|
-
if (value !== null) {
|
|
40
|
-
if (this.mode === 'update' && this.options.update && this.options.update.modifiedOnly) {
|
|
41
|
-
const modified = this.isModified(field, value)
|
|
42
|
-
if (modified) {
|
|
43
|
-
data.append(field, value)
|
|
44
|
-
}
|
|
45
|
-
} else {
|
|
46
|
-
data.append(field, value)
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
}
|
|
64
|
+
if (!this.field || !(data instanceof FormData)) {
|
|
65
|
+
return data
|
|
50
66
|
}
|
|
51
67
|
|
|
68
|
+
Object.entries(this.field).forEach(([fieldName, field]) => {
|
|
69
|
+
const value = field?.get?.()
|
|
70
|
+
|
|
71
|
+
if (value === null || value === undefined) {
|
|
72
|
+
return
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const shouldAppend = this.mode === 'update' &&
|
|
76
|
+
this.options?.update?.modifiedOnly
|
|
77
|
+
? this.isModified(fieldName, value)
|
|
78
|
+
: true
|
|
79
|
+
|
|
80
|
+
if (shouldAppend) {
|
|
81
|
+
data.append(fieldName, value)
|
|
82
|
+
}
|
|
83
|
+
})
|
|
84
|
+
|
|
52
85
|
return data
|
|
53
86
|
},
|
|
54
87
|
|
|
88
|
+
/**
|
|
89
|
+
* Appends file inputs to FormData
|
|
90
|
+
* @param {FormData} data - FormData instance
|
|
91
|
+
* @returns {FormData} Updated FormData
|
|
92
|
+
*/
|
|
55
93
|
appendFiles (data) {
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
// console.log('this file', this.file, this.file[file].input)
|
|
59
|
-
// console.log('file', file, this.file[file])
|
|
60
|
-
if (this.file.hasOwnProperty(file) && this.file[file].input && this.file[file].input.value) {
|
|
61
|
-
data.append(file, this.file[file].input.files[0])
|
|
62
|
-
}
|
|
94
|
+
if (!this.file || !(data instanceof FormData)) {
|
|
95
|
+
return data
|
|
63
96
|
}
|
|
64
97
|
|
|
98
|
+
Object.entries(this.file)
|
|
99
|
+
.filter(([, fileField]) => {
|
|
100
|
+
const input = fileField?.input
|
|
101
|
+
return input?.value && input?.files?.length > 0
|
|
102
|
+
})
|
|
103
|
+
.forEach(([fileName, fileField]) => {
|
|
104
|
+
data.append(fileName, fileField.input.files[0])
|
|
105
|
+
})
|
|
106
|
+
|
|
65
107
|
return data
|
|
66
108
|
},
|
|
67
109
|
|
|
68
|
-
|
|
69
|
-
|
|
110
|
+
/**
|
|
111
|
+
* Gets structured field data
|
|
112
|
+
* @returns {Object} Field data object
|
|
113
|
+
*/
|
|
114
|
+
getFieldData () {
|
|
115
|
+
if (!this.field) {
|
|
116
|
+
return {}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
return Object.entries(this.field).reduce((acc, [fieldName, field]) => {
|
|
120
|
+
const value = field?.get?.()
|
|
121
|
+
if (value !== null && value !== undefined) {
|
|
122
|
+
acc[fieldName] = value
|
|
123
|
+
}
|
|
124
|
+
return acc
|
|
125
|
+
}, {})
|
|
126
|
+
},
|
|
70
127
|
|
|
71
|
-
|
|
72
|
-
|
|
128
|
+
/**
|
|
129
|
+
* Gets structured file data
|
|
130
|
+
* @returns {Object} File data object
|
|
131
|
+
*/
|
|
132
|
+
getFileData () {
|
|
133
|
+
if (!this.file) {
|
|
134
|
+
return {}
|
|
73
135
|
}
|
|
74
136
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
137
|
+
return Object.entries(this.file).reduce((acc, [fileName, fileField]) => {
|
|
138
|
+
const input = fileField?.input
|
|
139
|
+
if (input?.value && input?.files?.length > 0) {
|
|
140
|
+
acc[fileName] = input.files[0]
|
|
141
|
+
}
|
|
142
|
+
return acc
|
|
143
|
+
}, {})
|
|
144
|
+
},
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Checks if any fields have been modified from their initial values
|
|
148
|
+
* @returns {boolean} True if any field is modified
|
|
149
|
+
*/
|
|
150
|
+
isModified () {
|
|
151
|
+
// console.log('checkModified', this.options.class)
|
|
152
|
+
// console.log('field', this.field)
|
|
153
|
+
// console.log('info', this.info)
|
|
154
|
+
|
|
155
|
+
if (!this.field || !this.info) {
|
|
79
156
|
return false
|
|
80
157
|
}
|
|
158
|
+
|
|
159
|
+
let modified = false
|
|
160
|
+
Object.entries(this.field).forEach(([fieldName]) => {
|
|
161
|
+
if (this.isFieldModified(fieldName)) {
|
|
162
|
+
modified = true
|
|
163
|
+
}
|
|
164
|
+
})
|
|
165
|
+
|
|
166
|
+
this.modified = modified
|
|
167
|
+
|
|
168
|
+
// console.log('modified', modified)
|
|
169
|
+
|
|
170
|
+
return modified
|
|
171
|
+
},
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Checks if a field value has been modified
|
|
175
|
+
* @param {string} fieldName - Field name
|
|
176
|
+
* @returns {boolean} True if modified
|
|
177
|
+
*/
|
|
178
|
+
/**
|
|
179
|
+
* Checks if a specific field value has been modified from its initial value
|
|
180
|
+
* @param {string} fieldName - Field name to check
|
|
181
|
+
* @returns {boolean} True if the field is modified
|
|
182
|
+
*/
|
|
183
|
+
isFieldModified (fieldName) {
|
|
184
|
+
// console.log('isFieldModified', fieldName)
|
|
185
|
+
const currentValue = this.field[fieldName]?.get?.() ?? undefined
|
|
186
|
+
const initialValue = this.info[fieldName] ?? undefined
|
|
187
|
+
|
|
188
|
+
// Special case for text fields: treat undefined and empty string as equivalent
|
|
189
|
+
if (typeof currentValue === 'string' || currentValue === undefined) {
|
|
190
|
+
const normalizedCurrent = currentValue || ''
|
|
191
|
+
const normalizedInitial = initialValue || ''
|
|
192
|
+
return normalizedCurrent !== normalizedInitial
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// Handle number comparisons
|
|
196
|
+
if (typeof initialValue === 'number') {
|
|
197
|
+
const parsedCurrent = Number(currentValue)
|
|
198
|
+
return isNaN(parsedCurrent) ? true : parsedCurrent !== initialValue
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// Standard null/undefined checks
|
|
202
|
+
if (initialValue === undefined || initialValue === null) {
|
|
203
|
+
return currentValue !== null && currentValue !== undefined
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
log.error('modified', initialValue !== currentValue)
|
|
207
|
+
|
|
208
|
+
return initialValue !== currentValue
|
|
81
209
|
}
|
|
82
210
|
}
|
package/src/form/fetch.js
CHANGED
|
@@ -1,30 +1,23 @@
|
|
|
1
|
+
import request from '../module/request'
|
|
2
|
+
|
|
1
3
|
export default {
|
|
2
|
-
fetch (option) {
|
|
4
|
+
async fetch (option) {
|
|
3
5
|
// console.log('fetch', this.options.route, option.method)
|
|
4
|
-
fetch(this.options.route, {
|
|
5
|
-
method: option.method,
|
|
6
|
-
body: option.formData
|
|
7
|
-
}).then(r => r.json()).then(info => {
|
|
8
|
-
if (info.error) {
|
|
9
|
-
// console.log('Error: ' + info.error)
|
|
10
|
-
if (this.error) {
|
|
11
|
-
this.error(info)
|
|
12
|
-
}
|
|
13
|
-
} else {
|
|
14
|
-
// console.log('updated', info, this.mode)
|
|
15
|
-
if (this.mode === 'create') {
|
|
16
|
-
this.emit('created', info)
|
|
17
|
-
this.mode = 'read'
|
|
18
|
-
} else {
|
|
19
|
-
this.info = info
|
|
20
|
-
this.emit('updated', info)
|
|
21
|
-
this.mode = 'read'
|
|
22
|
-
}
|
|
23
6
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
7
|
+
const info = await request(this.options.route, option.method, option.formData)
|
|
8
|
+
|
|
9
|
+
// console.log('updated', info, this.mode)
|
|
10
|
+
if (this.mode === 'create') {
|
|
11
|
+
this.emit('created', info)
|
|
12
|
+
this.mode = 'read'
|
|
13
|
+
} else {
|
|
14
|
+
this.info = info
|
|
15
|
+
this.emit('updated', info)
|
|
16
|
+
this.mode = 'read'
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
if (this.success) {
|
|
20
|
+
this.success(info)
|
|
21
|
+
}
|
|
29
22
|
}
|
|
30
23
|
}
|
package/src/form/render.js
CHANGED
|
@@ -12,10 +12,10 @@ export default {
|
|
|
12
12
|
}
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
-
// console.log('dotified', this.field, info)
|
|
16
|
-
|
|
17
15
|
if (!info) return
|
|
18
16
|
|
|
17
|
+
// console.log('dotified', this.field, info)
|
|
18
|
+
|
|
19
19
|
for (const field in this.field) {
|
|
20
20
|
if (this.field.hasOwnProperty(field)) {
|
|
21
21
|
// console.log('field type', field, this.field[field])
|
package/src/form/submit.js
CHANGED
|
@@ -1,15 +1,20 @@
|
|
|
1
1
|
export default {
|
|
2
2
|
|
|
3
|
-
submit (ev) {
|
|
4
|
-
ev.preventDefault()
|
|
3
|
+
async submit (ev) {
|
|
4
|
+
if (ev) ev.preventDefault()
|
|
5
5
|
// console.log('submit', this.mode)
|
|
6
6
|
|
|
7
7
|
const data = this.initData()
|
|
8
8
|
|
|
9
|
+
// for (const pair of data.entries()) {
|
|
10
|
+
// console.log(`${pair[0]}: ${pair[1]}`)
|
|
11
|
+
// }
|
|
12
|
+
|
|
9
13
|
// console.log('data', data)
|
|
10
14
|
|
|
11
15
|
if (this.update) {
|
|
12
|
-
this.update
|
|
16
|
+
// console.log('this.update', this.update)
|
|
17
|
+
await this.update(data)
|
|
13
18
|
} else {
|
|
14
19
|
this.setMethod(data)
|
|
15
20
|
}
|
|
@@ -18,6 +23,7 @@ export default {
|
|
|
18
23
|
},
|
|
19
24
|
|
|
20
25
|
setMethod (formData) {
|
|
26
|
+
// console.log('setMethod', this.mode)
|
|
21
27
|
let method = 'PUT'
|
|
22
28
|
if (this.mode === 'create') {
|
|
23
29
|
method = 'POST'
|
package/src/form/update.js
CHANGED
|
@@ -1,46 +1,43 @@
|
|
|
1
|
+
import request from '../module/request'
|
|
2
|
+
|
|
1
3
|
export default {
|
|
2
|
-
update (
|
|
3
|
-
// console.log('update',
|
|
4
|
+
async update (body, options) {
|
|
5
|
+
// console.log('update', body, options)
|
|
4
6
|
// console.log('mode', this.mode)
|
|
5
7
|
options = options || {}
|
|
6
8
|
|
|
7
9
|
// console.log('mode', this.mode)
|
|
8
10
|
const method = options.method ||
|
|
9
|
-
|
|
10
|
-
|
|
11
|
+
this.options[this.mode].method ||
|
|
12
|
+
'PUT'
|
|
11
13
|
|
|
12
14
|
const action = options.action ||
|
|
13
|
-
|
|
14
|
-
|
|
15
|
+
this.options[this.mode].action ||
|
|
16
|
+
this.options.action
|
|
15
17
|
|
|
16
18
|
if (this.beforeCreate) {
|
|
17
|
-
this.beforeCreate(
|
|
19
|
+
this.beforeCreate(body)
|
|
18
20
|
}
|
|
19
21
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
22
|
+
// console.log('request', action, method, body)
|
|
23
|
+
const info = await request(action, method, body)
|
|
24
|
+
|
|
25
|
+
// console.log('update', info)
|
|
26
|
+
if (info.error) {
|
|
27
|
+
// console.log('Error: ' + info.error)
|
|
28
|
+
if (this.error) {
|
|
29
|
+
this.error(info)
|
|
30
|
+
}
|
|
31
|
+
} else {
|
|
32
|
+
// console.log('info', this.mode, info)
|
|
33
|
+
if (this.mode === 'create') {
|
|
34
|
+
this.emit('created', info)
|
|
35
|
+
this.setMode('read')
|
|
33
36
|
} else {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
this.emit('created', info)
|
|
37
|
-
this.setMode('read')
|
|
38
|
-
} else {
|
|
39
|
-
this.emit('updated', info)
|
|
40
|
-
this.setMode('read')
|
|
41
|
-
}
|
|
42
|
-
this.info = info
|
|
37
|
+
this.emit('updated', info)
|
|
38
|
+
this.setMode('read')
|
|
43
39
|
}
|
|
44
|
-
|
|
40
|
+
this.info = info
|
|
41
|
+
}
|
|
45
42
|
}
|
|
46
43
|
}
|
package/src/list/build.js
CHANGED
|
@@ -100,7 +100,12 @@ export default {
|
|
|
100
100
|
// console.log('progress', progress, this.count)
|
|
101
101
|
|
|
102
102
|
if (this.statusDisplay) {
|
|
103
|
-
|
|
103
|
+
let percent = parseInt(progress / this.count * 100)
|
|
104
|
+
if (progress > this.count) {
|
|
105
|
+
percent = 100
|
|
106
|
+
progress = this.count
|
|
107
|
+
}
|
|
108
|
+
|
|
104
109
|
this.statusDisplay('count', percent + '% | ' + progress + ' / ' + this.count)
|
|
105
110
|
}
|
|
106
111
|
|
package/src/list/status.js
CHANGED
|
@@ -9,7 +9,12 @@ export default {
|
|
|
9
9
|
|
|
10
10
|
statusCount (count) {
|
|
11
11
|
// console.log('statusCount', count)
|
|
12
|
+
//
|
|
12
13
|
let items = 'items'
|
|
14
|
+
if (count < 1) {
|
|
15
|
+
items = 'item'
|
|
16
|
+
}
|
|
17
|
+
|
|
13
18
|
if (this.status && this.status.count && this.status.count.name) {
|
|
14
19
|
items = this.status.count.name
|
|
15
20
|
}
|
package/src/list/update.js
CHANGED
package/src/list/virtual.js
CHANGED
|
@@ -135,7 +135,7 @@ VirtualList.prototype.set = function (items) {
|
|
|
135
135
|
}
|
|
136
136
|
|
|
137
137
|
const progress = Math.ceil((scrollTop / self.itemHeight) + self.itemsByScreen) - 1
|
|
138
|
-
// console.log('progress', progress)
|
|
138
|
+
// console.log('progress', progress, scrollTop, self.itemHeight)
|
|
139
139
|
self.emit('progress', progress)
|
|
140
140
|
|
|
141
141
|
// e.preventDefault && e.preventDefault()
|
package/src/module/emitter.js
CHANGED
|
@@ -1,21 +1,53 @@
|
|
|
1
|
+
// Event emitter mixin that can be extended into other objects
|
|
1
2
|
export default {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
this.
|
|
5
|
-
|
|
3
|
+
// Initialize the events storage if needed
|
|
4
|
+
_initEvents () {
|
|
5
|
+
this.events = this.events || {}
|
|
6
|
+
},
|
|
7
|
+
|
|
8
|
+
// Add an event listener
|
|
9
|
+
on (event, listener) {
|
|
10
|
+
this._initEvents()
|
|
11
|
+
// Use nullish coalescing assignment for array initialization
|
|
12
|
+
this.events[event] ??= []
|
|
13
|
+
this.events[event].push(listener)
|
|
14
|
+
return this
|
|
15
|
+
},
|
|
16
|
+
|
|
17
|
+
// Emit an event with optional arguments
|
|
18
|
+
emit (event, ...args) {
|
|
19
|
+
this._initEvents()
|
|
20
|
+
// Use optional chaining to safely access and iterate events
|
|
21
|
+
this.events[event]?.forEach(listener => {
|
|
22
|
+
try {
|
|
23
|
+
listener.apply(this, args)
|
|
24
|
+
} catch (error) {
|
|
25
|
+
console.error(`Error in event listener for ${event}:`, error)
|
|
26
|
+
}
|
|
27
|
+
})
|
|
6
28
|
return this
|
|
7
29
|
},
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
this.
|
|
30
|
+
|
|
31
|
+
// Remove a specific listener for an event
|
|
32
|
+
off (event, listener) {
|
|
33
|
+
this._initEvents()
|
|
34
|
+
const listeners = this.events[event]
|
|
35
|
+
if (listeners?.length) {
|
|
36
|
+
const index = listeners.indexOf(listener)
|
|
37
|
+
if (index !== -1) {
|
|
38
|
+
listeners.splice(index, 1)
|
|
39
|
+
}
|
|
40
|
+
}
|
|
12
41
|
return this
|
|
13
42
|
},
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
43
|
+
|
|
44
|
+
// Remove all listeners for an event or all events
|
|
45
|
+
removeAll (event) {
|
|
46
|
+
this._initEvents()
|
|
47
|
+
if (event) {
|
|
48
|
+
delete this.events[event]
|
|
49
|
+
} else {
|
|
50
|
+
this.events = {}
|
|
19
51
|
}
|
|
20
52
|
return this
|
|
21
53
|
}
|
package/src/module/extract.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* @param {[type]} str [description]
|
|
5
5
|
* @return {[type]} [description]
|
|
6
6
|
*/
|
|
7
|
-
|
|
7
|
+
const e = (instance, ev) => {
|
|
8
8
|
if (!ev) return instance
|
|
9
9
|
else if (!ev.match(/\./)) {
|
|
10
10
|
return {
|
|
@@ -43,7 +43,7 @@ function e (instance, ev) {
|
|
|
43
43
|
* @param {string} func A string representing a function accessible in dot notation
|
|
44
44
|
* @return {function} The function
|
|
45
45
|
*/
|
|
46
|
-
|
|
46
|
+
const f = (instance, func) => {
|
|
47
47
|
if (!func) return
|
|
48
48
|
|
|
49
49
|
if (typeof func === 'function') {
|
package/src/module/layout.js
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
import { is as isObject } from '../module/object'
|
|
2
2
|
|
|
3
|
+
const createComponent = (Component, options = {}) => {
|
|
4
|
+
// Check if Component is a class (has prototype) or function
|
|
5
|
+
const isClass = Component.prototype && Component.prototype.constructor === Component
|
|
6
|
+
|
|
7
|
+
if (isClass) {
|
|
8
|
+
return new Component(options)
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
return Component(options)
|
|
12
|
+
}
|
|
13
|
+
|
|
3
14
|
/**
|
|
4
15
|
* Recursively creates components based on a provided schema.
|
|
5
16
|
*
|
|
@@ -9,7 +20,7 @@ import { is as isObject } from '../module/object'
|
|
|
9
20
|
* @param {number} [level=0] - The current level of recursion.
|
|
10
21
|
* @returns {Object} The structure containing all created components.
|
|
11
22
|
*/
|
|
12
|
-
|
|
23
|
+
const create = (schema, container, structure = {}, level = 0, components = []) => {
|
|
13
24
|
level++
|
|
14
25
|
let component
|
|
15
26
|
const object = {}
|
|
@@ -20,7 +31,7 @@ function create (schema, container, structure = {}, level = 0, components = [])
|
|
|
20
31
|
}
|
|
21
32
|
|
|
22
33
|
for (let i = 0; i < schema.length; i++) {
|
|
23
|
-
|
|
34
|
+
let name
|
|
24
35
|
let options = {}
|
|
25
36
|
|
|
26
37
|
if (schema[i] instanceof Object && typeof schema[i] === 'function') {
|
|
@@ -37,7 +48,7 @@ function create (schema, container, structure = {}, level = 0, components = [])
|
|
|
37
48
|
}
|
|
38
49
|
}
|
|
39
50
|
|
|
40
|
-
component =
|
|
51
|
+
component = createComponent(schema[i], options)
|
|
41
52
|
|
|
42
53
|
const element = component.element || component
|
|
43
54
|
if (level === 1) structure.element = element
|