@knowark/componarkjs 1.13.3 → 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.
Files changed (177) hide show
  1. package/lib/base/component/component.js +17 -1
  2. package/lib/base/component/component.test.js +475 -389
  3. package/lib/base/utils/define.js +28 -6
  4. package/lib/base/utils/define.test.js +129 -42
  5. package/lib/base/utils/format.test.js +16 -16
  6. package/lib/base/utils/helpers.js +11 -4
  7. package/lib/base/utils/helpers.test.js +134 -115
  8. package/lib/base/utils/slots.test.js +38 -38
  9. package/lib/base/utils/uuid.test.js +13 -13
  10. package/lib/components/audio/components/audio.js +22 -3
  11. package/lib/components/audio/components/audio.test.js +120 -90
  12. package/lib/components/camera/components/camera.js +8 -3
  13. package/lib/components/camera/components/camera.test.js +96 -91
  14. package/lib/components/capture/components/capture.js +33 -5
  15. package/lib/components/capture/components/capture.test.js +165 -97
  16. package/lib/components/droparea/components/droparea-preview.js +66 -15
  17. package/lib/components/droparea/components/droparea-preview.test.js +262 -78
  18. package/lib/components/droparea/components/droparea.js +47 -8
  19. package/lib/components/droparea/components/droparea.test.js +309 -298
  20. package/lib/components/emit/components/emit.js +24 -4
  21. package/lib/components/emit/components/emit.test.js +192 -134
  22. package/lib/components/index.js +1 -1
  23. package/lib/components/list/components/{list.item.js → item.js} +1 -1
  24. package/lib/components/list/components/item.test.js +70 -69
  25. package/lib/components/list/components/list.js +35 -5
  26. package/lib/components/list/components/list.test.js +358 -227
  27. package/lib/components/list/index.js +1 -1
  28. package/lib/components/paginator/components/paginator.js +3 -2
  29. package/lib/components/paginator/components/paginator.test.js +146 -143
  30. package/lib/components/spinner/components/spinner.js +1 -1
  31. package/lib/components/spinner/components/spinner.test.js +36 -41
  32. package/lib/components/splitview/components/splitview.detail.js +1 -1
  33. package/lib/components/splitview/components/splitview.detail.test.js +78 -74
  34. package/lib/components/splitview/components/splitview.js +40 -10
  35. package/lib/components/splitview/components/splitview.master.js +29 -3
  36. package/lib/components/splitview/components/splitview.master.test.js +52 -52
  37. package/lib/components/splitview/components/splitview.test.js +136 -32
  38. package/lib/components/translate/components/translate.js +32 -10
  39. package/lib/components/translate/components/translate.test.js +492 -133
  40. package/package.json +7 -27
  41. package/scripts/node-test-setup.js +94 -0
  42. package/showcase/components/index.html +1 -1
  43. package/{jsconfig.json → tsconfig.json} +6 -4
  44. package/types/base/component/component.d.ts +48 -0
  45. package/types/base/component/component.d.ts.map +1 -0
  46. package/types/base/component/component.test.d.ts +2 -0
  47. package/types/base/component/component.test.d.ts.map +1 -0
  48. package/types/base/component/index.d.ts +8 -0
  49. package/types/base/component/index.d.ts.map +1 -0
  50. package/types/base/index.d.ts +2 -0
  51. package/types/base/index.d.ts.map +1 -0
  52. package/types/base/styles/index.d.ts +3 -0
  53. package/types/base/styles/index.d.ts.map +1 -0
  54. package/types/base/styles/styles.d.ts +3 -0
  55. package/types/base/styles/styles.d.ts.map +1 -0
  56. package/types/base/utils/define.d.ts +5 -0
  57. package/types/base/utils/define.d.ts.map +1 -0
  58. package/types/base/utils/define.test.d.ts +2 -0
  59. package/types/base/utils/define.test.d.ts.map +1 -0
  60. package/types/base/utils/format.d.ts +13 -0
  61. package/types/base/utils/format.d.ts.map +1 -0
  62. package/types/base/utils/format.test.d.ts +2 -0
  63. package/types/base/utils/format.test.d.ts.map +1 -0
  64. package/types/base/utils/helpers.d.ts +11 -0
  65. package/types/base/utils/helpers.d.ts.map +1 -0
  66. package/types/base/utils/helpers.test.d.ts +2 -0
  67. package/types/base/utils/helpers.test.d.ts.map +1 -0
  68. package/types/base/utils/index.d.ts +6 -0
  69. package/types/base/utils/index.d.ts.map +1 -0
  70. package/types/base/utils/slots.d.ts +15 -0
  71. package/types/base/utils/slots.d.ts.map +1 -0
  72. package/types/base/utils/slots.test.d.ts +2 -0
  73. package/types/base/utils/slots.test.d.ts.map +1 -0
  74. package/types/base/utils/uuid.d.ts +3 -0
  75. package/types/base/utils/uuid.d.ts.map +1 -0
  76. package/types/base/utils/uuid.test.d.ts +2 -0
  77. package/types/base/utils/uuid.test.d.ts.map +1 -0
  78. package/types/components/audio/components/audio.d.ts +18 -0
  79. package/types/components/audio/components/audio.d.ts.map +1 -0
  80. package/types/components/audio/components/audio.test.d.ts +2 -0
  81. package/types/components/audio/components/audio.test.d.ts.map +1 -0
  82. package/types/components/audio/index.d.ts +2 -0
  83. package/types/components/audio/index.d.ts.map +1 -0
  84. package/types/components/audio/styles/ark.css.d.ts +3 -0
  85. package/types/components/audio/styles/ark.css.d.ts.map +1 -0
  86. package/types/components/audio/styles/index.d.ts +3 -0
  87. package/types/components/audio/styles/index.d.ts.map +1 -0
  88. package/types/components/camera/components/camera.d.ts +18 -0
  89. package/types/components/camera/components/camera.d.ts.map +1 -0
  90. package/types/components/camera/components/camera.test.d.ts +2 -0
  91. package/types/components/camera/components/camera.test.d.ts.map +1 -0
  92. package/types/components/camera/index.d.ts +2 -0
  93. package/types/components/camera/index.d.ts.map +1 -0
  94. package/types/components/camera/styles/ark.css.d.ts +3 -0
  95. package/types/components/camera/styles/ark.css.d.ts.map +1 -0
  96. package/types/components/camera/styles/index.d.ts +3 -0
  97. package/types/components/camera/styles/index.d.ts.map +1 -0
  98. package/types/components/capture/components/capture.d.ts +10 -0
  99. package/types/components/capture/components/capture.d.ts.map +1 -0
  100. package/types/components/capture/components/capture.test.d.ts +2 -0
  101. package/types/components/capture/components/capture.test.d.ts.map +1 -0
  102. package/types/components/capture/index.d.ts +2 -0
  103. package/types/components/capture/index.d.ts.map +1 -0
  104. package/types/components/droparea/components/droparea-preview.d.ts +21 -0
  105. package/types/components/droparea/components/droparea-preview.d.ts.map +1 -0
  106. package/types/components/droparea/components/droparea-preview.test.d.ts +2 -0
  107. package/types/components/droparea/components/droparea-preview.test.d.ts.map +1 -0
  108. package/types/components/droparea/components/droparea.d.ts +32 -0
  109. package/types/components/droparea/components/droparea.d.ts.map +1 -0
  110. package/types/components/droparea/components/droparea.test.d.ts +2 -0
  111. package/types/components/droparea/components/droparea.test.d.ts.map +1 -0
  112. package/types/components/droparea/index.d.ts +2 -0
  113. package/types/components/droparea/index.d.ts.map +1 -0
  114. package/types/components/droparea/styles/ark.css.d.ts +3 -0
  115. package/types/components/droparea/styles/ark.css.d.ts.map +1 -0
  116. package/types/components/droparea/styles/index.d.ts +3 -0
  117. package/types/components/droparea/styles/index.d.ts.map +1 -0
  118. package/types/components/emit/components/emit.d.ts +10 -0
  119. package/types/components/emit/components/emit.d.ts.map +1 -0
  120. package/types/components/emit/components/emit.test.d.ts +2 -0
  121. package/types/components/emit/components/emit.test.d.ts.map +1 -0
  122. package/types/components/emit/index.d.ts +2 -0
  123. package/types/components/emit/index.d.ts.map +1 -0
  124. package/types/components/index.d.ts +10 -0
  125. package/types/components/index.d.ts.map +1 -0
  126. package/types/components/list/components/item.d.ts +8 -0
  127. package/types/components/list/components/item.d.ts.map +1 -0
  128. package/types/components/list/components/item.test.d.ts +2 -0
  129. package/types/components/list/components/item.test.d.ts.map +1 -0
  130. package/types/components/list/components/list.d.ts +13 -0
  131. package/types/components/list/components/list.d.ts.map +1 -0
  132. package/types/components/list/components/list.test.d.ts +2 -0
  133. package/types/components/list/components/list.test.d.ts.map +1 -0
  134. package/types/components/list/index.d.ts +3 -0
  135. package/types/components/list/index.d.ts.map +1 -0
  136. package/types/components/paginator/components/paginator.d.ts +32 -0
  137. package/types/components/paginator/components/paginator.d.ts.map +1 -0
  138. package/types/components/paginator/components/paginator.test.d.ts +2 -0
  139. package/types/components/paginator/components/paginator.test.d.ts.map +1 -0
  140. package/types/components/paginator/index.d.ts +2 -0
  141. package/types/components/paginator/index.d.ts.map +1 -0
  142. package/types/components/paginator/styles/ark.css.d.ts +3 -0
  143. package/types/components/paginator/styles/ark.css.d.ts.map +1 -0
  144. package/types/components/paginator/styles/index.d.ts +3 -0
  145. package/types/components/paginator/styles/index.d.ts.map +1 -0
  146. package/types/components/spinner/components/spinner.d.ts +11 -0
  147. package/types/components/spinner/components/spinner.d.ts.map +1 -0
  148. package/types/components/spinner/components/spinner.test.d.ts +2 -0
  149. package/types/components/spinner/components/spinner.test.d.ts.map +1 -0
  150. package/types/components/spinner/index.d.ts +2 -0
  151. package/types/components/spinner/index.d.ts.map +1 -0
  152. package/types/components/spinner/styles/ark.css.d.ts +3 -0
  153. package/types/components/spinner/styles/ark.css.d.ts.map +1 -0
  154. package/types/components/spinner/styles/index.d.ts +3 -0
  155. package/types/components/spinner/styles/index.d.ts.map +1 -0
  156. package/types/components/splitview/components/splitview.d.ts +12 -0
  157. package/types/components/splitview/components/splitview.d.ts.map +1 -0
  158. package/types/components/splitview/components/splitview.detail.d.ts +10 -0
  159. package/types/components/splitview/components/splitview.detail.d.ts.map +1 -0
  160. package/types/components/splitview/components/splitview.detail.test.d.ts +2 -0
  161. package/types/components/splitview/components/splitview.detail.test.d.ts.map +1 -0
  162. package/types/components/splitview/components/splitview.master.d.ts +8 -0
  163. package/types/components/splitview/components/splitview.master.d.ts.map +1 -0
  164. package/types/components/splitview/components/splitview.master.test.d.ts +2 -0
  165. package/types/components/splitview/components/splitview.master.test.d.ts.map +1 -0
  166. package/types/components/splitview/components/splitview.test.d.ts +2 -0
  167. package/types/components/splitview/components/splitview.test.d.ts.map +1 -0
  168. package/types/components/splitview/index.d.ts +4 -0
  169. package/types/components/splitview/index.d.ts.map +1 -0
  170. package/types/components/translate/components/translate.d.ts +18 -0
  171. package/types/components/translate/components/translate.d.ts.map +1 -0
  172. package/types/components/translate/components/translate.test.d.ts +2 -0
  173. package/types/components/translate/components/translate.test.d.ts.map +1 -0
  174. package/types/components/translate/index.d.ts +2 -0
  175. package/types/components/translate/index.d.ts.map +1 -0
  176. package/types/index.d.ts +3 -0
  177. package/types/index.d.ts.map +1 -0
