@vanilla-bean/components 2.0.4 → 2.0.5
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/Component/Component.js +12 -11
- package/Component/Component.test.js +41 -0
- package/Component/README.md +1 -1
- package/package.json +1 -1
- package/spellcheck.config.cjs +2 -0
- package/styled/styled.test.js +12 -2
- package/theme/page.js +11 -5
package/Component/Component.js
CHANGED
|
@@ -611,19 +611,20 @@ class Component extends Elem {
|
|
|
611
611
|
|
|
612
612
|
/**
|
|
613
613
|
* Destroys this component and all children. Runs all cleanup functions,
|
|
614
|
-
* clears registries, and removes from DOM.
|
|
614
|
+
* clears registries, and removes from DOM. Removal from the document is a disconnect: components listening for
|
|
615
|
+
* one (onDisconnected) hear it here, once, with no event detail.
|
|
615
616
|
*/
|
|
616
617
|
destroy() {
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
618
|
+
// Innermost first: a component's own disconnect runs its descendants' cleanup, which takes their listeners away
|
|
619
|
+
const watching = [
|
|
620
|
+
...Array.from(this.elem?.querySelectorAll('*') ?? [], node => node._component).reverse(),
|
|
621
|
+
this,
|
|
622
|
+
].filter(component => component?.elemObserver);
|
|
623
|
+
const wasConnected = Boolean(this.elem?.isConnected);
|
|
624
|
+
|
|
625
|
+
// Their observers are let go first, so the removal below reports nothing and this is the only disconnect
|
|
626
|
+
for (const component of watching) component.elemObserver.disconnect();
|
|
627
|
+
if (wasConnected) for (const component of watching) component.emit('disconnected');
|
|
627
628
|
|
|
628
629
|
this.processCleanup(this.cleanup, true);
|
|
629
630
|
if (this._destroyCleanup) this.processCleanup(this._destroyCleanup);
|
|
@@ -1047,6 +1047,47 @@ describe('Component', () => {
|
|
|
1047
1047
|
});
|
|
1048
1048
|
});
|
|
1049
1049
|
|
|
1050
|
+
describe('destroy', () => {
|
|
1051
|
+
const settle = () => new Promise(resolve => setTimeout(resolve, 0));
|
|
1052
|
+
|
|
1053
|
+
test('a component in the document hears its own removal once', async () => {
|
|
1054
|
+
const onDisconnected = mock();
|
|
1055
|
+
const comp = new Component({ appendTo: document.body, onDisconnected });
|
|
1056
|
+
|
|
1057
|
+
comp.destroy();
|
|
1058
|
+
await settle();
|
|
1059
|
+
|
|
1060
|
+
expect(onDisconnected).toHaveBeenCalledTimes(1);
|
|
1061
|
+
});
|
|
1062
|
+
|
|
1063
|
+
test('components inside it hear it too, nested in plain elements or not', async () => {
|
|
1064
|
+
const parent = new Component({ appendTo: document.body });
|
|
1065
|
+
const wrapper = document.createElement('div');
|
|
1066
|
+
const direct = mock();
|
|
1067
|
+
const nested = mock();
|
|
1068
|
+
|
|
1069
|
+
new Component({ appendTo: parent, onDisconnected: direct });
|
|
1070
|
+
parent.elem.append(wrapper);
|
|
1071
|
+
new Component({ appendTo: wrapper, onDisconnected: nested });
|
|
1072
|
+
|
|
1073
|
+
parent.destroy();
|
|
1074
|
+
await settle();
|
|
1075
|
+
|
|
1076
|
+
expect(direct).toHaveBeenCalledTimes(1);
|
|
1077
|
+
expect(nested).toHaveBeenCalledTimes(1);
|
|
1078
|
+
});
|
|
1079
|
+
|
|
1080
|
+
test('one never in the document hears nothing', async () => {
|
|
1081
|
+
const onDisconnected = mock();
|
|
1082
|
+
const comp = new Component({ autoRender: false, onDisconnected });
|
|
1083
|
+
|
|
1084
|
+
comp.destroy();
|
|
1085
|
+
await settle();
|
|
1086
|
+
|
|
1087
|
+
expect(onDisconnected).not.toHaveBeenCalled();
|
|
1088
|
+
});
|
|
1089
|
+
});
|
|
1090
|
+
|
|
1050
1091
|
describe('_setOption routing', () => {
|
|
1051
1092
|
test('aria-* routes to setAttribute', () => {
|
|
1052
1093
|
component = new Component({ 'aria-label': 'test label' });
|
package/Component/README.md
CHANGED
|
@@ -440,7 +440,7 @@ component.addCleanup(id, fn); // Register cleanup function (chains with existing
|
|
|
440
440
|
component.replaceCleanup(id, fn); // Replace cleanup, running the previous one immediately
|
|
441
441
|
component.replaceDestroyCleanup(id, fn); // Destroy-only cleanup: survives disconnect, runs on destroy()
|
|
442
442
|
component.processCleanup(); // Execute all cleanup functions
|
|
443
|
-
component.destroy(); //
|
|
443
|
+
component.destroy(); // Remove from DOM: onDisconnected fires (innermost first), then all cleanup runs
|
|
444
444
|
```
|
|
445
445
|
|
|
446
446
|
#### Event Methods
|
package/package.json
CHANGED
package/spellcheck.config.cjs
CHANGED
package/styled/styled.test.js
CHANGED
|
@@ -2,18 +2,28 @@
|
|
|
2
2
|
|
|
3
3
|
import { Component } from '../Component';
|
|
4
4
|
import theme from '../theme';
|
|
5
|
+
import * as utils from '../utils';
|
|
5
6
|
import { styled, configured } from './styled';
|
|
6
7
|
|
|
7
8
|
const mockShimCSS = mock(() => {});
|
|
8
9
|
mock.module('./shimCSS', () => ({ shimCSS: mockShimCSS }));
|
|
9
10
|
|
|
10
|
-
|
|
11
|
-
|
|
11
|
+
// bun's module mocks outlive this file, so the rest of utils passes through and the real id generator comes back
|
|
12
|
+
// once these tests are done
|
|
13
|
+
const realNanoid = utils.classSafeNanoid;
|
|
14
|
+
const testNanoid = () => 'test-id-1234567890';
|
|
15
|
+
const mockNanoid = mock(testNanoid);
|
|
16
|
+
mock.module('../utils', () => ({ ...utils, classSafeNanoid: mockNanoid }));
|
|
12
17
|
|
|
13
18
|
describe('styled system', () => {
|
|
14
19
|
beforeEach(() => {
|
|
15
20
|
mockShimCSS.mockClear();
|
|
16
21
|
mockNanoid.mockClear();
|
|
22
|
+
mockNanoid.mockImplementation(testNanoid);
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
afterAll(() => {
|
|
26
|
+
mockNanoid.mockImplementation(realNanoid);
|
|
17
27
|
});
|
|
18
28
|
|
|
19
29
|
describe('configured()', () => {
|
package/theme/page.js
CHANGED
|
@@ -10,6 +10,8 @@ export default theme => `
|
|
|
10
10
|
html {
|
|
11
11
|
height: 100%;
|
|
12
12
|
color-scheme: ${colors.black.isDark() ? 'dark' : 'light'};
|
|
13
|
+
font-size: 16px;
|
|
14
|
+
${fonts.kodeMono}
|
|
13
15
|
}
|
|
14
16
|
|
|
15
17
|
body {
|
|
@@ -34,13 +36,17 @@ export default theme => `
|
|
|
34
36
|
* {
|
|
35
37
|
touch-action: manipulation;
|
|
36
38
|
-webkit-text-size-adjust: none;
|
|
39
|
+
}
|
|
37
40
|
|
|
38
|
-
|
|
39
|
-
|
|
41
|
+
/* The page's font is inherited, so content that sets its own (a terminal, an embedded editor) keeps it. These are
|
|
42
|
+
the elements the browser gives a font or size of their own. */
|
|
43
|
+
:where(h1, h2, h3, h4, h5, h6, small, big, code, kbd, pre, samp, tt, var, button, input, select, textarea, optgroup, option, legend) {
|
|
44
|
+
font-family: inherit;
|
|
45
|
+
font-size: inherit;
|
|
46
|
+
}
|
|
40
47
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
}
|
|
48
|
+
:where(sub, sup) {
|
|
49
|
+
font-size: smaller;
|
|
44
50
|
}
|
|
45
51
|
|
|
46
52
|
#app {
|