@furystack/shades 11.1.0 → 12.0.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.
- package/CHANGELOG.md +312 -0
- package/README.md +13 -13
- package/esm/component-factory.spec.js +13 -5
- package/esm/component-factory.spec.js.map +1 -1
- package/esm/components/index.d.ts +4 -1
- package/esm/components/index.d.ts.map +1 -1
- package/esm/components/index.js +4 -1
- package/esm/components/index.js.map +1 -1
- package/esm/components/lazy-load.d.ts +2 -4
- package/esm/components/lazy-load.d.ts.map +1 -1
- package/esm/components/lazy-load.js +40 -24
- package/esm/components/lazy-load.js.map +1 -1
- package/esm/components/lazy-load.spec.js +57 -50
- package/esm/components/lazy-load.spec.js.map +1 -1
- package/esm/components/link-to-route.d.ts +2 -0
- package/esm/components/link-to-route.d.ts.map +1 -1
- package/esm/components/link-to-route.js +3 -2
- package/esm/components/link-to-route.js.map +1 -1
- package/esm/components/link-to-route.spec.js +13 -9
- package/esm/components/link-to-route.spec.js.map +1 -1
- package/esm/components/nested-route-link.d.ts +62 -0
- package/esm/components/nested-route-link.d.ts.map +1 -0
- package/esm/components/nested-route-link.js +66 -0
- package/esm/components/nested-route-link.js.map +1 -0
- package/esm/components/nested-route-link.spec.d.ts +2 -0
- package/esm/components/nested-route-link.spec.d.ts.map +1 -0
- package/esm/components/nested-route-link.spec.js +179 -0
- package/esm/components/nested-route-link.spec.js.map +1 -0
- package/esm/components/nested-route-types.d.ts +37 -0
- package/esm/components/nested-route-types.d.ts.map +1 -0
- package/esm/components/nested-route-types.js +2 -0
- package/esm/components/nested-route-types.js.map +1 -0
- package/esm/components/nested-router.d.ts +103 -0
- package/esm/components/nested-router.d.ts.map +1 -0
- package/esm/components/nested-router.js +183 -0
- package/esm/components/nested-router.js.map +1 -0
- package/esm/components/nested-router.spec.d.ts +2 -0
- package/esm/components/nested-router.spec.d.ts.map +1 -0
- package/esm/components/nested-router.spec.js +737 -0
- package/esm/components/nested-router.spec.js.map +1 -0
- package/esm/components/route-link.d.ts +4 -0
- package/esm/components/route-link.d.ts.map +1 -1
- package/esm/components/route-link.js +5 -5
- package/esm/components/route-link.js.map +1 -1
- package/esm/components/route-link.spec.js +16 -12
- package/esm/components/route-link.spec.js.map +1 -1
- package/esm/components/router.d.ts +20 -2
- package/esm/components/router.d.ts.map +1 -1
- package/esm/components/router.js +12 -7
- package/esm/components/router.js.map +1 -1
- package/esm/components/router.spec.js +141 -74
- package/esm/components/router.spec.js.map +1 -1
- package/esm/initialize.d.ts +11 -0
- package/esm/initialize.d.ts.map +1 -1
- package/esm/initialize.js +5 -0
- package/esm/initialize.js.map +1 -1
- package/esm/jsx.d.ts +83 -2
- package/esm/jsx.d.ts.map +1 -1
- package/esm/models/children-list.d.ts +5 -1
- package/esm/models/children-list.d.ts.map +1 -1
- package/esm/models/partial-element.d.ts +12 -2
- package/esm/models/partial-element.d.ts.map +1 -1
- package/esm/models/render-options.d.ts +89 -3
- package/esm/models/render-options.d.ts.map +1 -1
- package/esm/models/selection-state.d.ts +4 -0
- package/esm/models/selection-state.d.ts.map +1 -1
- package/esm/services/location-service.d.ts +11 -0
- package/esm/services/location-service.d.ts.map +1 -1
- package/esm/services/location-service.js +11 -0
- package/esm/services/location-service.js.map +1 -1
- package/esm/services/resource-manager.d.ts +24 -0
- package/esm/services/resource-manager.d.ts.map +1 -1
- package/esm/services/resource-manager.js +36 -1
- package/esm/services/resource-manager.js.map +1 -1
- package/esm/services/resource-manager.spec.js +102 -0
- package/esm/services/resource-manager.spec.js.map +1 -1
- package/esm/services/screen-service.d.ts +81 -4
- package/esm/services/screen-service.d.ts.map +1 -1
- package/esm/services/screen-service.js +75 -4
- package/esm/services/screen-service.js.map +1 -1
- package/esm/services/screen-service.spec.js +91 -7
- package/esm/services/screen-service.spec.js.map +1 -1
- package/esm/shade-component.d.ts +17 -4
- package/esm/shade-component.d.ts.map +1 -1
- package/esm/shade-component.js +67 -5
- package/esm/shade-component.js.map +1 -1
- package/esm/shade-host-props-ref.integration.spec.d.ts +2 -0
- package/esm/shade-host-props-ref.integration.spec.d.ts.map +1 -0
- package/esm/shade-host-props-ref.integration.spec.js +381 -0
- package/esm/shade-host-props-ref.integration.spec.js.map +1 -0
- package/esm/shade-resources.integration.spec.js +208 -39
- package/esm/shade-resources.integration.spec.js.map +1 -1
- package/esm/shade.d.ts +20 -17
- package/esm/shade.d.ts.map +1 -1
- package/esm/shade.js +172 -33
- package/esm/shade.js.map +1 -1
- package/esm/shade.spec.js +31 -30
- package/esm/shade.spec.js.map +1 -1
- package/esm/shades.integration.spec.js +135 -72
- package/esm/shades.integration.spec.js.map +1 -1
- package/esm/style-manager.d.ts +2 -2
- package/esm/style-manager.js +2 -2
- package/esm/svg-types.d.ts +389 -0
- package/esm/svg-types.d.ts.map +1 -0
- package/esm/svg-types.js +9 -0
- package/esm/svg-types.js.map +1 -0
- package/esm/svg.d.ts +15 -0
- package/esm/svg.d.ts.map +1 -0
- package/esm/svg.js +76 -0
- package/esm/svg.js.map +1 -0
- package/esm/svg.spec.d.ts +2 -0
- package/esm/svg.spec.d.ts.map +1 -0
- package/esm/svg.spec.js +80 -0
- package/esm/svg.spec.js.map +1 -0
- package/esm/vnode.d.ts +103 -0
- package/esm/vnode.d.ts.map +1 -0
- package/esm/vnode.integration.spec.d.ts +2 -0
- package/esm/vnode.integration.spec.d.ts.map +1 -0
- package/esm/vnode.integration.spec.js +494 -0
- package/esm/vnode.integration.spec.js.map +1 -0
- package/esm/vnode.js +453 -0
- package/esm/vnode.js.map +1 -0
- package/esm/vnode.spec.d.ts +2 -0
- package/esm/vnode.spec.d.ts.map +1 -0
- package/esm/vnode.spec.js +473 -0
- package/esm/vnode.spec.js.map +1 -0
- package/package.json +8 -9
- package/src/component-factory.spec.tsx +18 -5
- package/src/components/index.ts +4 -1
- package/src/components/lazy-load.spec.tsx +82 -75
- package/src/components/lazy-load.tsx +49 -27
- package/src/components/link-to-route.spec.tsx +25 -21
- package/src/components/link-to-route.tsx +4 -2
- package/src/components/nested-route-link.spec.tsx +303 -0
- package/src/components/nested-route-link.tsx +100 -0
- package/src/components/nested-route-types.ts +42 -0
- package/src/components/nested-router.spec.tsx +918 -0
- package/src/components/nested-router.tsx +260 -0
- package/src/components/route-link.spec.tsx +22 -18
- package/src/components/route-link.tsx +6 -5
- package/src/components/router.spec.tsx +196 -108
- package/src/components/router.tsx +21 -8
- package/src/initialize.ts +12 -0
- package/src/jsx.ts +129 -2
- package/src/models/children-list.ts +7 -1
- package/src/models/partial-element.ts +13 -2
- package/src/models/render-options.ts +90 -3
- package/src/models/selection-state.ts +4 -0
- package/src/services/location-service.tsx +11 -0
- package/src/services/resource-manager.spec.ts +128 -0
- package/src/services/resource-manager.ts +36 -1
- package/src/services/screen-service.spec.ts +109 -7
- package/src/services/screen-service.ts +81 -4
- package/src/shade-component.ts +72 -6
- package/src/shade-host-props-ref.integration.spec.tsx +460 -0
- package/src/shade-resources.integration.spec.tsx +276 -52
- package/src/shade.spec.tsx +40 -39
- package/src/shade.ts +186 -58
- package/src/shades.integration.spec.tsx +154 -80
- package/src/style-manager.ts +2 -2
- package/src/svg-types.ts +437 -0
- package/src/svg.spec.ts +89 -0
- package/src/svg.ts +78 -0
- package/src/vnode.integration.spec.tsx +657 -0
- package/src/vnode.spec.ts +579 -0
- package/src/vnode.ts +508 -0
|
@@ -4,7 +4,7 @@ import { sleepAsync, usingAsync } from '@furystack/utils'
|
|
|
4
4
|
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
|
|
5
5
|
import { initializeShadeRoot } from './initialize.js'
|
|
6
6
|
import { createComponent } from './shade-component.js'
|
|
7
|
-
import { Shade } from './shade.js'
|
|
7
|
+
import { flushUpdates, Shade } from './shade.js'
|
|
8
8
|
|
|
9
9
|
describe('Shades integration tests', () => {
|
|
10
10
|
beforeEach(() => {
|
|
@@ -14,34 +14,38 @@ describe('Shades integration tests', () => {
|
|
|
14
14
|
document.body.innerHTML = ''
|
|
15
15
|
})
|
|
16
16
|
|
|
17
|
-
it('Should mount a custom component to a Shade root', () => {
|
|
18
|
-
|
|
19
|
-
|
|
17
|
+
it('Should mount a custom component to a Shade root', async () => {
|
|
18
|
+
await usingAsync(new Injector(), async (injector) => {
|
|
19
|
+
const rootElement = document.getElementById('root') as HTMLDivElement
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
const ExampleComponent = Shade({ render: () => <div>Hello</div>, shadowDomName: 'shades-example' })
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
23
|
+
initializeShadeRoot({
|
|
24
|
+
injector,
|
|
25
|
+
rootElement,
|
|
26
|
+
jsxElement: <ExampleComponent />,
|
|
27
|
+
})
|
|
28
|
+
await flushUpdates()
|
|
29
|
+
expect(document.body.innerHTML).toBe('<div id="root"><shades-example><div>Hello</div></shades-example></div>')
|
|
27
30
|
})
|
|
28
|
-
expect(document.body.innerHTML).toBe('<div id="root"><shades-example><div>Hello</div></shades-example></div>')
|
|
29
31
|
})
|
|
30
32
|
|
|
31
|
-
it('Should mount a custom component with a string render result', () => {
|
|
32
|
-
|
|
33
|
-
|
|
33
|
+
it('Should mount a custom component with a string render result', async () => {
|
|
34
|
+
await usingAsync(new Injector(), async (injector) => {
|
|
35
|
+
const rootElement = document.getElementById('root') as HTMLDivElement
|
|
34
36
|
|
|
35
|
-
|
|
37
|
+
const ExampleComponent = Shade({ render: () => 'Hello', shadowDomName: 'shades-string-render-result' })
|
|
36
38
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
39
|
+
initializeShadeRoot({
|
|
40
|
+
injector,
|
|
41
|
+
rootElement,
|
|
42
|
+
jsxElement: <ExampleComponent />,
|
|
43
|
+
})
|
|
44
|
+
await flushUpdates()
|
|
45
|
+
expect(document.body.innerHTML).toBe(
|
|
46
|
+
'<div id="root"><shades-string-render-result>Hello</shades-string-render-result></div>',
|
|
47
|
+
)
|
|
41
48
|
})
|
|
42
|
-
expect(document.body.innerHTML).toBe(
|
|
43
|
-
'<div id="root"><shades-string-render-result>Hello</shades-string-render-result></div>',
|
|
44
|
-
)
|
|
45
49
|
})
|
|
46
50
|
|
|
47
51
|
it('Should mount a custom component with null render result', async () => {
|
|
@@ -55,6 +59,7 @@ describe('Shades integration tests', () => {
|
|
|
55
59
|
rootElement,
|
|
56
60
|
jsxElement: <ExampleComponent />,
|
|
57
61
|
})
|
|
62
|
+
await flushUpdates()
|
|
58
63
|
expect(document.body.innerHTML).toBe(
|
|
59
64
|
'<div id="root"><shades-null-render-result></shades-null-render-result></div>',
|
|
60
65
|
)
|
|
@@ -80,6 +85,7 @@ describe('Shades integration tests', () => {
|
|
|
80
85
|
rootElement,
|
|
81
86
|
jsxElement: <ExampleComponent />,
|
|
82
87
|
})
|
|
88
|
+
await flushUpdates()
|
|
83
89
|
expect(document.body.innerHTML).toBe(
|
|
84
90
|
'<div id="root"><shades-fragment-render-result><p>1</p><p>2</p></shades-fragment-render-result></div>',
|
|
85
91
|
)
|
|
@@ -107,6 +113,7 @@ describe('Shades integration tests', () => {
|
|
|
107
113
|
rootElement,
|
|
108
114
|
jsxElement: <ExampleComponent />,
|
|
109
115
|
})
|
|
116
|
+
await flushUpdates()
|
|
110
117
|
expect(document.body.innerHTML).toBe(
|
|
111
118
|
'<div id="root"><shades-fragment-render-result-nested><p><p>1</p><p>2</p></p></shades-fragment-render-result-nested></div>',
|
|
112
119
|
)
|
|
@@ -137,6 +144,7 @@ describe('Shades integration tests', () => {
|
|
|
137
144
|
rootElement,
|
|
138
145
|
jsxElement: <ExampleComponent />,
|
|
139
146
|
})
|
|
147
|
+
await flushUpdates()
|
|
140
148
|
expect(document.body.innerHTML).toBe(
|
|
141
149
|
'<div id="root"><shades-fragment-render-result-2><shades-fragment-test-custom-component><p>Hello</p></shades-fragment-test-custom-component><shades-fragment-test-custom-component><p>Hello</p></shades-fragment-test-custom-component></shades-fragment-render-result-2></div>',
|
|
142
150
|
)
|
|
@@ -168,22 +176,28 @@ describe('Shades integration tests', () => {
|
|
|
168
176
|
</ExampleComponent>
|
|
169
177
|
),
|
|
170
178
|
})
|
|
179
|
+
await flushUpdates()
|
|
171
180
|
expect(document.body.innerHTML).toBe(
|
|
172
181
|
'<div id="root"><shades-example-2><div><shades-example-sub><div>1</div></shades-example-sub><shades-example-sub><div>2</div></shades-example-sub><shades-example-sub><div>3</div></shades-example-sub></div></shades-example-2></div>',
|
|
173
182
|
)
|
|
174
183
|
})
|
|
175
184
|
})
|
|
176
185
|
|
|
177
|
-
it(
|
|
186
|
+
it('Should execute useDisposable cleanup on component disconnection', async () => {
|
|
178
187
|
await usingAsync(new Injector(), async (injector) => {
|
|
179
188
|
const rootElement = document.getElementById('root') as HTMLDivElement
|
|
180
189
|
const cleanup = vi.fn()
|
|
181
|
-
const
|
|
190
|
+
const setup = vi.fn()
|
|
182
191
|
|
|
183
192
|
const ExampleComponent = Shade({
|
|
184
|
-
constructed,
|
|
185
193
|
shadowDomName: 'example-component-1',
|
|
186
|
-
render: () =>
|
|
194
|
+
render: ({ useDisposable }) => {
|
|
195
|
+
useDisposable('test', () => {
|
|
196
|
+
setup()
|
|
197
|
+
return { [Symbol.dispose]: cleanup }
|
|
198
|
+
})
|
|
199
|
+
return <div>Hello</div>
|
|
200
|
+
},
|
|
187
201
|
})
|
|
188
202
|
|
|
189
203
|
initializeShadeRoot({
|
|
@@ -191,7 +205,8 @@ describe('Shades integration tests', () => {
|
|
|
191
205
|
rootElement,
|
|
192
206
|
jsxElement: <ExampleComponent />,
|
|
193
207
|
})
|
|
194
|
-
|
|
208
|
+
await flushUpdates()
|
|
209
|
+
expect(setup).toBeCalled()
|
|
195
210
|
expect(cleanup).not.toBeCalled()
|
|
196
211
|
document.body.innerHTML = ''
|
|
197
212
|
await sleepAsync(10) // Dispose can be async
|
|
@@ -199,31 +214,6 @@ describe('Shades integration tests', () => {
|
|
|
199
214
|
})
|
|
200
215
|
})
|
|
201
216
|
|
|
202
|
-
it('Should execute the onAttach and onDetach callbacks', async () => {
|
|
203
|
-
await usingAsync(new Injector(), async (injector) => {
|
|
204
|
-
const rootElement = document.getElementById('root') as HTMLDivElement
|
|
205
|
-
const onAttach = vi.fn()
|
|
206
|
-
const onDetach = vi.fn()
|
|
207
|
-
|
|
208
|
-
const ExampleComponent = Shade({
|
|
209
|
-
onAttach,
|
|
210
|
-
onDetach,
|
|
211
|
-
shadowDomName: 'example-component-2',
|
|
212
|
-
render: () => <div>Hello</div>,
|
|
213
|
-
})
|
|
214
|
-
|
|
215
|
-
initializeShadeRoot({
|
|
216
|
-
injector,
|
|
217
|
-
rootElement,
|
|
218
|
-
jsxElement: <ExampleComponent />,
|
|
219
|
-
})
|
|
220
|
-
expect(onAttach).toBeCalled()
|
|
221
|
-
expect(onDetach).not.toBeCalled()
|
|
222
|
-
document.body.innerHTML = ''
|
|
223
|
-
expect(onDetach).toBeCalled()
|
|
224
|
-
})
|
|
225
|
-
})
|
|
226
|
-
|
|
227
217
|
it('Should update state', async () => {
|
|
228
218
|
await usingAsync(new Injector(), async (injector) => {
|
|
229
219
|
const rootElement = document.getElementById('root') as HTMLDivElement
|
|
@@ -250,19 +240,26 @@ describe('Shades integration tests', () => {
|
|
|
250
240
|
rootElement,
|
|
251
241
|
jsxElement: <ExampleComponent />,
|
|
252
242
|
})
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
const
|
|
243
|
+
await flushUpdates()
|
|
244
|
+
|
|
245
|
+
const plus = async () => {
|
|
246
|
+
document.getElementById('plus')?.click()
|
|
247
|
+
await flushUpdates()
|
|
248
|
+
}
|
|
249
|
+
const minus = async () => {
|
|
250
|
+
document.getElementById('minus')?.click()
|
|
251
|
+
await flushUpdates()
|
|
252
|
+
}
|
|
256
253
|
const expectCount = (count: number) => expect(document.body.innerHTML).toContain(`Count is ${count}`)
|
|
257
254
|
|
|
258
255
|
expectCount(0)
|
|
259
|
-
plus()
|
|
256
|
+
await plus()
|
|
260
257
|
expectCount(1)
|
|
261
|
-
plus()
|
|
258
|
+
await plus()
|
|
262
259
|
expectCount(2)
|
|
263
260
|
|
|
264
|
-
minus()
|
|
265
|
-
minus()
|
|
261
|
+
await minus()
|
|
262
|
+
await minus()
|
|
266
263
|
expectCount(0)
|
|
267
264
|
})
|
|
268
265
|
})
|
|
@@ -314,9 +311,16 @@ describe('Shades integration tests', () => {
|
|
|
314
311
|
rootElement,
|
|
315
312
|
jsxElement: <ExampleComponent />,
|
|
316
313
|
})
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
const
|
|
314
|
+
await flushUpdates()
|
|
315
|
+
|
|
316
|
+
const plus = async () => {
|
|
317
|
+
document.getElementById('plus')?.click()
|
|
318
|
+
await flushUpdates()
|
|
319
|
+
}
|
|
320
|
+
const minus = async () => {
|
|
321
|
+
document.getElementById('minus')?.click()
|
|
322
|
+
await flushUpdates()
|
|
323
|
+
}
|
|
320
324
|
const expectCount = (count: number) => expect(document.body.innerHTML).toContain(`Count is ${count}`)
|
|
321
325
|
|
|
322
326
|
await sleepAsync(100)
|
|
@@ -324,16 +328,16 @@ describe('Shades integration tests', () => {
|
|
|
324
328
|
expectCount(0)
|
|
325
329
|
|
|
326
330
|
await sleepAsync(100)
|
|
327
|
-
plus()
|
|
331
|
+
await plus()
|
|
328
332
|
expectCount(1)
|
|
329
333
|
expect(store.getItem('count')).toBe('1')
|
|
330
334
|
|
|
331
|
-
plus()
|
|
335
|
+
await plus()
|
|
332
336
|
expectCount(2)
|
|
333
337
|
expect(store.getItem('count')).toBe('2')
|
|
334
338
|
|
|
335
|
-
minus()
|
|
336
|
-
minus()
|
|
339
|
+
await minus()
|
|
340
|
+
await minus()
|
|
337
341
|
expectCount(0)
|
|
338
342
|
expect(store.getItem('count')).toBe('0')
|
|
339
343
|
})
|
|
@@ -365,24 +369,31 @@ describe('Shades integration tests', () => {
|
|
|
365
369
|
rootElement,
|
|
366
370
|
jsxElement: <ExampleComponent />,
|
|
367
371
|
})
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
const
|
|
372
|
+
await flushUpdates()
|
|
373
|
+
|
|
374
|
+
const plus = async () => {
|
|
375
|
+
document.getElementById('plus')?.click()
|
|
376
|
+
await flushUpdates()
|
|
377
|
+
}
|
|
378
|
+
const minus = async () => {
|
|
379
|
+
document.getElementById('minus')?.click()
|
|
380
|
+
await flushUpdates()
|
|
381
|
+
}
|
|
371
382
|
const expectCount = (count: number) => expect(document.body.innerHTML).toContain(`Count is ${count}`)
|
|
372
383
|
|
|
373
384
|
expectCount(0)
|
|
374
385
|
|
|
375
386
|
await sleepAsync(100)
|
|
376
|
-
plus()
|
|
387
|
+
await plus()
|
|
377
388
|
expectCount(1)
|
|
378
389
|
expect(location.search).toBe(`?${serializeToQueryString({ count: 1 })}`)
|
|
379
390
|
|
|
380
|
-
plus()
|
|
391
|
+
await plus()
|
|
381
392
|
expectCount(2)
|
|
382
393
|
expect(location.search).toBe(`?${serializeToQueryString({ count: 2 })}`)
|
|
383
394
|
|
|
384
|
-
minus()
|
|
385
|
-
minus()
|
|
395
|
+
await minus()
|
|
396
|
+
await minus()
|
|
386
397
|
expectCount(0)
|
|
387
398
|
expect(location.search).toBe(`?${serializeToQueryString({ count: 0 })}`)
|
|
388
399
|
})
|
|
@@ -439,31 +450,94 @@ describe('Shades integration tests', () => {
|
|
|
439
450
|
</Parent>
|
|
440
451
|
),
|
|
441
452
|
})
|
|
453
|
+
await flushUpdates()
|
|
442
454
|
|
|
443
|
-
const plus = () =>
|
|
444
|
-
|
|
455
|
+
const plus = async () => {
|
|
456
|
+
document.getElementById('plus')?.click()
|
|
457
|
+
await flushUpdates()
|
|
458
|
+
}
|
|
459
|
+
const minus = async () => {
|
|
460
|
+
document.getElementById('minus')?.click()
|
|
461
|
+
await flushUpdates()
|
|
462
|
+
}
|
|
445
463
|
|
|
446
464
|
const expectCount = (count: number) => expect(document.body.innerHTML).toContain(`Count is ${count}`)
|
|
447
|
-
const toggleChildren = () =>
|
|
465
|
+
const toggleChildren = async () => {
|
|
466
|
+
document.getElementById('showHideChildren')?.click()
|
|
467
|
+
await flushUpdates()
|
|
468
|
+
}
|
|
448
469
|
|
|
449
470
|
expectCount(0)
|
|
450
|
-
plus()
|
|
471
|
+
await plus()
|
|
451
472
|
expectCount(1)
|
|
452
473
|
|
|
453
|
-
toggleChildren()
|
|
474
|
+
await toggleChildren()
|
|
454
475
|
|
|
455
476
|
expect(document.getElementById('plus')).toBeNull()
|
|
456
477
|
|
|
457
478
|
await sleepAsync(10) // Dispose can be async
|
|
458
479
|
|
|
459
|
-
toggleChildren()
|
|
480
|
+
await toggleChildren()
|
|
460
481
|
expect(document.getElementById('plus')).toBeDefined()
|
|
461
482
|
|
|
462
483
|
expectCount(0)
|
|
463
|
-
plus()
|
|
484
|
+
await plus()
|
|
464
485
|
expectCount(1)
|
|
465
|
-
minus()
|
|
486
|
+
await minus()
|
|
466
487
|
expectCount(0)
|
|
467
488
|
})
|
|
468
489
|
})
|
|
490
|
+
|
|
491
|
+
it('Should propagate changed props from parent to child Shade component', async () => {
|
|
492
|
+
await usingAsync(new Injector(), async (injector) => {
|
|
493
|
+
const rootElement = document.getElementById('root') as HTMLDivElement
|
|
494
|
+
|
|
495
|
+
const ChildComponent = Shade<{ isDisabled: boolean }>({
|
|
496
|
+
shadowDomName: 'shade-prop-child',
|
|
497
|
+
render: ({ props }) => {
|
|
498
|
+
return <input type="checkbox" disabled={props.isDisabled} data-testid="inner-input" />
|
|
499
|
+
},
|
|
500
|
+
})
|
|
501
|
+
|
|
502
|
+
const ParentComponent = Shade({
|
|
503
|
+
shadowDomName: 'shade-prop-parent',
|
|
504
|
+
render: ({ useState }) => {
|
|
505
|
+
const [isDisabled, setIsDisabled] = useState('isDisabled', false)
|
|
506
|
+
return (
|
|
507
|
+
<div>
|
|
508
|
+
<button id="toggle-disabled" onclick={() => setIsDisabled(!isDisabled)}>
|
|
509
|
+
Toggle
|
|
510
|
+
</button>
|
|
511
|
+
<ChildComponent isDisabled={isDisabled} />
|
|
512
|
+
</div>
|
|
513
|
+
)
|
|
514
|
+
},
|
|
515
|
+
})
|
|
516
|
+
|
|
517
|
+
initializeShadeRoot({
|
|
518
|
+
injector,
|
|
519
|
+
rootElement,
|
|
520
|
+
jsxElement: <ParentComponent />,
|
|
521
|
+
})
|
|
522
|
+
|
|
523
|
+
await flushUpdates()
|
|
524
|
+
await flushUpdates()
|
|
525
|
+
|
|
526
|
+
const innerInput = document.querySelector('[data-testid="inner-input"]') as HTMLInputElement
|
|
527
|
+
expect(innerInput).toBeTruthy()
|
|
528
|
+
expect(innerInput.disabled).toBe(false)
|
|
529
|
+
|
|
530
|
+
// Click the toggle button
|
|
531
|
+
const toggleBtn = document.getElementById('toggle-disabled') as HTMLButtonElement
|
|
532
|
+
toggleBtn.click()
|
|
533
|
+
|
|
534
|
+
// Wait for parent re-render + child re-render (two microtask levels)
|
|
535
|
+
await flushUpdates()
|
|
536
|
+
await flushUpdates()
|
|
537
|
+
await flushUpdates()
|
|
538
|
+
|
|
539
|
+
const updatedInput = document.querySelector('[data-testid="inner-input"]') as HTMLInputElement
|
|
540
|
+
expect(updatedInput.disabled).toBe(true)
|
|
541
|
+
})
|
|
542
|
+
})
|
|
469
543
|
})
|
package/src/style-manager.ts
CHANGED
|
@@ -25,9 +25,9 @@ class StyleManagerClass {
|
|
|
25
25
|
|
|
26
26
|
/**
|
|
27
27
|
* Registers CSS styles for a component.
|
|
28
|
-
* Styles are only injected once per component (based on
|
|
28
|
+
* Styles are only injected once per component (based on the custom element name).
|
|
29
29
|
*
|
|
30
|
-
* @param shadowDomName - The
|
|
30
|
+
* @param shadowDomName - The custom element tag name (used as CSS selector)
|
|
31
31
|
* @param cssObject - The CSSObject containing styles and nested selectors
|
|
32
32
|
* @param elementBaseName - Optional base element name for customized built-in elements (e.g., 'a', 'button').
|
|
33
33
|
* When provided, generates selector like `a[is="component-name"]` instead of `component-name`
|