@knowark/componarkjs 1.13.4 → 1.14.0
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/lib/base/component/component.js +17 -1
- package/lib/base/component/component.test.js +475 -389
- package/lib/base/utils/define.js +28 -6
- package/lib/base/utils/define.test.js +129 -42
- package/lib/base/utils/format.test.js +16 -16
- package/lib/base/utils/helpers.js +11 -4
- package/lib/base/utils/helpers.test.js +134 -115
- package/lib/base/utils/slots.test.js +38 -38
- package/lib/base/utils/uuid.test.js +13 -13
- package/lib/components/audio/components/audio.js +19 -1
- package/lib/components/audio/components/audio.test.js +120 -90
- package/lib/components/camera/components/camera.js +5 -0
- package/lib/components/camera/components/camera.test.js +96 -91
- package/lib/components/capture/components/capture.js +30 -2
- package/lib/components/capture/components/capture.test.js +165 -97
- package/lib/components/droparea/components/droparea-preview.js +58 -8
- package/lib/components/droparea/components/droparea-preview.test.js +262 -80
- package/lib/components/droparea/components/droparea.js +41 -4
- package/lib/components/droparea/components/droparea.test.js +309 -299
- package/lib/components/emit/components/emit.js +23 -3
- package/lib/components/emit/components/emit.test.js +192 -134
- package/lib/components/list/components/item.test.js +69 -68
- package/lib/components/list/components/list.js +33 -3
- package/lib/components/list/components/list.test.js +358 -227
- package/lib/components/paginator/components/paginator.test.js +146 -143
- package/lib/components/spinner/components/spinner.test.js +36 -41
- package/lib/components/splitview/components/splitview.detail.test.js +75 -73
- package/lib/components/splitview/components/splitview.js +36 -8
- package/lib/components/splitview/components/splitview.master.js +27 -2
- package/lib/components/splitview/components/splitview.master.test.js +52 -52
- package/lib/components/splitview/components/splitview.test.js +135 -31
- package/lib/components/translate/components/translate.js +28 -8
- package/lib/components/translate/components/translate.test.js +492 -133
- package/package.json +3 -27
- package/scripts/node-test-setup.js +94 -0
|
@@ -14,7 +14,7 @@ export class Capture extends Component {
|
|
|
14
14
|
|
|
15
15
|
/** @param {Object} context */
|
|
16
16
|
init (context = {}) {
|
|
17
|
-
const data =
|
|
17
|
+
const data = this._parseJSON(this._pop(':scope > data')?.textContent)
|
|
18
18
|
this.source = /** @type {object} */ (
|
|
19
19
|
context.source) || data || this.source || {}
|
|
20
20
|
this.template = context.template || this.template || (
|
|
@@ -42,7 +42,24 @@ export class Capture extends Component {
|
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
_format (template) {
|
|
45
|
-
|
|
45
|
+
let render = null
|
|
46
|
+
|
|
47
|
+
try {
|
|
48
|
+
render = Function(`return \`${template}\``)
|
|
49
|
+
} catch (error) {
|
|
50
|
+
this.emit('error', error)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return (data) => {
|
|
54
|
+
if (!render) return ''
|
|
55
|
+
|
|
56
|
+
try {
|
|
57
|
+
return render.call(data)
|
|
58
|
+
} catch (error) {
|
|
59
|
+
this.emit('error', error)
|
|
60
|
+
return ''
|
|
61
|
+
}
|
|
62
|
+
}
|
|
46
63
|
}
|
|
47
64
|
|
|
48
65
|
_pop (selector) {
|
|
@@ -50,5 +67,16 @@ export class Capture extends Component {
|
|
|
50
67
|
element?.remove()
|
|
51
68
|
return element
|
|
52
69
|
}
|
|
70
|
+
|
|
71
|
+
_parseJSON (source) {
|
|
72
|
+
if (!source) return null
|
|
73
|
+
|
|
74
|
+
try {
|
|
75
|
+
return JSON.parse(source)
|
|
76
|
+
} catch (error) {
|
|
77
|
+
this.emit('error', error)
|
|
78
|
+
return null
|
|
79
|
+
}
|
|
80
|
+
}
|
|
53
81
|
}
|
|
54
82
|
Component.define(tag, Capture)
|
|
@@ -1,112 +1,180 @@
|
|
|
1
|
+
import { it } from 'node:test'
|
|
2
|
+
import assert from 'node:assert/strict'
|
|
1
3
|
import './capture.js'
|
|
2
4
|
|
|
3
|
-
|
|
4
|
-
let container = null
|
|
5
|
+
let container = null
|
|
5
6
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
const setup = () => {
|
|
8
|
+
document.body.innerHTML = ''
|
|
9
|
+
container = document.createElement('div')
|
|
10
|
+
document.body.appendChild(container)
|
|
11
|
+
}
|
|
10
12
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
it('can be instantiated', () => {
|
|
14
|
+
setup()
|
|
15
|
+
container.innerHTML = `
|
|
16
|
+
<ark-capture></ark-capture>
|
|
17
|
+
`
|
|
15
18
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
`
|
|
19
|
+
const capture = container.querySelector('ark-capture')
|
|
20
|
+
assert.deepStrictEqual(capture, capture.init())
|
|
21
|
+
})
|
|
20
22
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
23
|
+
it('renders the given data detail', () => {
|
|
24
|
+
setup()
|
|
25
|
+
container.innerHTML = `
|
|
26
|
+
<ark-capture>
|
|
27
|
+
<data>
|
|
28
|
+
{
|
|
29
|
+
"name": "John Doe",
|
|
30
|
+
"job": "Programmer"
|
|
31
|
+
}
|
|
32
|
+
</data>
|
|
33
|
+
<output></output>
|
|
34
|
+
</ark-capture>
|
|
35
|
+
`
|
|
36
|
+
|
|
37
|
+
const capture = container.querySelector('ark-capture')
|
|
38
|
+
capture.init().render()
|
|
39
|
+
const output = capture.querySelector('output')
|
|
40
|
+
|
|
41
|
+
assert.deepStrictEqual(capture.children.length, 1)
|
|
42
|
+
assert.ok(output.innerHTML.includes('John Doe'))
|
|
43
|
+
assert.ok(output.innerHTML.includes('Programmer'))
|
|
44
|
+
})
|
|
24
45
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
46
|
+
it('renders json data on the given template on the given output', () => {
|
|
47
|
+
setup()
|
|
48
|
+
container.innerHTML = `
|
|
49
|
+
<ark-capture>
|
|
50
|
+
<data>
|
|
51
|
+
{
|
|
52
|
+
"name": "John Doe",
|
|
53
|
+
"job": "Programmer"
|
|
54
|
+
}
|
|
55
|
+
</data>
|
|
56
|
+
<template>
|
|
57
|
+
<div id="output">
|
|
58
|
+
<strong>\${this.name}</strong>
|
|
59
|
+
<strong>\${this.job}</strong>
|
|
60
|
+
</div>
|
|
61
|
+
</template>
|
|
62
|
+
<output></output>
|
|
63
|
+
</ark-capture>
|
|
64
|
+
`
|
|
65
|
+
|
|
66
|
+
const capture = container.querySelector('ark-capture')
|
|
67
|
+
capture.init().render()
|
|
68
|
+
const output = capture.querySelector('output')
|
|
69
|
+
|
|
70
|
+
assert.deepStrictEqual(capture.children.length, 1)
|
|
71
|
+
assert.ok(output.children[0].innerHTML.includes('John Doe'))
|
|
72
|
+
assert.ok(output.children[0].innerHTML.includes('Programmer'))
|
|
73
|
+
})
|
|
74
|
+
|
|
75
|
+
it('captures specific custom events and renders its details', () => {
|
|
76
|
+
setup()
|
|
77
|
+
container.innerHTML = `
|
|
78
|
+
<ark-capture receive="custom">
|
|
79
|
+
<template>
|
|
80
|
+
<div id="output">
|
|
81
|
+
<strong>\${this.name}</strong>
|
|
82
|
+
<strong>\${this.job}</strong>
|
|
83
|
+
</div>
|
|
84
|
+
</template>
|
|
85
|
+
<output></output>
|
|
86
|
+
<p>Adjoint Element</p>
|
|
87
|
+
</ark-capture>
|
|
88
|
+
`
|
|
89
|
+
|
|
90
|
+
const capture = container.querySelector('ark-capture')
|
|
91
|
+
capture.init().render()
|
|
92
|
+
capture.addEventListener('custom', capture.handle.bind(capture))
|
|
93
|
+
const output = capture.querySelector('output')
|
|
94
|
+
|
|
95
|
+
capture.dispatchEvent(new CustomEvent('custom', {
|
|
96
|
+
bubbles: true,
|
|
97
|
+
detail: {
|
|
98
|
+
name: 'Richard Roe', job: 'Analyst'
|
|
99
|
+
}
|
|
100
|
+
}))
|
|
101
|
+
|
|
102
|
+
assert.deepStrictEqual(capture.children.length, 2)
|
|
103
|
+
assert.ok(output.children[0].innerHTML.includes('Richard Roe'))
|
|
104
|
+
assert.ok(output.children[0].innerHTML.includes('Analyst'))
|
|
105
|
+
|
|
106
|
+
capture.dispatchEvent(new CustomEvent('custom', {
|
|
107
|
+
bubbles: true,
|
|
108
|
+
detail: {
|
|
109
|
+
name: 'Megan More', job: 'Manager'
|
|
110
|
+
}
|
|
111
|
+
}))
|
|
112
|
+
|
|
113
|
+
assert.deepStrictEqual(capture.children.length, 2)
|
|
114
|
+
assert.ok(output.children[0].innerHTML.includes('Megan More'))
|
|
115
|
+
assert.ok(output.children[0].innerHTML.includes('Manager'))
|
|
116
|
+
})
|
|
45
117
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
</div>
|
|
60
|
-
</template>
|
|
61
|
-
<output></output>
|
|
62
|
-
</ark-capture>
|
|
63
|
-
`
|
|
64
|
-
|
|
65
|
-
const capture = container.querySelector('ark-capture')
|
|
66
|
-
const output = capture.querySelector('output')
|
|
67
|
-
|
|
68
|
-
expect(capture.children.length).toEqual(1)
|
|
69
|
-
expect(output.children[0].innerHTML).toContain('John Doe')
|
|
70
|
-
expect(output.children[0].innerHTML).toContain('Programmer')
|
|
118
|
+
it('emits error when data JSON is invalid', () => {
|
|
119
|
+
setup()
|
|
120
|
+
const holder = document.createElement('div')
|
|
121
|
+
holder.innerHTML = `
|
|
122
|
+
<ark-capture>
|
|
123
|
+
<data>{ invalid json }</data>
|
|
124
|
+
<output></output>
|
|
125
|
+
</ark-capture>
|
|
126
|
+
`
|
|
127
|
+
const capture = holder.querySelector('ark-capture')
|
|
128
|
+
let errorEvent = null
|
|
129
|
+
capture.addEventListener('error', (event) => {
|
|
130
|
+
errorEvent = event
|
|
71
131
|
})
|
|
72
132
|
|
|
73
|
-
|
|
74
|
-
container.innerHTML = `
|
|
75
|
-
<ark-capture receive="custom">
|
|
76
|
-
<template>
|
|
77
|
-
<div id="output">
|
|
78
|
-
<strong>\${this.name}</strong>
|
|
79
|
-
<strong>\${this.job}</strong>
|
|
80
|
-
</div>
|
|
81
|
-
</template>
|
|
82
|
-
<output></output>
|
|
83
|
-
<p>Adjoint Element</p>
|
|
84
|
-
</ark-capture>
|
|
85
|
-
`
|
|
86
|
-
|
|
87
|
-
const capture = container.querySelector('ark-capture')
|
|
88
|
-
const output = capture.querySelector('output')
|
|
89
|
-
|
|
90
|
-
capture.dispatchEvent(new CustomEvent('custom', {
|
|
91
|
-
bubbles: true,
|
|
92
|
-
detail: {
|
|
93
|
-
name: 'Richard Roe', job: 'Analyst'
|
|
94
|
-
}
|
|
95
|
-
}))
|
|
133
|
+
capture.init().render()
|
|
96
134
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
expect(output.children[0].innerHTML).toContain('Analyst')
|
|
135
|
+
assert.ok(errorEvent)
|
|
136
|
+
})
|
|
100
137
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
}
|
|
138
|
+
it('emits error when template cannot be compiled', () => {
|
|
139
|
+
setup()
|
|
140
|
+
const holder = document.createElement('div')
|
|
141
|
+
holder.innerHTML = `
|
|
142
|
+
<ark-capture>
|
|
143
|
+
<data>{"name":"John"}</data>
|
|
144
|
+
<template>\${this.name</template>
|
|
145
|
+
<output></output>
|
|
146
|
+
</ark-capture>
|
|
147
|
+
`
|
|
148
|
+
const capture = holder.querySelector('ark-capture')
|
|
149
|
+
let errorEvent = null
|
|
150
|
+
capture.addEventListener('error', (event) => {
|
|
151
|
+
errorEvent = event
|
|
152
|
+
})
|
|
107
153
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
154
|
+
capture.init().render()
|
|
155
|
+
|
|
156
|
+
assert.ok(errorEvent)
|
|
157
|
+
assert.deepStrictEqual(capture.querySelector('output').innerHTML, '')
|
|
158
|
+
})
|
|
159
|
+
|
|
160
|
+
it('emits error when template evaluation fails at runtime', () => {
|
|
161
|
+
setup()
|
|
162
|
+
const holder = document.createElement('div')
|
|
163
|
+
holder.innerHTML = `
|
|
164
|
+
<ark-capture>
|
|
165
|
+
<data>{"name":"John"}</data>
|
|
166
|
+
<template>\${this.profile.name}</template>
|
|
167
|
+
<output></output>
|
|
168
|
+
</ark-capture>
|
|
169
|
+
`
|
|
170
|
+
const capture = holder.querySelector('ark-capture')
|
|
171
|
+
let errorEvent = null
|
|
172
|
+
capture.addEventListener('error', (event) => {
|
|
173
|
+
errorEvent = event
|
|
111
174
|
})
|
|
175
|
+
|
|
176
|
+
capture.init().render()
|
|
177
|
+
|
|
178
|
+
assert.ok(errorEvent)
|
|
179
|
+
assert.deepStrictEqual(capture.querySelector('output').innerHTML, '')
|
|
112
180
|
})
|
|
@@ -6,10 +6,21 @@ import './droparea.js'
|
|
|
6
6
|
const tag = 'ark-droparea-preview'
|
|
7
7
|
|
|
8
8
|
export class DropareaPreview extends Component {
|
|
9
|
+
constructor () {
|
|
10
|
+
super()
|
|
11
|
+
this._objectUrls = new Map()
|
|
12
|
+
this._onDragEnd = this.handleDrop.bind(this)
|
|
13
|
+
}
|
|
14
|
+
|
|
9
15
|
init (_context = {}) {
|
|
10
16
|
return super.init()
|
|
11
17
|
}
|
|
12
18
|
|
|
19
|
+
disconnectedCallback () {
|
|
20
|
+
this.revokeAllFiles()
|
|
21
|
+
super.disconnectedCallback()
|
|
22
|
+
}
|
|
23
|
+
|
|
13
24
|
render () {
|
|
14
25
|
this.content = /* html */ `
|
|
15
26
|
<ul data-preview-list class="ark-droparea-preview__list drag-sort-enable"></ul>
|
|
@@ -18,7 +29,7 @@ export class DropareaPreview extends Component {
|
|
|
18
29
|
}
|
|
19
30
|
|
|
20
31
|
previewFile (file) {
|
|
21
|
-
const blobUrl =
|
|
32
|
+
const blobUrl = this.getObjectURL(file)
|
|
22
33
|
const fileType = file.type.split('/')[0]
|
|
23
34
|
const previewZone = this.select('[data-preview-list]')
|
|
24
35
|
const picture = document.createElement('li')
|
|
@@ -28,7 +39,9 @@ export class DropareaPreview extends Component {
|
|
|
28
39
|
removeButton.className = 'ark-droparea__remove'
|
|
29
40
|
|
|
30
41
|
if (fileType != 'image') {
|
|
31
|
-
|
|
42
|
+
const text = document.createElement('p')
|
|
43
|
+
text.textContent = file.name
|
|
44
|
+
picture.appendChild(text)
|
|
32
45
|
picture.setAttribute('data', `${blobUrl}`)
|
|
33
46
|
} else {
|
|
34
47
|
picture.style.backgroundImage = `url('${blobUrl}')`
|
|
@@ -68,9 +81,12 @@ export class DropareaPreview extends Component {
|
|
|
68
81
|
}
|
|
69
82
|
|
|
70
83
|
enableDragItem (item) {
|
|
84
|
+
if (item.hasAttribute('data-drag-enabled')) return
|
|
85
|
+
|
|
86
|
+
item.setAttribute('data-drag-enabled', '')
|
|
71
87
|
item.setAttribute('draggable', true)
|
|
72
88
|
item.addEventListener('drag', this.handleDrag.bind(this, item))
|
|
73
|
-
item.addEventListener('dragend', this.
|
|
89
|
+
item.addEventListener('dragend', this._onDragEnd, false)
|
|
74
90
|
}
|
|
75
91
|
|
|
76
92
|
/* istanbul ignore next */
|
|
@@ -94,10 +110,12 @@ export class DropareaPreview extends Component {
|
|
|
94
110
|
}
|
|
95
111
|
}
|
|
96
112
|
|
|
97
|
-
handleDrop (
|
|
98
|
-
const droparea =
|
|
113
|
+
handleDrop (event) {
|
|
114
|
+
const droparea = event.target.closest('ark-droparea')
|
|
115
|
+
if (!droparea) return
|
|
116
|
+
|
|
99
117
|
droparea.preview.createNewFileList()
|
|
100
|
-
|
|
118
|
+
event.target.classList.remove('drag-sort-active')
|
|
101
119
|
droparea.preview.dispatchAlterEvent()
|
|
102
120
|
}
|
|
103
121
|
/* ---------------------------------------------------- */
|
|
@@ -120,9 +138,41 @@ export class DropareaPreview extends Component {
|
|
|
120
138
|
return this.files.some((item) => item.name === file.name)
|
|
121
139
|
}
|
|
122
140
|
|
|
141
|
+
getObjectURL (file) {
|
|
142
|
+
if (this._objectUrls.has(file)) return this._objectUrls.get(file)
|
|
143
|
+
|
|
144
|
+
const url = URL.createObjectURL(file)
|
|
145
|
+
this._objectUrls.set(file, url)
|
|
146
|
+
return url
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
revokeFile (file) {
|
|
150
|
+
const url = this._objectUrls.get(file)
|
|
151
|
+
if (!url) return
|
|
152
|
+
|
|
153
|
+
this._objectUrls.delete(file)
|
|
154
|
+
URL.revokeObjectURL?.(url)
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
revokeAllFiles () {
|
|
158
|
+
for (const url of this._objectUrls.values()) {
|
|
159
|
+
URL.revokeObjectURL?.(url)
|
|
160
|
+
}
|
|
161
|
+
this._objectUrls.clear()
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
clearPreview () {
|
|
165
|
+
const previewZone = this.select('[data-preview-list]')
|
|
166
|
+
previewZone && (previewZone.textContent = '')
|
|
167
|
+
this.toggleVisibility()
|
|
168
|
+
}
|
|
169
|
+
|
|
123
170
|
removeFile (file, event) {
|
|
124
171
|
const element = event.target
|
|
125
172
|
const fileIndex = this.droparea.fileList.indexOf(file)
|
|
173
|
+
if (fileIndex < 0) return
|
|
174
|
+
|
|
175
|
+
this.revokeFile(file)
|
|
126
176
|
this.droparea.fileList.splice(fileIndex, 1)
|
|
127
177
|
element.parentNode.remove()
|
|
128
178
|
this.selectAll('li').forEach((item, index) =>
|
|
@@ -137,7 +187,7 @@ export class DropareaPreview extends Component {
|
|
|
137
187
|
}
|
|
138
188
|
|
|
139
189
|
get droparea () {
|
|
140
|
-
return /** @type {Droparea} */ (this.closest('
|
|
190
|
+
return /** @type {Droparea} */ (this.closest('ark-droparea'))
|
|
141
191
|
}
|
|
142
192
|
|
|
143
193
|
get mediaList () {
|
|
@@ -147,7 +197,7 @@ export class DropareaPreview extends Component {
|
|
|
147
197
|
name: file.name,
|
|
148
198
|
type: file.type,
|
|
149
199
|
size: file.size,
|
|
150
|
-
url:
|
|
200
|
+
url: this.getObjectURL(file)
|
|
151
201
|
})
|
|
152
202
|
})
|
|
153
203
|
return mediaList
|