@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.
- 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 +22 -3
- package/lib/components/audio/components/audio.test.js +120 -90
- package/lib/components/camera/components/camera.js +8 -3
- package/lib/components/camera/components/camera.test.js +96 -91
- package/lib/components/capture/components/capture.js +33 -5
- package/lib/components/capture/components/capture.test.js +165 -97
- package/lib/components/droparea/components/droparea-preview.js +66 -15
- package/lib/components/droparea/components/droparea-preview.test.js +262 -78
- package/lib/components/droparea/components/droparea.js +47 -8
- package/lib/components/droparea/components/droparea.test.js +309 -298
- package/lib/components/emit/components/emit.js +24 -4
- package/lib/components/emit/components/emit.test.js +192 -134
- package/lib/components/index.js +1 -1
- package/lib/components/list/components/{list.item.js → item.js} +1 -1
- package/lib/components/list/components/item.test.js +70 -69
- package/lib/components/list/components/list.js +35 -5
- package/lib/components/list/components/list.test.js +358 -227
- package/lib/components/list/index.js +1 -1
- package/lib/components/paginator/components/paginator.js +3 -2
- package/lib/components/paginator/components/paginator.test.js +146 -143
- package/lib/components/spinner/components/spinner.js +1 -1
- package/lib/components/spinner/components/spinner.test.js +36 -41
- package/lib/components/splitview/components/splitview.detail.js +1 -1
- package/lib/components/splitview/components/splitview.detail.test.js +78 -74
- package/lib/components/splitview/components/splitview.js +40 -10
- package/lib/components/splitview/components/splitview.master.js +29 -3
- package/lib/components/splitview/components/splitview.master.test.js +52 -52
- package/lib/components/splitview/components/splitview.test.js +136 -32
- package/lib/components/translate/components/translate.js +32 -10
- package/lib/components/translate/components/translate.test.js +492 -133
- package/package.json +7 -27
- package/scripts/node-test-setup.js +94 -0
- package/showcase/components/index.html +1 -1
- package/{jsconfig.json → tsconfig.json} +6 -4
- package/types/base/component/component.d.ts +48 -0
- package/types/base/component/component.d.ts.map +1 -0
- package/types/base/component/component.test.d.ts +2 -0
- package/types/base/component/component.test.d.ts.map +1 -0
- package/types/base/component/index.d.ts +8 -0
- package/types/base/component/index.d.ts.map +1 -0
- package/types/base/index.d.ts +2 -0
- package/types/base/index.d.ts.map +1 -0
- package/types/base/styles/index.d.ts +3 -0
- package/types/base/styles/index.d.ts.map +1 -0
- package/types/base/styles/styles.d.ts +3 -0
- package/types/base/styles/styles.d.ts.map +1 -0
- package/types/base/utils/define.d.ts +5 -0
- package/types/base/utils/define.d.ts.map +1 -0
- package/types/base/utils/define.test.d.ts +2 -0
- package/types/base/utils/define.test.d.ts.map +1 -0
- package/types/base/utils/format.d.ts +13 -0
- package/types/base/utils/format.d.ts.map +1 -0
- package/types/base/utils/format.test.d.ts +2 -0
- package/types/base/utils/format.test.d.ts.map +1 -0
- package/types/base/utils/helpers.d.ts +11 -0
- package/types/base/utils/helpers.d.ts.map +1 -0
- package/types/base/utils/helpers.test.d.ts +2 -0
- package/types/base/utils/helpers.test.d.ts.map +1 -0
- package/types/base/utils/index.d.ts +6 -0
- package/types/base/utils/index.d.ts.map +1 -0
- package/types/base/utils/slots.d.ts +15 -0
- package/types/base/utils/slots.d.ts.map +1 -0
- package/types/base/utils/slots.test.d.ts +2 -0
- package/types/base/utils/slots.test.d.ts.map +1 -0
- package/types/base/utils/uuid.d.ts +3 -0
- package/types/base/utils/uuid.d.ts.map +1 -0
- package/types/base/utils/uuid.test.d.ts +2 -0
- package/types/base/utils/uuid.test.d.ts.map +1 -0
- package/types/components/audio/components/audio.d.ts +18 -0
- package/types/components/audio/components/audio.d.ts.map +1 -0
- package/types/components/audio/components/audio.test.d.ts +2 -0
- package/types/components/audio/components/audio.test.d.ts.map +1 -0
- package/types/components/audio/index.d.ts +2 -0
- package/types/components/audio/index.d.ts.map +1 -0
- package/types/components/audio/styles/ark.css.d.ts +3 -0
- package/types/components/audio/styles/ark.css.d.ts.map +1 -0
- package/types/components/audio/styles/index.d.ts +3 -0
- package/types/components/audio/styles/index.d.ts.map +1 -0
- package/types/components/camera/components/camera.d.ts +18 -0
- package/types/components/camera/components/camera.d.ts.map +1 -0
- package/types/components/camera/components/camera.test.d.ts +2 -0
- package/types/components/camera/components/camera.test.d.ts.map +1 -0
- package/types/components/camera/index.d.ts +2 -0
- package/types/components/camera/index.d.ts.map +1 -0
- package/types/components/camera/styles/ark.css.d.ts +3 -0
- package/types/components/camera/styles/ark.css.d.ts.map +1 -0
- package/types/components/camera/styles/index.d.ts +3 -0
- package/types/components/camera/styles/index.d.ts.map +1 -0
- package/types/components/capture/components/capture.d.ts +10 -0
- package/types/components/capture/components/capture.d.ts.map +1 -0
- package/types/components/capture/components/capture.test.d.ts +2 -0
- package/types/components/capture/components/capture.test.d.ts.map +1 -0
- package/types/components/capture/index.d.ts +2 -0
- package/types/components/capture/index.d.ts.map +1 -0
- package/types/components/droparea/components/droparea-preview.d.ts +21 -0
- package/types/components/droparea/components/droparea-preview.d.ts.map +1 -0
- package/types/components/droparea/components/droparea-preview.test.d.ts +2 -0
- package/types/components/droparea/components/droparea-preview.test.d.ts.map +1 -0
- package/types/components/droparea/components/droparea.d.ts +32 -0
- package/types/components/droparea/components/droparea.d.ts.map +1 -0
- package/types/components/droparea/components/droparea.test.d.ts +2 -0
- package/types/components/droparea/components/droparea.test.d.ts.map +1 -0
- package/types/components/droparea/index.d.ts +2 -0
- package/types/components/droparea/index.d.ts.map +1 -0
- package/types/components/droparea/styles/ark.css.d.ts +3 -0
- package/types/components/droparea/styles/ark.css.d.ts.map +1 -0
- package/types/components/droparea/styles/index.d.ts +3 -0
- package/types/components/droparea/styles/index.d.ts.map +1 -0
- package/types/components/emit/components/emit.d.ts +10 -0
- package/types/components/emit/components/emit.d.ts.map +1 -0
- package/types/components/emit/components/emit.test.d.ts +2 -0
- package/types/components/emit/components/emit.test.d.ts.map +1 -0
- package/types/components/emit/index.d.ts +2 -0
- package/types/components/emit/index.d.ts.map +1 -0
- package/types/components/index.d.ts +10 -0
- package/types/components/index.d.ts.map +1 -0
- package/types/components/list/components/item.d.ts +8 -0
- package/types/components/list/components/item.d.ts.map +1 -0
- package/types/components/list/components/item.test.d.ts +2 -0
- package/types/components/list/components/item.test.d.ts.map +1 -0
- package/types/components/list/components/list.d.ts +13 -0
- package/types/components/list/components/list.d.ts.map +1 -0
- package/types/components/list/components/list.test.d.ts +2 -0
- package/types/components/list/components/list.test.d.ts.map +1 -0
- package/types/components/list/index.d.ts +3 -0
- package/types/components/list/index.d.ts.map +1 -0
- package/types/components/paginator/components/paginator.d.ts +32 -0
- package/types/components/paginator/components/paginator.d.ts.map +1 -0
- package/types/components/paginator/components/paginator.test.d.ts +2 -0
- package/types/components/paginator/components/paginator.test.d.ts.map +1 -0
- package/types/components/paginator/index.d.ts +2 -0
- package/types/components/paginator/index.d.ts.map +1 -0
- package/types/components/paginator/styles/ark.css.d.ts +3 -0
- package/types/components/paginator/styles/ark.css.d.ts.map +1 -0
- package/types/components/paginator/styles/index.d.ts +3 -0
- package/types/components/paginator/styles/index.d.ts.map +1 -0
- package/types/components/spinner/components/spinner.d.ts +11 -0
- package/types/components/spinner/components/spinner.d.ts.map +1 -0
- package/types/components/spinner/components/spinner.test.d.ts +2 -0
- package/types/components/spinner/components/spinner.test.d.ts.map +1 -0
- package/types/components/spinner/index.d.ts +2 -0
- package/types/components/spinner/index.d.ts.map +1 -0
- package/types/components/spinner/styles/ark.css.d.ts +3 -0
- package/types/components/spinner/styles/ark.css.d.ts.map +1 -0
- package/types/components/spinner/styles/index.d.ts +3 -0
- package/types/components/spinner/styles/index.d.ts.map +1 -0
- package/types/components/splitview/components/splitview.d.ts +12 -0
- package/types/components/splitview/components/splitview.d.ts.map +1 -0
- package/types/components/splitview/components/splitview.detail.d.ts +10 -0
- package/types/components/splitview/components/splitview.detail.d.ts.map +1 -0
- package/types/components/splitview/components/splitview.detail.test.d.ts +2 -0
- package/types/components/splitview/components/splitview.detail.test.d.ts.map +1 -0
- package/types/components/splitview/components/splitview.master.d.ts +8 -0
- package/types/components/splitview/components/splitview.master.d.ts.map +1 -0
- package/types/components/splitview/components/splitview.master.test.d.ts +2 -0
- package/types/components/splitview/components/splitview.master.test.d.ts.map +1 -0
- package/types/components/splitview/components/splitview.test.d.ts +2 -0
- package/types/components/splitview/components/splitview.test.d.ts.map +1 -0
- package/types/components/splitview/index.d.ts +4 -0
- package/types/components/splitview/index.d.ts.map +1 -0
- package/types/components/translate/components/translate.d.ts +18 -0
- package/types/components/translate/components/translate.d.ts.map +1 -0
- package/types/components/translate/components/translate.test.d.ts +2 -0
- package/types/components/translate/components/translate.test.d.ts.map +1 -0
- package/types/components/translate/index.d.ts +2 -0
- package/types/components/translate/index.d.ts.map +1 -0
- package/types/index.d.ts +3 -0
- package/types/index.d.ts.map +1 -0
package/lib/base/utils/define.js
CHANGED
|
@@ -1,20 +1,42 @@
|
|
|
1
1
|
// @ts-nocheck
|
|
2
2
|
|
|
3
|
+
const stylesheetRegistry = new Map()
|
|
4
|
+
const fallbackRegistry = new Map()
|
|
5
|
+
|
|
3
6
|
/** @param {string} tag
|
|
4
7
|
* @param {CustomElementConstructor} element
|
|
5
8
|
* @param {string} styles **/
|
|
6
9
|
export function define (tag, element, styles = '') {
|
|
7
|
-
globalThis.customElements.
|
|
10
|
+
const definedElement = globalThis.customElements.get(tag)
|
|
11
|
+
if (!definedElement) {
|
|
12
|
+
globalThis.customElements.define(tag, element)
|
|
13
|
+
}
|
|
8
14
|
if (!styles?.trim()) return
|
|
15
|
+
if (typeof document === 'undefined') return
|
|
9
16
|
|
|
10
17
|
try {
|
|
11
|
-
|
|
18
|
+
let sheet = stylesheetRegistry.get(tag)
|
|
19
|
+
if (!sheet) {
|
|
20
|
+
sheet = new globalThis.CSSStyleSheet()
|
|
21
|
+
stylesheetRegistry.set(tag, sheet)
|
|
22
|
+
}
|
|
12
23
|
sheet.replaceSync(styles)
|
|
13
|
-
|
|
14
|
-
|
|
24
|
+
|
|
25
|
+
const adopted = document.adoptedStyleSheets || []
|
|
26
|
+
if (!adopted.includes(sheet)) {
|
|
27
|
+
document.adoptedStyleSheets = [...adopted, sheet]
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return sheet
|
|
15
31
|
} catch (error) {
|
|
16
|
-
|
|
32
|
+
let style = fallbackRegistry.get(tag)
|
|
33
|
+
if (!style) {
|
|
34
|
+
style = document.createElement('style')
|
|
35
|
+
style.setAttribute('data-componark-tag', tag)
|
|
36
|
+
fallbackRegistry.set(tag, style)
|
|
37
|
+
document.head.appendChild(style)
|
|
38
|
+
}
|
|
17
39
|
style.textContent = styles
|
|
18
|
-
|
|
40
|
+
return style
|
|
19
41
|
}
|
|
20
42
|
}
|
|
@@ -1,62 +1,149 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { it, mock } from 'node:test'
|
|
2
|
+
import assert from 'node:assert/strict'
|
|
2
3
|
import { define } from './define.js'
|
|
3
4
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
define('new-element', NewElement)
|
|
5
|
+
it('can define a custome element', () => {
|
|
6
|
+
class NewElement extends globalThis.HTMLElement {}
|
|
7
|
+
define('new-element', NewElement)
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
const newElement = document.createElement('new-element')
|
|
10
|
+
assert.ok(newElement)
|
|
11
|
+
})
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
}
|
|
13
|
+
it('can define a custom element using constructable CSSStyleSheet', () => {
|
|
14
|
+
let definedStyles = null
|
|
15
|
+
class MockCSSStyleSheet extends globalThis.CSSStyleSheet {
|
|
16
|
+
replaceSync (styles) {
|
|
17
|
+
definedStyles = styles
|
|
19
18
|
}
|
|
19
|
+
}
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
body {
|
|
27
|
-
color: red;
|
|
21
|
+
const cssStyleSheetSpy = mock.method(
|
|
22
|
+
globalThis,
|
|
23
|
+
'CSSStyleSheet',
|
|
24
|
+
function () {
|
|
25
|
+
return new MockCSSStyleSheet()
|
|
28
26
|
}
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
class CSSStyledElement extends globalThis.HTMLElement {}
|
|
30
|
+
const styles = `
|
|
31
|
+
body {
|
|
32
|
+
color: red;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
div {
|
|
36
|
+
margin: 5px;
|
|
37
|
+
}
|
|
38
|
+
`
|
|
39
|
+
|
|
40
|
+
define('css-styled-element', CSSStyledElement, styles)
|
|
29
41
|
|
|
30
|
-
|
|
31
|
-
|
|
42
|
+
const styledElement = document.createElement('css-styled-element')
|
|
43
|
+
assert.ok(styledElement)
|
|
44
|
+
|
|
45
|
+
assert.deepStrictEqual(styles, definedStyles)
|
|
46
|
+
cssStyleSheetSpy.mock.restore()
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
it('can define a custom element using an style fallback element', () => {
|
|
50
|
+
const cssStyleSheetSpy = mock.method(
|
|
51
|
+
globalThis,
|
|
52
|
+
'CSSStyleSheet',
|
|
53
|
+
function () {
|
|
54
|
+
throw new Error('Constructable stylesheets are unavailable')
|
|
32
55
|
}
|
|
33
|
-
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
class StyledElement extends globalThis.HTMLElement {}
|
|
59
|
+
const styles = `
|
|
60
|
+
body {
|
|
61
|
+
color: red;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
div {
|
|
65
|
+
margin: 5px;
|
|
66
|
+
}
|
|
67
|
+
`
|
|
68
|
+
|
|
69
|
+
define('styled-element', StyledElement, styles)
|
|
70
|
+
cssStyleSheetSpy.mock.restore()
|
|
34
71
|
|
|
35
|
-
|
|
72
|
+
const styledElement = document.createElement('styled-element')
|
|
73
|
+
assert.ok(styledElement)
|
|
74
|
+
const style = Array.from(document.head.querySelectorAll('style')).find(
|
|
75
|
+
(item) => item.textContent.includes('color: red;')
|
|
76
|
+
)
|
|
77
|
+
assert.ok(style)
|
|
78
|
+
})
|
|
36
79
|
|
|
37
|
-
|
|
38
|
-
|
|
80
|
+
it('does not throw when defining an already defined custom element', () => {
|
|
81
|
+
class DuplicateElement extends globalThis.HTMLElement {}
|
|
82
|
+
define('duplicate-element', DuplicateElement)
|
|
39
83
|
|
|
40
|
-
|
|
84
|
+
assert.doesNotThrow(() => {
|
|
85
|
+
define('duplicate-element', DuplicateElement)
|
|
41
86
|
})
|
|
87
|
+
})
|
|
42
88
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
89
|
+
it('reuses fallback styles for repeated definitions of the same tag', () => {
|
|
90
|
+
const cssStyleSheetSpy = mock.method(
|
|
91
|
+
globalThis,
|
|
92
|
+
'CSSStyleSheet',
|
|
93
|
+
function () {
|
|
94
|
+
throw new Error('Constructable stylesheets are unavailable')
|
|
48
95
|
}
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
class ReusedStyledElement extends globalThis.HTMLElement {}
|
|
99
|
+
|
|
100
|
+
define('reused-styled-element', ReusedStyledElement, 'body { color: red; }')
|
|
101
|
+
define('reused-styled-element', ReusedStyledElement, 'body { color: blue; }')
|
|
102
|
+
|
|
103
|
+
cssStyleSheetSpy.mock.restore()
|
|
104
|
+
|
|
105
|
+
const styles = Array.from(
|
|
106
|
+
document.head.querySelectorAll('style[data-componark-tag="reused-styled-element"]')
|
|
107
|
+
)
|
|
108
|
+
assert.deepStrictEqual(styles.length, 1)
|
|
109
|
+
assert.ok(styles[0].textContent.includes('color: blue;'))
|
|
110
|
+
})
|
|
49
111
|
|
|
50
|
-
|
|
51
|
-
|
|
112
|
+
it('does not add a constructable stylesheet more than once for the same tag', () => {
|
|
113
|
+
class MockCSSStyleSheet extends globalThis.CSSStyleSheet {
|
|
114
|
+
replaceSync (_styles) {}
|
|
115
|
+
}
|
|
116
|
+
const cssStyleSheetSpy = mock.method(
|
|
117
|
+
globalThis,
|
|
118
|
+
'CSSStyleSheet',
|
|
119
|
+
function () {
|
|
120
|
+
return new MockCSSStyleSheet()
|
|
52
121
|
}
|
|
53
|
-
|
|
122
|
+
)
|
|
123
|
+
class OnceStyledElement extends globalThis.HTMLElement {}
|
|
54
124
|
|
|
55
|
-
|
|
125
|
+
const beforeCount = document.adoptedStyleSheets.length
|
|
126
|
+
define('once-styled-element', OnceStyledElement, 'body { color: orange; }')
|
|
127
|
+
const firstCount = document.adoptedStyleSheets.length
|
|
128
|
+
define('once-styled-element', OnceStyledElement, 'body { color: green; }')
|
|
129
|
+
const secondCount = document.adoptedStyleSheets.length
|
|
56
130
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
131
|
+
cssStyleSheetSpy.mock.restore()
|
|
132
|
+
assert.deepStrictEqual(firstCount, beforeCount + 1)
|
|
133
|
+
assert.deepStrictEqual(secondCount, firstCount)
|
|
134
|
+
})
|
|
135
|
+
|
|
136
|
+
it('returns early when styles are provided but document is unavailable', () => {
|
|
137
|
+
const previousDocument = globalThis.document
|
|
138
|
+
class NoDocumentElement extends globalThis.HTMLElement {}
|
|
139
|
+
|
|
140
|
+
delete globalThis.document
|
|
141
|
+
|
|
142
|
+
try {
|
|
143
|
+
assert.doesNotThrow(() => {
|
|
144
|
+
define('no-document-element', NoDocumentElement, 'body { color: red; }')
|
|
145
|
+
})
|
|
146
|
+
} finally {
|
|
147
|
+
globalThis.document = previousDocument
|
|
148
|
+
}
|
|
62
149
|
})
|
|
@@ -1,19 +1,19 @@
|
|
|
1
|
+
import { it } from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
1
3
|
import { camelToKebab, kebabToCamel, snakeToCamel } from './format.js'
|
|
2
4
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
expect(camel).toBe('myVariable')
|
|
18
|
-
})
|
|
5
|
+
it('can convert camel to kebab', () => {
|
|
6
|
+
const camel = 'myVariable'
|
|
7
|
+
const kebab = camelToKebab(camel)
|
|
8
|
+
assert.strictEqual(kebab, 'my-variable')
|
|
9
|
+
})
|
|
10
|
+
it('can convert kebab to camel', () => {
|
|
11
|
+
const kebab = 'my-variable'
|
|
12
|
+
const camel = kebabToCamel(kebab)
|
|
13
|
+
assert.strictEqual(camel, 'myVariable')
|
|
14
|
+
})
|
|
15
|
+
it('can convert snake to camel', () => {
|
|
16
|
+
const kebab = 'my_variable'
|
|
17
|
+
const camel = snakeToCamel(kebab)
|
|
18
|
+
assert.strictEqual(camel, 'myVariable')
|
|
19
19
|
})
|
|
@@ -25,8 +25,11 @@ export function listen (self) {
|
|
|
25
25
|
if (pipe?.toLocaleLowerCase() === 'object') {
|
|
26
26
|
return set(this, objectPath.trim(), event.detail)
|
|
27
27
|
}
|
|
28
|
-
|
|
29
|
-
|
|
28
|
+
const inputValue = (
|
|
29
|
+
get(event, eventPath, undefined) ||
|
|
30
|
+
get(event, 'detail', '')
|
|
31
|
+
)
|
|
32
|
+
set(this, objectPath.trim(), transform(pipe, inputValue))
|
|
30
33
|
}
|
|
31
34
|
}
|
|
32
35
|
|
|
@@ -102,6 +105,7 @@ function transform (pipe, value) {
|
|
|
102
105
|
/** @param {object} object @param {string} path @param {any} value */
|
|
103
106
|
export function set (object, path, value) {
|
|
104
107
|
const pathArray = path.match(/([^[.\]])+/g)
|
|
108
|
+
if (!pathArray?.length) return
|
|
105
109
|
|
|
106
110
|
pathArray.reduce((accumulator, key, index) => {
|
|
107
111
|
if (accumulator[key.trim()] === undefined) accumulator[key.trim()] = {}
|
|
@@ -113,9 +117,12 @@ export function set (object, path, value) {
|
|
|
113
117
|
/** @param {object} object @param {string} path @param {any} fallback */
|
|
114
118
|
export function get (object, path, fallback) {
|
|
115
119
|
const pathArray = path.match(/([^[.\]])+/g)
|
|
120
|
+
if (!pathArray?.length) return fallback
|
|
116
121
|
|
|
117
|
-
|
|
118
|
-
accumulator[key.trim()], object)
|
|
122
|
+
const value = pathArray.reduce((accumulator, key) => accumulator &&
|
|
123
|
+
accumulator[key.trim()], object)
|
|
124
|
+
|
|
125
|
+
return value === undefined ? fallback : value
|
|
119
126
|
}
|
|
120
127
|
|
|
121
128
|
/** @param {object} object @return {string} */
|
|
@@ -1,154 +1,173 @@
|
|
|
1
|
+
import { it } from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
1
3
|
import { listen, reflect, set, get, keys } from './helpers.js'
|
|
2
4
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
`
|
|
10
|
-
|
|
11
|
-
listen(element)
|
|
12
|
-
|
|
13
|
-
element.querySelector('button').click()
|
|
14
|
-
expect(!element.hasAttribute('clicked-element')).toBeTruthy()
|
|
15
|
-
})
|
|
16
|
-
|
|
17
|
-
it('does not allow invalid attribute', () => {
|
|
18
|
-
const element = document.createElement('div')
|
|
19
|
-
element.innerHTML = /* html */`
|
|
20
|
-
<button listen ark-on-click="myMethod"></button>
|
|
21
|
-
`
|
|
5
|
+
it('does not allow invalid attribute', () => {
|
|
6
|
+
const element = document.createElement('div')
|
|
7
|
+
element.innerHTML = /* html */`
|
|
8
|
+
<button on-open="click" listen on-click="click" on-click="myMethod"
|
|
9
|
+
on-close="click"></button>
|
|
10
|
+
`
|
|
22
11
|
|
|
23
|
-
|
|
12
|
+
listen(element)
|
|
24
13
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
14
|
+
element.querySelector('button').click()
|
|
15
|
+
assert.ok(!element.hasAttribute('clicked-element'))
|
|
16
|
+
})
|
|
17
|
+
|
|
18
|
+
it('does not allow invalid attribute', () => {
|
|
19
|
+
const element = document.createElement('div')
|
|
20
|
+
element.innerHTML = /* html */`
|
|
21
|
+
<button listen ark-on-click="myMethod"></button>
|
|
22
|
+
`
|
|
23
|
+
|
|
24
|
+
listen(element)
|
|
25
|
+
|
|
26
|
+
element.querySelector('button').click()
|
|
27
|
+
assert.ok(!element.hasAttribute('clicked-element'))
|
|
28
|
+
})
|
|
28
29
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
30
|
+
it('attribute ', () => {
|
|
31
|
+
const button = document.createElement('button')
|
|
32
|
+
button.setAttribute('listen', '')
|
|
33
|
+
button.setAttribute('on-abc', 'method')
|
|
34
|
+
button.setAttribute('on-xyz', 'method')
|
|
34
35
|
|
|
35
|
-
|
|
36
|
-
|
|
36
|
+
const content = document.createElement('div')
|
|
37
|
+
content.appendChild(button)
|
|
37
38
|
|
|
38
|
-
|
|
39
|
-
|
|
39
|
+
listen(content)
|
|
40
|
+
})
|
|
40
41
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
42
|
+
it('It does not allow to execute undeclared methods.', () => {
|
|
43
|
+
const element = document.createElement('div')
|
|
44
|
+
element.innerHTML = /* html */`
|
|
45
|
+
<button listen on-click="myMethod"></button>
|
|
46
|
+
`
|
|
46
47
|
|
|
47
|
-
|
|
48
|
+
listen(element)
|
|
48
49
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
50
|
+
element.querySelector('button').click()
|
|
51
|
+
assert.ok(!element.hasAttribute('clicked-element'))
|
|
52
|
+
})
|
|
52
53
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
54
|
+
it('can listen events', () => {
|
|
55
|
+
const element = document.createElement('div')
|
|
56
|
+
Object.defineProperty(element, 'binding', {value: 'listen'})
|
|
57
|
+
element.innerHTML = /* html */`
|
|
58
|
+
<button listen on-click="myMethod"></button>
|
|
59
|
+
`
|
|
60
|
+
// @ts-ignore
|
|
61
|
+
element.myMethod = function () {
|
|
62
|
+
element.setAttribute('clicked-element', '')
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
listen(element)
|
|
66
|
+
|
|
67
|
+
element.querySelector('button').click()
|
|
68
|
+
assert.ok(element.hasAttribute('clicked-element'))
|
|
69
|
+
})
|
|
63
70
|
|
|
64
|
-
|
|
71
|
+
it('ignores missing methods when listening', () => {
|
|
72
|
+
const element = document.createElement('div')
|
|
73
|
+
Object.defineProperty(element, 'binding', {value: 'listen'})
|
|
74
|
+
element.innerHTML = /* html */`
|
|
75
|
+
<button listen on-click="missing"></button>
|
|
76
|
+
`
|
|
77
|
+
// @ts-ignore
|
|
78
|
+
element.myMethod = function () {
|
|
79
|
+
element.setAttribute('clicked-element', '')
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
listen(element)
|
|
83
|
+
|
|
84
|
+
element.querySelector('button').click()
|
|
85
|
+
assert.ok(!element.hasAttribute('clicked-element'))
|
|
86
|
+
})
|
|
65
87
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
88
|
+
it('can create attribute', () => {
|
|
89
|
+
const element = document.createElement('div')
|
|
90
|
+
const properties = ['myProperty']
|
|
69
91
|
|
|
70
|
-
|
|
71
|
-
const element = document.createElement('div')
|
|
72
|
-
element.binding = 'listen'
|
|
73
|
-
element.innerHTML = /* html */`
|
|
74
|
-
<button listen on-click="missing"></button>
|
|
75
|
-
`
|
|
76
|
-
// @ts-ignore
|
|
77
|
-
element.myMethod = function () {
|
|
78
|
-
element.setAttribute('clicked-element', '')
|
|
79
|
-
}
|
|
92
|
+
reflect(element, properties)
|
|
80
93
|
|
|
81
|
-
|
|
94
|
+
// @ts-ignore
|
|
95
|
+
element.myProperty = 'value'
|
|
82
96
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
97
|
+
// @ts-ignore
|
|
98
|
+
assert.strictEqual(element.myProperty, 'value')
|
|
99
|
+
assert.ok(element.hasAttribute('my-property'))
|
|
100
|
+
})
|
|
86
101
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
102
|
+
it('cannot create attribute with property undefined', () => {
|
|
103
|
+
const element = document.createElement('div')
|
|
104
|
+
const properties = ['myProperty']
|
|
90
105
|
|
|
91
|
-
|
|
106
|
+
reflect(element, properties)
|
|
92
107
|
|
|
93
|
-
|
|
94
|
-
|
|
108
|
+
// @ts-ignore
|
|
109
|
+
element.myProperty = undefined
|
|
95
110
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
111
|
+
// @ts-ignore
|
|
112
|
+
assert.strictEqual(element.myProperty, '')
|
|
113
|
+
assert.ok(!element.hasAttribute('my-property'))
|
|
114
|
+
})
|
|
100
115
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
const properties = ['myProperty']
|
|
116
|
+
it('sets an object properties by a given path', () => {
|
|
117
|
+
const object = {}
|
|
104
118
|
|
|
105
|
-
|
|
119
|
+
set(object, 'value.data', 'Hello')
|
|
106
120
|
|
|
107
|
-
|
|
108
|
-
|
|
121
|
+
assert.deepStrictEqual(object.value.data, 'Hello')
|
|
122
|
+
})
|
|
109
123
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
})
|
|
124
|
+
it('ignores set paths that cannot be parsed', () => {
|
|
125
|
+
const object = { value: 7 }
|
|
126
|
+
set(object, '', 'Hello')
|
|
127
|
+
assert.deepStrictEqual(object, { value: 7 })
|
|
128
|
+
})
|
|
114
129
|
|
|
115
|
-
|
|
116
|
-
|
|
130
|
+
it('gets an object properties by a given path', () => {
|
|
131
|
+
const object = { state: { data: { value: 25 } }, data: 13 }
|
|
117
132
|
|
|
118
|
-
|
|
133
|
+
let value = get(object, 'data')
|
|
119
134
|
|
|
120
|
-
|
|
121
|
-
})
|
|
135
|
+
assert.deepStrictEqual(value, 13)
|
|
122
136
|
|
|
123
|
-
|
|
124
|
-
const object = { state: { data: { value: 25 } }, data: 13 }
|
|
137
|
+
value = get(object, 'state.data.value')
|
|
125
138
|
|
|
126
|
-
|
|
139
|
+
assert.deepStrictEqual(value, 25)
|
|
127
140
|
|
|
128
|
-
|
|
141
|
+
const fallback = get(object, 'state.missing.value', 7)
|
|
129
142
|
|
|
130
|
-
|
|
143
|
+
assert.deepStrictEqual(fallback, 7)
|
|
144
|
+
})
|
|
131
145
|
|
|
132
|
-
|
|
146
|
+
it('gets falsy values by a given path without replacing them', () => {
|
|
147
|
+
const object = { state: { count: 0, enabled: false, empty: '' } }
|
|
133
148
|
|
|
134
|
-
|
|
149
|
+
assert.deepStrictEqual(get(object, 'state.count', 7), 0)
|
|
150
|
+
assert.deepStrictEqual(get(object, 'state.enabled', true), false)
|
|
151
|
+
assert.deepStrictEqual(get(object, 'state.empty', 'fallback'), '')
|
|
152
|
+
})
|
|
135
153
|
|
|
136
|
-
|
|
137
|
-
}
|
|
154
|
+
it('returns fallback when get path cannot be parsed', () => {
|
|
155
|
+
const object = { value: 7 }
|
|
156
|
+
assert.deepStrictEqual(get(object, '', 'fallback'), 'fallback')
|
|
157
|
+
})
|
|
138
158
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
159
|
+
it('retrieves the object keys of truthy values', () => {
|
|
160
|
+
const background = 'primary'
|
|
161
|
+
const shadow = 'small'
|
|
162
|
+
const color = ''
|
|
143
163
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
164
|
+
const classes = {
|
|
165
|
+
[`background-${background}`]: background,
|
|
166
|
+
[`color-${color}`]: color,
|
|
167
|
+
[`shadow-${shadow}`]: shadow
|
|
168
|
+
}
|
|
149
169
|
|
|
150
|
-
|
|
170
|
+
const result = keys(classes)
|
|
151
171
|
|
|
152
|
-
|
|
153
|
-
})
|
|
172
|
+
assert.deepStrictEqual(result, 'background-primary shadow-small')
|
|
154
173
|
})
|