@knowark/componarkjs 1.13.4 → 1.14.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (118) hide show
  1. package/README.md +57 -45
  2. package/lib/base/component/component.js +142 -20
  3. package/lib/base/component/component.test.js +753 -374
  4. package/lib/base/component/index.js +3 -0
  5. package/lib/base/styles/index.js +4 -1
  6. package/lib/base/utils/define.js +30 -7
  7. package/lib/base/utils/define.test.js +129 -42
  8. package/lib/base/utils/format.js +12 -6
  9. package/lib/base/utils/format.test.js +16 -16
  10. package/lib/base/utils/helpers.js +42 -9
  11. package/lib/base/utils/helpers.test.js +134 -115
  12. package/lib/base/utils/index.js +1 -0
  13. package/lib/base/utils/slots.js +3 -2
  14. package/lib/base/utils/slots.test.js +38 -38
  15. package/lib/base/utils/uuid.js +1 -1
  16. package/lib/base/utils/uuid.test.js +13 -13
  17. package/lib/components/audio/components/audio.js +36 -3
  18. package/lib/components/audio/components/audio.test.js +120 -90
  19. package/lib/components/audio/index.js +1 -0
  20. package/lib/components/audio/styles/index.js +5 -1
  21. package/lib/components/camera/components/camera.js +15 -0
  22. package/lib/components/camera/components/camera.test.js +96 -91
  23. package/lib/components/camera/index.js +1 -0
  24. package/lib/components/camera/styles/index.js +5 -1
  25. package/lib/components/capture/components/capture.js +48 -4
  26. package/lib/components/capture/components/capture.test.js +165 -97
  27. package/lib/components/capture/index.js +1 -0
  28. package/lib/components/droparea/components/droparea-preview.js +114 -19
  29. package/lib/components/droparea/components/droparea-preview.test.js +344 -80
  30. package/lib/components/droparea/components/droparea.js +82 -6
  31. package/lib/components/droparea/components/droparea.test.js +309 -299
  32. package/lib/components/droparea/index.js +1 -0
  33. package/lib/components/droparea/styles/index.js +5 -1
  34. package/lib/components/emit/components/emit.js +34 -4
  35. package/lib/components/emit/components/emit.test.js +192 -134
  36. package/lib/components/emit/index.js +1 -0
  37. package/lib/components/index.js +2 -1
  38. package/lib/components/list/components/item.js +6 -0
  39. package/lib/components/list/components/item.test.js +69 -68
  40. package/lib/components/list/components/list.js +51 -7
  41. package/lib/components/list/components/list.test.js +358 -227
  42. package/lib/components/list/index.js +1 -0
  43. package/lib/components/paginator/components/paginator.js +34 -8
  44. package/lib/components/paginator/components/paginator.test.js +146 -143
  45. package/lib/components/paginator/index.js +1 -0
  46. package/lib/components/paginator/styles/index.js +5 -1
  47. package/lib/components/spinner/components/spinner.js +10 -0
  48. package/lib/components/spinner/components/spinner.test.js +36 -41
  49. package/lib/components/spinner/index.js +1 -0
  50. package/lib/components/spinner/styles/index.js +5 -1
  51. package/lib/components/splitview/components/splitview.detail.js +10 -1
  52. package/lib/components/splitview/components/splitview.detail.test.js +75 -73
  53. package/lib/components/splitview/components/splitview.js +54 -11
  54. package/lib/components/splitview/components/splitview.master.js +37 -2
  55. package/lib/components/splitview/components/splitview.master.test.js +52 -52
  56. package/lib/components/splitview/components/splitview.test.js +135 -31
  57. package/lib/components/splitview/index.js +1 -0
  58. package/lib/components/translate/components/translate.js +65 -14
  59. package/lib/components/translate/components/translate.test.js +658 -131
  60. package/lib/components/translate/index.js +1 -0
  61. package/lib/index.js +3 -0
  62. package/package.json +4 -27
  63. package/scripts/node-test-setup.js +94 -0
  64. package/tsconfig.json +1 -1
  65. package/types/base/component/component.d.ts +43 -8
  66. package/types/base/component/component.d.ts.map +1 -1
  67. package/types/base/component/index.d.ts +4 -6
  68. package/types/base/component/index.d.ts.map +1 -1
  69. package/types/base/styles/index.d.ts +3 -2
  70. package/types/base/styles/index.d.ts.map +1 -1
  71. package/types/base/utils/define.d.ts +3 -2
  72. package/types/base/utils/define.d.ts.map +1 -1
  73. package/types/base/utils/format.d.ts +12 -6
  74. package/types/base/utils/format.d.ts.map +1 -1
  75. package/types/base/utils/helpers.d.ts +27 -7
  76. package/types/base/utils/helpers.d.ts.map +1 -1
  77. package/types/base/utils/slots.d.ts +8 -10
  78. package/types/base/utils/slots.d.ts.map +1 -1
  79. package/types/base/utils/uuid.d.ts +1 -1
  80. package/types/base/utils/uuid.d.ts.map +1 -1
  81. package/types/components/audio/components/audio.d.ts +23 -9
  82. package/types/components/audio/components/audio.d.ts.map +1 -1
  83. package/types/components/audio/styles/index.d.ts +3 -2
  84. package/types/components/audio/styles/index.d.ts.map +1 -1
  85. package/types/components/camera/components/camera.d.ts +11 -3
  86. package/types/components/camera/components/camera.d.ts.map +1 -1
  87. package/types/components/camera/styles/index.d.ts +3 -2
  88. package/types/components/camera/styles/index.d.ts.map +1 -1
  89. package/types/components/capture/components/capture.d.ts +23 -3
  90. package/types/components/capture/components/capture.d.ts.map +1 -1
  91. package/types/components/droparea/components/droparea-preview.d.ts +64 -11
  92. package/types/components/droparea/components/droparea-preview.d.ts.map +1 -1
  93. package/types/components/droparea/components/droparea.d.ts +58 -13
  94. package/types/components/droparea/components/droparea.d.ts.map +1 -1
  95. package/types/components/droparea/styles/index.d.ts +3 -2
  96. package/types/components/droparea/styles/index.d.ts.map +1 -1
  97. package/types/components/emit/components/emit.d.ts +15 -3
  98. package/types/components/emit/components/emit.d.ts.map +1 -1
  99. package/types/components/list/components/item.d.ts +8 -1
  100. package/types/components/list/components/item.d.ts.map +1 -1
  101. package/types/components/list/components/list.d.ts +23 -5
  102. package/types/components/list/components/list.d.ts.map +1 -1
  103. package/types/components/paginator/components/paginator.d.ts +32 -8
  104. package/types/components/paginator/components/paginator.d.ts.map +1 -1
  105. package/types/components/paginator/styles/index.d.ts +3 -2
  106. package/types/components/paginator/styles/index.d.ts.map +1 -1
  107. package/types/components/spinner/components/spinner.d.ts +14 -3
  108. package/types/components/spinner/components/spinner.d.ts.map +1 -1
  109. package/types/components/spinner/styles/index.d.ts +3 -2
  110. package/types/components/spinner/styles/index.d.ts.map +1 -1
  111. package/types/components/splitview/components/splitview.d.ts +22 -4
  112. package/types/components/splitview/components/splitview.d.ts.map +1 -1
  113. package/types/components/splitview/components/splitview.detail.d.ts +12 -2
  114. package/types/components/splitview/components/splitview.detail.d.ts.map +1 -1
  115. package/types/components/splitview/components/splitview.master.d.ts +12 -1
  116. package/types/components/splitview/components/splitview.master.d.ts.map +1 -1
  117. package/types/components/translate/components/translate.d.ts +44 -10
  118. package/types/components/translate/components/translate.d.ts.map +1 -1