@@ -1,4 +1,4 @@
1
- import { Component } from '../../../base/component/index.js'
1
+ import { Component } from "#base/index.js"
2
2
 
3
3
  const tag = 'ark-emit'
4
4
  export class Emit extends Component {
@@ -20,10 +20,9 @@ export class Emit extends Component {
20
20
 
21
21
  let data = null
22
22
  if (this.bind && this.source) {
23
- const element = this.closest(this.bind)
24
- data = Function(`return ${this.source.trim()}`).call(element)
23
+ data = this._resolveBoundData()
25
24
  } else if (this.source) {
26
- data = JSON.parse(this.source)
25
+ data = this._parseJSON(this.source)
27
26
  }
28
27
 
29
28
  Object.assign(detail, data)
@@ -40,5 +39,26 @@ export class Emit extends Component {
40
39
  element?.remove()
41
40
  return element
42
41
  }
42
+
43
+ _resolveBoundData () {
44
+ const element = this.closest(this.bind)
45
+ if (!element) return null
46
+
47
+ try {
48
+ return Function(`return ${this.source.trim()}`).call(element)
49
+ } catch (error) {
50
+ this.emit('error', error)
51
+ return null
52
+ }
53
+ }
54
+
55
+ _parseJSON (source) {
56
+ try {
57
+ return JSON.parse(source)
58
+ } catch (error) {
59
+ this.emit('error', error)
60
+ return null
61
+ }
62
+ }
43
63
  }
44
64
  Component.define(tag, Emit)
@@ -1,169 +1,227 @@
1
+ import { it } from 'node:test';
2
+ import assert from 'node:assert/strict';
1
3
  import './emit.js'
2
4
 
3
- describe('Emit', () => {
4
- let container = null
5
+ let container = null
5
6
 
6
- beforeEach(() => {
7
- container = document.createElement('div')
8
- document.body.appendChild(container)
9
- })
7
+ const setup = () => {
8
+ document.body.innerHTML = '';
9
+ container = document.createElement('div')
10
+ document.body.appendChild(container)
11
+ };
10
12
 
11
- afterEach(() => {
12
- container.remove()
13
- container = null
14
- })
13
+ it('can be instantiated', () => {
14
+ setup();
15
+ container.innerHTML = `
16
+ <ark-emit></ark-emit>
17
+ `
15
18
 
16
- it('can be instantiated', () => {
17
- container.innerHTML = `
18
- <ark-emit></ark-emit>
19
- `
19
+ const emit = container.querySelector('ark-emit')
20
+ assert.deepStrictEqual(emit, emit.init())
21
+ })
20
22
 
21
- const emit = container.querySelector('ark-emit')
22
- expect(emit).toEqual(emit.init())
23
- })
23
+ it('emits a target event when handling the one listened at', () => {
24
+ setup();
25
+ container.innerHTML = `
26
+ <ark-emit receive="click" dispatch="custom">
27
+ <button>Sending a click event when pressed!</button>
28
+ </ark-emit>
29
+ `
30
+ const emit = container.querySelector('ark-emit')
31
+ let customCalled = false
32
+ emit.addEventListener('custom', (event) => { customCalled = true })
24
33
 
25
- it('emits a target event when handling the one listened at', () => {
26
- container.innerHTML = `
27
- <ark-emit receive="click" dispatch="custom">
28
- <button>Sending a click event when pressed!</button>
29
- </ark-emit>
30
- `
31
- const emit = container.querySelector('ark-emit')
32
- let customCalled = false
33
- emit.addEventListener('custom', (event) => { customCalled = true })
34
+ container.querySelector('button').click()
34
35
 
35
- container.querySelector('button').click()
36
+ assert.strictEqual(customCalled, true)
37
+ })
36
38
 
37
- expect(customCalled).toBe(true)
38
- })
39
+ it('listens to click events and dispatches emit events by default', () => {
40
+ setup();
41
+ container.innerHTML = `
42
+ <ark-emit>
43
+ <button>Sending a click event when pressed!</button>
44
+ </ark-emit>
45
+ `
46
+ const emit = container.querySelector('ark-emit')
47
+ let emitCalled = false
48
+ emit.addEventListener('emit', (event) => { emitCalled = true })
39
49
 
40
- it('listens to click events and dispatches emit events by default', () => {
41
- container.innerHTML = `
42
- <ark-emit>
43
- <button>Sending a click event when pressed!</button>
44
- </ark-emit>
45
- `
46
- const emit = container.querySelector('ark-emit')
47
- let emitCalled = false
48
- emit.addEventListener('emit', (event) => { emitCalled = true })
50
+ container.querySelector('button').click()
49
51
 
50
- container.querySelector('button').click()
52
+ assert.strictEqual(emitCalled, true)
53
+ })
51
54
 
52
- expect(emitCalled).toBe(true)
55
+ it('it carries over the json data given to it', () => {
56
+ setup();
57
+ const data = {
58
+ id: '7a792bda-6f8a-44ed-a63a-a48bba1e76bf',
59
+ name: 'John Doe'
60
+ }
61
+ container.innerHTML = `
62
+ <ark-emit>
63
+ <data>${JSON.stringify(data)}</data>
64
+ <button>Sending a click event when pressed!</button>
65
+ </ark-emit>
66
+ `
67
+
68
+ const emit = container.querySelector('ark-emit')
69
+
70
+ const dataElement = emit.querySelector('data')
71
+ assert.strictEqual(dataElement, null)
72
+
73
+ emit.addEventListener('emit', (event) => {
74
+ const detail = event.detail
75
+ assert.deepStrictEqual(detail, data)
53
76
  })
54
77
 
55
- it('it carries over the json data given to it', () => {
56
- expect.assertions(2)
57
- const data = {
58
- id: '7a792bda-6f8a-44ed-a63a-a48bba1e76bf',
59
- name: 'John Doe'
60
- }
61
- container.innerHTML = `
62
- <ark-emit>
78
+ container.querySelector('button').click()
79
+ })
80
+
81
+ it('it merges upstream event details', () => {
82
+ setup();
83
+ const data = {
84
+ id: '7a792bda-6f8a-44ed-a63a-a48bba1e76bf',
85
+ name: 'John Doe'
86
+ }
87
+ container.innerHTML = `
88
+ <ark-emit data-outer receive="inner" dispatch="outer">
89
+ <data>
90
+ {
91
+ "age": 34,
92
+ "job": "programmer"
93
+ }
94
+ </data>
95
+ <ark-emit data-inner dispatch="inner">
63
96
  <data>${JSON.stringify(data)}</data>
64
97
  <button>Sending a click event when pressed!</button>
65
98
  </ark-emit>
66
- `
67
-
68
- const emit = container.querySelector('ark-emit')
99
+ </ark-emit>
100
+ `
69
101
 
70
- const dataElement = emit.querySelector('data')
71
- expect(dataElement).toBe(null)
72
-
73
- emit.addEventListener('emit', (event) => {
74
- const detail = event.detail
75
- expect(detail).toEqual(data)
102
+ const emit = container.querySelector('[data-outer]')
103
+ emit.addEventListener('outer', (event) => {
104
+ const detail = event.detail
105
+ assert.deepStrictEqual(detail, {
106
+ id: '7a792bda-6f8a-44ed-a63a-a48bba1e76bf',
107
+ name: 'John Doe',
108
+ age: 34,
109
+ job: 'programmer'
76
110
  })
111
+ })
112
+
113
+ container.querySelector('[data-inner]').click()
114
+ })
77
115
 
78
- container.querySelector('button').click()
116
+ it('receives the target.value of regular events', async () => {
117
+ setup();
118
+ container.innerHTML = `
119
+ <ark-emit receive="change">
120
+ <input type="text"></input>
121
+ </ark-emit>
122
+ `
123
+ const input = container.querySelector('input')
124
+ const inputEvent = new Event('change', { bubbles: true })
125
+ const target = { name: 'input', value: 'XYZ' }
126
+ Object.defineProperty(
127
+ inputEvent, 'target', { writable: false, value: target })
128
+
129
+ const emit = container.querySelector('ark-emit')
130
+ emit.addEventListener('emit', (event) => {
131
+ const detail = event.detail
132
+ assert.deepStrictEqual(detail, { value: 'XYZ' })
79
133
  })
80
134
 
81
- it('it merges upstream event details', () => {
82
- expect.assertions(1)
83
- const data = {
84
- id: '7a792bda-6f8a-44ed-a63a-a48bba1e76bf',
85
- name: 'John Doe'
86
- }
87
- container.innerHTML = `
88
- <ark-emit data-outer receive="inner" dispatch="outer">
89
- <data>
90
- {
91
- "age": 34,
92
- "job": "programmer"
93
- }
94
- </data>
95
- <ark-emit data-inner dispatch="inner">
96
- <data>${JSON.stringify(data)}</data>
135
+ input.dispatchEvent(inputEvent)
136
+ })
137
+
138
+ it('binds to the given ancestor referenced by a selector', async () => {
139
+ setup();
140
+ container.innerHTML = `
141
+ <div class="grandparent" data-name="John", data-surname="Doe">
142
+ <div class="parent">
143
+ <ark-emit bind=".grandparent">
144
+ <data>
145
+ {
146
+ name: this.dataset.name,
147
+ surname: this.dataset.surname
148
+ }
149
+ </data>
97
150
  <button>Sending a click event when pressed!</button>
98
151
  </ark-emit>
99
- </ark-emit>
100
- `
101
-
102
- const emit = container.querySelector('[data-outer]')
103
- emit.addEventListener('outer', (event) => {
104
- const detail = event.detail
105
- expect(detail).toEqual({
106
- id: '7a792bda-6f8a-44ed-a63a-a48bba1e76bf',
107
- name: 'John Doe',
108
- age: 34,
109
- job: 'programmer'
110
- })
152
+ </div>
153
+ </div>
154
+ `
155
+
156
+ const emit = container.querySelector('ark-emit')
157
+ emit.addEventListener('emit', (event) => {
158
+ const { detail } = event
159
+ assert.deepStrictEqual(detail, {
160
+ name: 'John',
161
+ surname: 'Doe'
111
162
  })
163
+ })
164
+
165
+ container.querySelector('button').click()
166
+ })
112
167
 
113
- container.querySelector('[data-inner]').click()
168
+ it('emits error when given invalid JSON data', () => {
169
+ setup()
170
+ container.innerHTML = `
171
+ <ark-emit>
172
+ <data>{ invalid json }</data>
173
+ <button>Sending a click event when pressed!</button>
174
+ </ark-emit>
175
+ `
176
+ const emit = container.querySelector('ark-emit')
177
+ let errorEvent = null
178
+ emit.addEventListener('error', (event) => {
179
+ errorEvent = event
114
180
  })
115
181
 
116
- it('receives the target.value of regular events', async () => {
117
- expect.assertions(1)
182
+ container.querySelector('button').click()
118
183
 
119
- container.innerHTML = `
120
- <ark-emit receive="change">
121
- <input type="text"></input>
122
- </ark-emit>
123
- `
124
- const input = container.querySelector('input')
125
- const inputEvent = new Event('change', { bubbles: true })
126
- const target = { name: 'input', value: 'XYZ' }
127
- Object.defineProperty(
128
- inputEvent, 'target', { writable: false, value: target })
129
-
130
- const emit = container.querySelector('ark-emit')
131
- emit.addEventListener('emit', (event) => {
132
- const detail = event.detail
133
- expect(detail).toEqual({ value: 'XYZ' })
134
- })
184
+ assert.ok(errorEvent)
185
+ })
135
186
 
136
- input.dispatchEvent(inputEvent)
187
+ it('emits error when bound source expression is invalid', () => {
188
+ setup()
189
+ container.innerHTML = `
190
+ <div class="grandparent">
191
+ <ark-emit bind=".grandparent">
192
+ <data>{ invalid:</data>
193
+ <button>Send</button>
194
+ </ark-emit>
195
+ </div>
196
+ `
197
+ const emit = container.querySelector('ark-emit')
198
+ let errorEvent = null
199
+ emit.addEventListener('error', (event) => {
200
+ errorEvent = event
137
201
  })
138
202
 
139
- it('binds to the given ancestor referenced by a selector', async () => {
140
- expect.assertions(1)
141
-
142
- container.innerHTML = `
143
- <div class="grandparent" data-name="John", data-surname="Doe">
144
- <div class="parent">
145
- <ark-emit bind=".grandparent">
146
- <data>
147
- {
148
- name: this.dataset.name,
149
- surname: this.dataset.surname
150
- }
151
- </data>
152
- <button>Sending a click event when pressed!</button>
153
- </ark-emit>
154
- </div>
155
- </div>
156
- `
157
-
158
- const emit = container.querySelector('ark-emit')
159
- emit.addEventListener('emit', (event) => {
160
- const { detail } = event
161
- expect(detail).toEqual({
162
- name: 'John',
163
- surname: 'Doe'
164
- })
165
- })
203
+ container.querySelector('button').click()
166
204
 
167
- container.querySelector('button').click()
205
+ assert.ok(errorEvent)
206
+ })
207
+
208
+ it('ignores bound expressions when the ancestor selector does not match', () => {
209
+ setup()
210
+ container.innerHTML = `
211
+ <div class="parent">
212
+ <ark-emit bind=".missing">
213
+ <data>{ value: 'A' }</data>
214
+ <button>Send</button>
215
+ </ark-emit>
216
+ </div>
217
+ `
218
+ const emit = container.querySelector('ark-emit')
219
+ let detail = null
220
+ emit.addEventListener('emit', (event) => {
221
+ detail = event.detail
168
222
  })
223
+
224
+ container.querySelector('button').click()
225
+
226
+ assert.deepStrictEqual(detail, {})
169
227
  })
@@ -6,4 +6,4 @@ export * from './list/index.js'
6
6
  export * from './paginator/index.js'
7
7
  export * from './spinner/index.js'
8
8
  export * from './splitview/index.js'
9
- export * from './translate/index.js'
9
+ export * from './translate/index.js'
@@ -1,4 +1,4 @@
1
- import { Component } from '../../../base/component/index.js'
1
+ import { Component } from "#base/index.js"
2
2
 
3
3
  const tag = 'ark-list-item'
4
4
  export class ListItem extends Component {
@@ -1,91 +1,92 @@
1
+ import { it } from 'node:test';
2
+ import assert from 'node:assert/strict';
1
3
  import './list.js'
2
- import { ListItem } from './list.item.js'
4
+ import { ListItem } from './item.js'
3
5
 
4
- describe('List item', () => {
5
- let container = null
6
+ let container = null
6
7
 
7
- beforeEach(() => {
8
- container = document.createElement('div')
9
- document.body.appendChild(container)
10
- })
11
-
12
- afterEach(() => {
13
- container.remove()
14
- container = null
15
- })
8
+ const setup = () => {
9
+ document.body.innerHTML = '';
10
+ container = document.createElement('div')
11
+ document.body.appendChild(container)
12
+ };
16
13
 
17
- it('can be instantiated', () => {
18
- container.innerHTML = `
19
- <ark-list></ark-list>
20
- `
14
+ it('can be instantiated', () => {
15
+ setup();
16
+ container.innerHTML = `
17
+ <ark-list></ark-list>
18
+ `
21
19
 
22
- const list = container.querySelector('ark-list')
23
- list.source = ['Colombia', 'Uruguay', 'Brasil', 'Perú']
24
- list.render()
25
- const item = list.querySelector('ark-list-item')
20
+ const list = container.querySelector('ark-list')
21
+ list.source = ['Colombia', 'Uruguay', 'Brasil', 'Perú']
22
+ list.render()
23
+ const item = list.querySelector('ark-list-item')
26
24
 
27
- expect(item).toEqual(item.init())
28
- })
25
+ assert.deepStrictEqual(item, item.init())
26
+ })
29
27
 
30
- it('can be rendered with data', () => {
31
- container.innerHTML = `
32
- <ark-list></ark-list>
33
- `
28
+ it('can be rendered with data', () => {
29
+ setup();
30
+ container.innerHTML = `
31
+ <ark-list></ark-list>
32
+ `
34
33
 
35
- const list = container.querySelector('ark-list')
36
- list.source = ['Colombia']
37
- list.render()
38
- const item = list.querySelector('ark-list-item')
34
+ const list = container.querySelector('ark-list')
35
+ list.source = ['Colombia']
36
+ list.render()
37
+ const item = list.querySelector('ark-list-item')
39
38
 
40
- item.data = 'my data'
41
- item.render()
39
+ item.data = 'my data'
40
+ item.render()
42
41
 
43
- expect(item.innerHTML.trim()).toEqual('my data')
44
- })
42
+ assert.deepStrictEqual(item.innerHTML.trim(), 'my data')
43
+ })
45
44
 
46
- it('can be rendered with template', () => {
47
- container.innerHTML = `
48
- <ark-list data-template-list></ark-list>
49
- `
45
+ it('can be rendered with template', () => {
46
+ setup();
47
+ container.innerHTML = `
48
+ <ark-list data-template-list></ark-list>
49
+ `
50
50
 
51
- const list = container.querySelector('[data-template-list]')
52
- list.source = ['Colombia']
53
- list.render()
54
- const item = list.querySelector('ark-list-item')
51
+ const list = container.querySelector('[data-template-list]')
52
+ list.source = ['Colombia']
53
+ list.render()
54
+ const item = list.querySelector('ark-list-item')
55
55
 
56
- item.data = 'my data'
57
- item.template = data => /* html */ `<span>${data}</span>`
58
- item.render()
56
+ item.data = 'my data'
57
+ item.template = data => /* html */ `<span>${data}</span>`
58
+ item.render()
59
59
 
60
- expect(item.innerHTML.trim()).toEqual('<span>my data</span>')
61
- })
60
+ assert.deepStrictEqual(item.innerHTML.trim(), '<span>my data</span>')
61
+ })
62
62
 
63
- it('can be rendered with template', () => {
64
- container.innerHTML = `
65
- <ark-list data-template-list></ark-list>
66
- `
63
+ it('can be rendered with template', () => {
64
+ setup();
65
+ container.innerHTML = `
66
+ <ark-list data-template-list></ark-list>
67
+ `
67
68
 
68
- const list = container.querySelector('[data-template-list]')
69
- list.source = ['Colombia']
70
- list.render()
71
- const item = list.querySelector('ark-list-item')
69
+ const list = container.querySelector('[data-template-list]')
70
+ list.source = ['Colombia']
71
+ list.render()
72
+ const item = list.querySelector('ark-list-item')
72
73
 
73
- item.data = 'my data'
74
- item.template = data => /* html */ `<span>${data}</span>`
75
- item.render()
74
+ item.data = 'my data'
75
+ item.template = data => /* html */ `<span>${data}</span>`
76
+ item.render()
76
77
 
77
- item.addEventListener('list-item:selected', event => {
78
- expect(event.detail.data).toEqual('my data')
79
- })
80
- item.click()
78
+ item.addEventListener('list-item:selected', event => {
79
+ assert.deepStrictEqual(event.detail.data, 'my data')
81
80
  })
81
+ item.click()
82
+ })
82
83
 
83
- it('can be rendered without template', () => {
84
- const item = new ListItem()
85
- item.init({
86
- data: 'my data'
87
- }).render()
84
+ it('can be rendered without template', () => {
85
+ setup();
86
+ const item = new ListItem()
87
+ item.init({
88
+ data: 'my data'
89
+ }).render()
88
90
 
89
- expect(item.innerHTML.trim()).toEqual('my data')
90
- })
91
+ assert.deepStrictEqual(item.innerHTML.trim(), 'my data')
91
92
  })
@@ -1,5 +1,5 @@
1
- import { Component } from '../../../base/component/index.js'
2
- import { ListItem } from './list.item.js'
1
+ import { Component } from '#base/index.js'
2
+ import { ListItem } from './item.js'
3
3
 
4
4
  const tag = 'ark-list'
5
5
 
@@ -20,15 +20,16 @@ export class List extends Component {
20
20
 
21
21
  render () {
22
22
  const listData = this.select('data')
23
- const list = JSON.parse(listData?.textContent || null)
23
+ const list = this._parseJSON(listData?.textContent)
24
24
  const source = list || this.source
25
+ const sourceList = Array.isArray(source) ? source : []
25
26
 
26
27
  const itemTemplate = (this.select('template'))?.innerHTML
27
28
  this.template = itemTemplate ? this._format(itemTemplate) : this.template
28
29
 
29
30
  this.content = ''
30
31
 
31
- source.forEach((data, index) => {
32
+ sourceList.forEach((data, index) => {
32
33
  const item = new ListItem()
33
34
 
34
35
  if (this.hasAttribute('click-disabled')) {
@@ -59,7 +60,24 @@ export class List extends Component {
59
60
  }
60
61
 
61
62
  _format (template) {
62
- return (data) => Function(`return \`${template}\``).call(data)
63
+ let render = null
64
+
65
+ try {
66
+ render = Function(`return \`${template}\``)
67
+ } catch (error) {
68
+ this.emit('error', error)
69
+ }
70
+
71
+ return (data) => {
72
+ if (!render) return ''
73
+
74
+ try {
75
+ return render.call(data)
76
+ } catch (error) {
77
+ this.emit('error', error)
78
+ return ''
79
+ }
80
+ }
63
81
  }
64
82
 
65
83
  /** @param {MouseEvent} event */
@@ -89,8 +107,20 @@ export class List extends Component {
89
107
 
90
108
  const target = /** @type {HTMLElement} */ (event.target)
91
109
  const item = /** @type {ListItem} */ (target.closest('ark-list-item'))
110
+ if (!item) return
92
111
 
93
112
  this.delete(Number(item.index))
94
113
  }
114
+
115
+ _parseJSON (source) {
116
+ if (!source) return null
117
+
118
+ try {
119
+ return JSON.parse(source)
120
+ } catch (error) {
121
+ this.emit('error', error)
122
+ return null
123
+ }
124
+ }
95
125
  }
96
126
  Component.define(tag, List)