@@ -1,3 +1,5 @@
1
+ import { it } from 'node:test';
2
+ import assert from 'node:assert/strict';
1
3
  import { Component } from '#base/index.js'
2
4
  import './splitview.detail.js'
3
5
 
@@ -18,77 +20,77 @@ class MockMain extends Component {
18
20
  }
19
21
  Component.define('mock-main', MockMain)
20
22
 
21
- describe('SplitViewDetail', () => {
22
- let container = null
23
- beforeEach(() => {
24
- container = document.createElement('div')
25
- document.body.appendChild(container)
26
- })
27
-
28
- afterEach(() => {
29
- container.remove()
30
- container = null
31
- })
32
-
33
- it('can be instantiated', () => {
34
- container.innerHTML = `
35
- <ark-splitview-detail>
36
- </ark-splitview-detail>
37
- `
38
- const detail = container.querySelector('ark-splitview-detail')
39
- expect(detail).toBeTruthy()
40
-
41
- expect(detail).toBe(detail.init())
42
- })
43
-
44
- it('can be instantiated with an inner main Component', () => {
45
- container.innerHTML = /* html */`
46
- <ark-splitview-detail>
47
- <mock-main>MAIN CONTENT</mock-main>
48
- </ark-splitview-detail>
49
- `
50
- const detail = container.querySelector('ark-splitview-detail')
51
-
52
- expect(detail.firstElementChild.textContent).toEqual('MAIN CONTENT')
53
- })
54
-
55
- it('can initialize its main Component', () => {
56
- container.innerHTML = /* html */`
57
- <ark-splitview-detail>
58
- <mock-main></mock-main>
59
- </ark-splitview-detail>
60
- `
61
- const detail = container.querySelector('ark-splitview-detail')
62
-
63
- detail.init({ name: 'Servagro' }).render()
64
-
65
- expect(detail.firstElementChild.textContent).toEqual('Servagro')
66
- })
67
-
68
- it('can manipulate its hidden attribute', () => {
69
- container.innerHTML = /* html */`
70
- <ark-splitview-detail>
71
- <mock-main></mock-main>
72
- </ark-splitview-detail>
73
- `
74
- const detail = container.querySelector('ark-splitview-detail')
75
-
76
- detail.show()
77
- expect(detail.hasAttribute('hidden')).toBeFalsy()
78
-
79
- detail.hide()
80
- expect(detail.hasAttribute('hidden')).toBeTruthy()
81
- })
82
-
83
- it('listens to close events to hide itself', () => {
84
- container.innerHTML = /* html */`
85
- <ark-splitview-detail>
86
- <mock-main></mock-main>
87
- </ark-splitview-detail>
88
- `
89
- const detail = container.querySelector('ark-splitview-detail')
90
- detail.dispatchEvent(new Event('close'))
91
-
92
- expect(detail.hasAttribute('hidden')).toBeTruthy()
93
- })
23
+ let container = null
24
+
25
+ const setup = () => {
26
+ document.body.innerHTML = '';
27
+ container = document.createElement('div')
28
+ document.body.appendChild(container)
29
+ };
30
+
31
+ it('can be instantiated', () => {
32
+ setup();
33
+ container.innerHTML = `
34
+ <ark-splitview-detail>
35
+ </ark-splitview-detail>
36
+ `
37
+ const detail = container.querySelector('ark-splitview-detail')
38
+ assert.ok(detail)
39
+
40
+ assert.strictEqual(detail, detail.init())
41
+ })
42
+
43
+ it('can be instantiated with an inner main Component', () => {
44
+ setup();
45
+ container.innerHTML = /* html */`
46
+ <ark-splitview-detail>
47
+ <mock-main>MAIN CONTENT</mock-main>
48
+ </ark-splitview-detail>
49
+ `
50
+ const detail = container.querySelector('ark-splitview-detail')
51
+
52
+ assert.deepStrictEqual(detail.firstElementChild.textContent, 'MAIN CONTENT')
53
+ })
54
+
55
+ it('can initialize its main Component', () => {
56
+ setup();
57
+ container.innerHTML = /* html */`
58
+ <ark-splitview-detail>
59
+ <mock-main></mock-main>
60
+ </ark-splitview-detail>
61
+ `
62
+ const detail = container.querySelector('ark-splitview-detail')
63
+
64
+ detail.init({ name: 'Servagro' }).render()
65
+
66
+ assert.deepStrictEqual(detail.firstElementChild.textContent, 'Servagro')
67
+ })
68
+
69
+ it('can manipulate its hidden attribute', () => {
70
+ setup();
71
+ container.innerHTML = /* html */`
72
+ <ark-splitview-detail>
73
+ <mock-main></mock-main>
74
+ </ark-splitview-detail>
75
+ `
76
+ const detail = container.querySelector('ark-splitview-detail')
77
+
78
+ detail.show()
79
+ assert.ok(!detail.hasAttribute('hidden'))
80
+
81
+ detail.hide()
82
+ assert.ok(detail.hasAttribute('hidden'))
83
+ })
84
+
85
+ it('listens to close events to hide itself', () => {
86
+ setup();
87
+ container.innerHTML = /* html */`
88
+ <ark-splitview-detail>
89
+ <mock-main></mock-main>
90
+ </ark-splitview-detail>
91
+ `
92
+ const detail = container.querySelector('ark-splitview-detail')
93
+ detail.dispatchEvent(new Event('close'))
94
+
95
+ assert.ok(detail.hasAttribute('hidden'))
94
96
  })
@@ -1,46 +1,89 @@
1
1
  import { Component, css } from "#base/index.js"
2
2
 
3
3
  /** @import {SplitViewDetail} from './splitview.detail.js' */
4
+ /** @import {SplitViewMaster} from './splitview.master.js' */
4
5
 
5
6
  const tag = 'ark-splitview'
7
+ /**
8
+ * Master-detail split view orchestrator.
9
+ */
6
10
  export class SplitView extends Component {
7
11
  constructor () {
8
12
  super()
9
13
  this.binding = 'splitview-listen'
10
- this.setDimensions()
11
- globalThis.addEventListener('resize', this.setDimensions.bind(this))
14
+ this._onResize = this.setDimensions.bind(this)
15
+ this._onMasterChange = this.onMasterChange.bind(this)
16
+ this._master = null
12
17
  }
13
18
 
19
+ /** @returns {void} */
14
20
  setDimensions () {
15
- this.style.setProperty('--inner-height', `${innerHeight}px`)
16
- this.style.setProperty('--inner-width', `${innerWidth}px`)
21
+ if (typeof globalThis.innerHeight !== 'number') return
22
+ if (typeof globalThis.innerWidth !== 'number') return
23
+
24
+ this.style.setProperty('--inner-height', `${globalThis.innerHeight}px`)
25
+ this.style.setProperty('--inner-width', `${globalThis.innerWidth}px`)
26
+ }
27
+
28
+ /** @returns {void} */
29
+ connectedCallback () {
30
+ this.setDimensions()
31
+ globalThis.addEventListener('resize', this._onResize)
32
+ super.connectedCallback()
33
+ }
34
+
35
+ /** @returns {void} */
36
+ disconnectedCallback () {
37
+ globalThis.removeEventListener('resize', this._onResize)
38
+ this._removeMasterListener()
39
+ super.disconnectedCallback()
40
+ }
41
+
42
+ /** @returns {void} */
43
+ _setMasterListener () {
44
+ const master = this.master
45
+ if (master === this._master) return
46
+
47
+ this._removeMasterListener()
48
+ this._master = master
49
+ this._master?.addEventListener('master-change', this._onMasterChange)
50
+ }
51
+
52
+ /** @returns {void} */
53
+ _removeMasterListener () {
54
+ if (!this._master) return
55
+ this._master.removeEventListener('master-change', this._onMasterChange)
56
+ this._master = null
17
57
  }
18
58
 
59
+ /** @returns {(SplitViewMaster|null)} */
19
60
  get master () {
20
- return this.select('ark-splitview-master')
61
+ return /** @type {SplitViewMaster|null} */ (
62
+ this.querySelector('ark-splitview-master'))
21
63
  }
22
64
 
65
+ /** @returns {SplitViewDetail} */
23
66
  get detail () {
24
67
  return /** @type {SplitViewDetail} */ (this.select('ark-splitview-detail'))
25
68
  }
26
69
 
70
+ /** @returns {this} */
27
71
  render () {
28
72
  this.renderDetail()
29
- if (this.master) {
30
- this.master.addEventListener(
31
- 'master-change', this.onMasterChange.bind(this))
32
- }
73
+ this._setMasterListener()
33
74
  return super.render()
34
75
  }
35
76
 
36
- /** @param {Object} context */
77
+ /** @param {object} context
78
+ * @returns {void} */
37
79
  renderDetail (context = {}) {
38
80
  if (!this.detail || !this.detail.init) return
39
81
 
40
82
  this.detail.init(context).render()
41
83
  }
42
84
 
43
- /** @param {CustomEvent} event */
85
+ /** @param {CustomEvent} event
86
+ * @returns {void} */
44
87
  onMasterChange (event) {
45
88
  event.stopPropagation()
46
89
 
@@ -1,23 +1,58 @@
1
1
  import { Component } from "#base/index.js"
2
2
 
3
3
  const tag = 'ark-splitview-master'
4
+ /**
5
+ * Master pane controller for split-view layout.
6
+ */
4
7
  export class SplitViewMaster extends Component {
5
8
  constructor () {
6
9
  super()
10
+ this._onMasterEvent = this.onMasterEvent.bind(this)
11
+ this._boundMasterEvent = null
7
12
  this.masterEvent = this.masterEvent
8
- this.addEventListener(
9
- this.masterEvent, this.onMasterEvent.bind(this))
10
13
  }
11
14
 
15
+ /** @param {object} context
16
+ * @returns {this} */
12
17
  init (context = {}) {
13
18
  this.binding = 'splitview-master-listen'
14
19
  return super.init(context)
15
20
  }
16
21
 
22
+ /** @returns {string[]} */
17
23
  reflectedProperties () {
18
24
  return ['masterEvent']
19
25
  }
20
26
 
27
+ /** @returns {void} */
28
+ connectedCallback () {
29
+ this._syncMasterEventListener()
30
+ super.connectedCallback()
31
+ }
32
+
33
+ /** @returns {void} */
34
+ disconnectedCallback () {
35
+ this._removeMasterEventListener()
36
+ super.disconnectedCallback()
37
+ }
38
+
39
+ /** @returns {void} */
40
+ _syncMasterEventListener () {
41
+ const masterEvent = (this.masterEvent || '').trim()
42
+ if (!masterEvent || masterEvent === this._boundMasterEvent) return
43
+
44
+ this._removeMasterEventListener()
45
+ this.addEventListener(masterEvent, this._onMasterEvent)
46
+ this._boundMasterEvent = masterEvent
47
+ }
48
+
49
+ /** @returns {void} */
50
+ _removeMasterEventListener () {
51
+ if (!this._boundMasterEvent) return
52
+ this.removeEventListener(this._boundMasterEvent, this._onMasterEvent)
53
+ this._boundMasterEvent = null
54
+ }
55
+
21
56
  /** @param {CustomEvent} event */
22
57
  onMasterEvent (event) {
23
58
  event.stopPropagation()
@@ -1,55 +1,55 @@
1
+ import { it } from 'node:test';
2
+ import assert from 'node:assert/strict';
1
3
  import './splitview.master.js'
2
4
 
3
- describe('SplitViewMaster', () => {
4
- let container = null
5
- beforeEach(() => {
6
- container = document.createElement('div')
7
- document.body.appendChild(container)
8
- })
9
-
10
- afterEach(() => {
11
- container.remove()
12
- container = null
13
- })
14
-
15
- it('can be instantiated', () => {
16
- container.innerHTML = /* html */`
17
- <ark-splitview-master>
18
- </ark-splitview-master>
19
- `
20
- const master = container.querySelector('ark-splitview-master')
21
- master.init()
22
- master.connectedCallback()
23
-
24
- expect(master).toBeTruthy()
25
- expect(master).toBe(master.init())
26
- expect(master.getAttribute('master-event')).toEqual('')
27
- })
28
-
29
- it('can be instantiated with master-event attribute', () => {
30
- container.innerHTML = `
31
- <ark-splitview-master master-event="my-event">
32
- </ark-splitview-master>
33
- `
34
- const master = container.querySelector('ark-splitview-master')
35
- expect(master.getAttribute('master-event')).toEqual('my-event')
36
- expect(master.masterEvent).toEqual('my-event')
37
- })
38
-
39
- it('can throw a master-change event', () => {
40
- container.innerHTML = `
41
- <ark-splitview-master master-event="click">
42
- <button>Button</button>
43
- </ark-splitview-master>
44
- `
45
- const master = container.querySelector('ark-splitview-master')
46
- const button = master.select('button')
47
-
48
- let masterEvent = null
49
- master.addEventListener('master-change', (event) => { masterEvent = event })
50
-
51
- button.click()
52
-
53
- expect(masterEvent).toBeTruthy()
54
- })
5
+ let container = null
6
+
7
+ const setup = () => {
8
+ document.body.innerHTML = '';
9
+ container = document.createElement('div')
10
+ document.body.appendChild(container)
11
+ };
12
+
13
+ it('can be instantiated', () => {
14
+ setup();
15
+ container.innerHTML = /* html */`
16
+ <ark-splitview-master>
17
+ </ark-splitview-master>
18
+ `
19
+ const master = container.querySelector('ark-splitview-master')
20
+ master.init()
21
+ master.connectedCallback()
22
+
23
+ assert.ok(master)
24
+ assert.strictEqual(master, master.init())
25
+ assert.deepStrictEqual(master.getAttribute('master-event'), '')
26
+ })
27
+
28
+ it('can be instantiated with master-event attribute', () => {
29
+ setup();
30
+ container.innerHTML = `
31
+ <ark-splitview-master master-event="my-event">
32
+ </ark-splitview-master>
33
+ `
34
+ const master = container.querySelector('ark-splitview-master')
35
+ assert.deepStrictEqual(master.getAttribute('master-event'), 'my-event')
36
+ assert.deepStrictEqual(master.masterEvent, 'my-event')
37
+ })
38
+
39
+ it('can throw a master-change event', () => {
40
+ setup();
41
+ container.innerHTML = `
42
+ <ark-splitview-master master-event="click">
43
+ <button>Button</button>
44
+ </ark-splitview-master>
45
+ `
46
+ const master = container.querySelector('ark-splitview-master')
47
+ const button = master.select('button')
48
+
49
+ let masterEvent = null
50
+ master.addEventListener('master-change', (event) => { masterEvent = event })
51
+
52
+ button.click()
53
+
54
+ assert.ok(masterEvent)
55
55
  })
@@ -1,6 +1,8 @@
1
+ import { it } from 'node:test';
2
+ import assert from 'node:assert/strict';
1
3
  import { Component } from '#base/index.js'
2
4
  import './splitview.js'
3
- import './splitview.detail'
5
+ import './splitview.detail.js'
4
6
  import './splitview.master.js'
5
7
 
6
8
  class NestedMaster extends Component {
@@ -28,47 +30,149 @@ class NestedDetail extends Component {
28
30
  }
29
31
  Component.define('nested-detail', NestedDetail)
30
32
 
31
- describe('SplitView', () => {
32
- let container = null
33
- beforeEach(() => {
34
- container = document.createElement('div')
35
- document.body.appendChild(container)
36
- })
33
+ let container = null
37
34
 
38
- afterEach(() => {
39
- container.remove()
40
- container = null
41
- })
35
+ const setup = () => {
36
+ document.body.innerHTML = '';
37
+ container = document.createElement('div')
38
+ document.body.appendChild(container)
39
+ };
40
+
41
+ it('can be instantiated', () => {
42
+ setup();
43
+ container.innerHTML = /* html */`
44
+ <ark-splitview></ark-splitview>
45
+ `
46
+ const splitview = container.querySelector('ark-splitview')
47
+
48
+ assert.ok(splitview)
49
+ assert.strictEqual(splitview.init(), splitview)
50
+ })
51
+
52
+ it('can coordinate the master and the detail components', () => {
53
+ setup();
54
+ container.innerHTML = /* html */`
55
+ <ark-splitview>
56
+ <ark-splitview-master master-event="nested:master">
57
+ <nested-master></nested-master>
58
+ </ark-splitview-master>
59
+ <ark-splitview-detail>
60
+ <nested-detail></nested-detail>
61
+ </ark-splitview-detail>
62
+ </ark-splitview>
63
+ `
64
+ const splitview = container.querySelector('ark-splitview')
65
+
66
+ const nestedMaster = splitview.select('nested-master')
67
+
68
+ nestedMaster.click()
69
+
70
+ const nestedDetail = splitview.select('nested-detail')
42
71
 
43
- it('can be instantiated', () => {
72
+ assert.deepStrictEqual(nestedDetail.content, 'NESTED MASTER VALUE')
73
+ })
74
+
75
+ it('cleans up global resize listeners when disconnected', () => {
76
+ setup()
77
+ const addEventListener = globalThis.addEventListener
78
+ const removeEventListener = globalThis.removeEventListener
79
+ let resizeAdded = 0
80
+ let resizeRemoved = 0
81
+
82
+ globalThis.addEventListener = function (type, listener, options) {
83
+ if (type === 'resize') resizeAdded += 1
84
+ return addEventListener(type, listener, options)
85
+ }
86
+
87
+ globalThis.removeEventListener = function (type, listener, options) {
88
+ if (type === 'resize') resizeRemoved += 1
89
+ return removeEventListener(type, listener, options)
90
+ }
91
+
92
+ try {
44
93
  container.innerHTML = /* html */`
45
94
  <ark-splitview></ark-splitview>
46
95
  `
47
96
  const splitview = container.querySelector('ark-splitview')
97
+ splitview.remove()
98
+ } finally {
99
+ globalThis.addEventListener = addEventListener
100
+ globalThis.removeEventListener = removeEventListener
101
+ }
48
102
 
49
- expect(splitview).toBeTruthy()
50
- expect(splitview.init()).toBe(splitview)
103
+ assert.ok(resizeAdded > 0)
104
+ assert.ok(resizeRemoved > 0)
105
+ })
106
+
107
+ it('returns early when there is no detail component to render', () => {
108
+ setup()
109
+ container.innerHTML = /* html */`
110
+ <ark-splitview></ark-splitview>
111
+ `
112
+ const splitview = container.querySelector('ark-splitview')
113
+
114
+ assert.doesNotThrow(() => {
115
+ splitview.renderDetail({ value: 'ignored' })
51
116
  })
117
+ })
52
118
 
53
- it('can coordinate the master and the detail components', () => {
54
- container.innerHTML = /* html */`
55
- <ark-splitview>
56
- <ark-splitview-master master-event="nested:master">
57
- <nested-master></nested-master>
58
- </ark-splitview-master>
59
- <ark-splitview-detail>
60
- <nested-detail></nested-detail>
61
- </ark-splitview-detail>
62
- </ark-splitview>
63
- `
64
- const splitview = container.querySelector('ark-splitview')
119
+ it('returns early when removing master listener with no master bound', () => {
120
+ setup()
121
+ container.innerHTML = /* html */`
122
+ <ark-splitview></ark-splitview>
123
+ `
124
+ const splitview = container.querySelector('ark-splitview')
65
125
 
66
- const nestedMaster = splitview.select('nested-master')
126
+ assert.doesNotThrow(() => {
127
+ splitview._removeMasterListener()
128
+ })
129
+ })
67
130
 
68
- nestedMaster.click()
131
+ it('does not rebind master listener when the master is unchanged', () => {
132
+ setup()
133
+ container.innerHTML = /* html */`
134
+ <ark-splitview>
135
+ <ark-splitview-master master-event="nested:master"></ark-splitview-master>
136
+ <ark-splitview-detail>
137
+ <nested-detail></nested-detail>
138
+ </ark-splitview-detail>
139
+ </ark-splitview>
140
+ `
141
+ const splitview = container.querySelector('ark-splitview')
142
+ const master = splitview.master
143
+ const addSpy = master.addEventListener
144
+ let added = 0
145
+ master.addEventListener = function (type, listener, options) {
146
+ added += 1
147
+ return addSpy.call(this, type, listener, options)
148
+ }
69
149
 
70
- const nestedDetail = splitview.select('nested-detail')
150
+ try {
151
+ splitview._removeMasterListener()
152
+ splitview._setMasterListener()
153
+ splitview._setMasterListener()
154
+ } finally {
155
+ master.addEventListener = addSpy
156
+ }
71
157
 
72
- expect(nestedDetail.content).toEqual('NESTED MASTER VALUE')
73
- })
158
+ assert.deepStrictEqual(added, 1)
159
+ })
160
+
161
+ it('returns early when viewport dimensions are unavailable', () => {
162
+ setup()
163
+ container.innerHTML = /* html */`
164
+ <ark-splitview></ark-splitview>
165
+ `
166
+ const splitview = container.querySelector('ark-splitview')
167
+ const originalInnerHeight = globalThis.innerHeight
168
+ const originalInnerWidth = globalThis.innerWidth
169
+
170
+ globalThis.innerHeight = undefined
171
+ assert.doesNotThrow(() => splitview.setDimensions())
172
+
173
+ globalThis.innerHeight = originalInnerHeight
174
+ globalThis.innerWidth = undefined
175
+ assert.doesNotThrow(() => splitview.setDimensions())
176
+
177
+ globalThis.innerWidth = originalInnerWidth
74
178
  })
@@ -1,3 +1,4 @@
1
+ /** Master-detail split view components. */
1
2
  export { SplitViewDetail } from './components/splitview.detail.js'
2
3
  export { SplitViewMaster } from './components/splitview.master.js'
3
4
  export { SplitView } from './components/splitview.js'