Skip to content

Commit

Permalink
Feature: Shadow DOM without wrapping DIV element (#146)
Browse files Browse the repository at this point in the history
* webcomponent shadowroot without div container

* remove type casting of parentNode

* Update browser.yml

* Update webComponent.html

* Update webComponent.html

---------

Co-authored-by: Hauke Broer <hbroer@users.noreply.github.com>
Co-authored-by: yandeu <20306025+yandeu@users.noreply.github.com>
  • Loading branch information
3 people authored Dec 26, 2024
1 parent 00c32e3 commit 196f49a
Show file tree
Hide file tree
Showing 5 changed files with 25 additions and 25 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/browser.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ jobs:
rm -f package.json
rm -f package-lock.json
npm init -y
npm i -D rimraf typescript puppeteer
npm i -D rimraf typescript@5.1.6 puppeteer
npm i -D webpack webpack-cli ts-loader nyc coverage-istanbul-loader
- name: Prepare
Expand Down
2 changes: 1 addition & 1 deletion src/component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ export class Component<P extends Object = any, S = any> {
// console.log('new: ', this.elements)

// get valid parent node
const parent = oldElements[0].parentElement as HTMLElement
const parent = oldElements[0].parentNode

// make sure we have a parent
if (!parent) console.warn('Component needs a parent element to get updated!')
Expand Down
11 changes: 2 additions & 9 deletions src/customElementsMode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,18 +74,11 @@ export const defineAsCustomElements: (
}

private buildEl(contents: any) {
// because nano-jsx update needs parentElement, we need
// to wrap the element in a div when using shadow mode
return h(this.shadowRoot ? 'div' : 'template', null, contents)
return h('template', null, contents)
}

private appendEl(el: any) {
if (this.shadowRoot) {
// el.dataset.wcRoot = true
this.$root.append(el)
} else {
this.$root.append(...el.childNodes)
}
this.$root.append(...el.childNodes)
}

private removeChildren() {
Expand Down
11 changes: 9 additions & 2 deletions test/browser/webComponent.html
Original file line number Diff line number Diff line change
Expand Up @@ -43,16 +43,23 @@
const myCustomElement = document.querySelector('my-custom-element')
Test.error(myCustomElement.innerHTML === 'invisible', 'Should show text "invisible"')
Test.error(
myCustomElement?.shadowRoot?.innerHTML === '<div><div><h1>title</h1>bye123</div></div>',
myCustomElement?.shadowRoot?.innerHTML === '<div><h1>title</h1>bye123</div>',
'Shadow should contain "title" and "bye123"'
)

// update attribute hello
myCustomElement.setAttribute("hello", 456)
Test.error(
myCustomElement?.shadowRoot?.innerHTML === '<div><h1>title</h1>bye456</div>',
'Shadow should contain "title" and "bye456"'
)
})

describe('slot-test', async () => {
const myCustomElement = document.querySelector('slot-test')
Test.error(myCustomElement.innerHTML === '<span slot="username">John Doe</span>', 'Should show span')
Test.error(
myCustomElement?.shadowRoot?.innerHTML === '<div><p>Hello: <slot name="username"></slot></p></div>',
myCustomElement?.shadowRoot?.innerHTML === '<p>Hello: <slot name="username"></slot></p>',
'Hello: John Doe'
)
})
Expand Down
24 changes: 12 additions & 12 deletions test/nodejs/customElementsMode.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ test('should render with correct content', async () => {
await wait()

const comp = document.querySelector('nano-test2')
expect(comp?.shadowRoot?.innerHTML).toEqual('<div><div>test text</div></div>')
expect(comp?.shadowRoot?.innerHTML).toEqual('<div>test text</div>')
expect(spy).not.toHaveBeenCalled()
})

Expand All @@ -65,7 +65,7 @@ test('should render with props', async () => {
await wait()

const comp = document.querySelector('nano-test3')
expect(comp?.shadowRoot?.innerHTML).toEqual('<div><div>test : fuga</div></div>')
expect(comp?.shadowRoot?.innerHTML).toEqual('<div>test : fuga</div>')
expect(spy).not.toHaveBeenCalled()
})

Expand All @@ -90,11 +90,11 @@ test('should update render result with props change', async () => {
await wait()

const comp = document.querySelector('nano-test4')
expect(comp?.shadowRoot?.innerHTML).toEqual('<div><div>test : fuga</div></div>')
expect(comp?.shadowRoot?.innerHTML).toEqual('<div>test : fuga</div>')

document.body.innerHTML = '<nano-test4 value="hoge"></nano-test4>'
const compChanged = document.querySelector('nano-test4')
expect(compChanged?.shadowRoot?.innerHTML).toEqual('<div><div>test : hoge</div></div>')
expect(compChanged?.shadowRoot?.innerHTML).toEqual('<div>test : hoge</div>')
expect(spy).not.toHaveBeenCalled()
})

Expand Down Expand Up @@ -123,10 +123,10 @@ test('should change render result with state change', async () => {
await wait()

const comp = document.querySelector('nano-test5')
expect(comp?.shadowRoot?.innerHTML).toEqual('<div><div><div>Counter: 0</div><button>Increment</button></div></div>')
expect(comp?.shadowRoot?.innerHTML).toEqual('<div><div>Counter: 0</div><button>Increment</button></div>')

comp?.shadowRoot?.querySelector('button')?.click()
expect(comp?.shadowRoot?.innerHTML).toEqual('<div><div><div>Counter: 1</div><button>Increment</button></div></div>')
expect(comp?.shadowRoot?.innerHTML).toEqual('<div><div>Counter: 1</div><button>Increment</button></div>')
expect(spy).not.toHaveBeenCalled()
})

Expand Down Expand Up @@ -163,17 +163,17 @@ test('should keep state with props change', async () => {

const comp = document.querySelector('nano-test6')
expect(comp?.shadowRoot?.innerHTML).toEqual(
'<div><div><div>Counter: 0</div><div>props: 1</div><button>Increment</button></div></div>'
'<div><div>Counter: 0</div><div>props: 1</div><button>Increment</button></div>'
)

comp?.shadowRoot?.querySelector('button')?.click()
expect(comp?.shadowRoot?.innerHTML).toEqual(
'<div><div><div>Counter: 1</div><div>props: 1</div><button>Increment</button></div></div>'
'<div><div>Counter: 1</div><div>props: 1</div><button>Increment</button></div>'
)
// @ts-ignore
comp.attributes.value?.value = 2
expect(comp?.shadowRoot?.innerHTML).toEqual(
'<div><div><div>Counter: 1</div><div>props: 2</div><button>Increment</button></div></div>'
'<div><div>Counter: 1</div><div>props: 2</div><button>Increment</button></div>'
)
expect(spy).not.toHaveBeenCalled()
})
Expand All @@ -190,10 +190,10 @@ test('should render also with functional component', async () => {
await wait()

const comp = document.querySelector('nano-test7')
expect(comp?.shadowRoot?.innerHTML).toEqual('<div><p>hoge</p></div>')
expect(comp?.shadowRoot?.innerHTML).toEqual('<p>hoge</p>')
// @ts-ignore
comp.attributes.value?.value = 'bar'
expect(comp?.shadowRoot?.innerHTML).toEqual('<div><p>bar</p></div>')
expect(comp?.shadowRoot?.innerHTML).toEqual('<p>bar</p>')
expect(spy).not.toHaveBeenCalled()
})

Expand Down Expand Up @@ -225,6 +225,6 @@ test('should render also with slot', async () => {
await wait()

const comp = document.querySelector('nano-test8')
expect(comp?.shadowRoot?.innerHTML).toEqual('<div><div><header>nano jsx</header><main><p>hoge</p></main></div></div>')
expect(comp?.shadowRoot?.innerHTML).toEqual('<div><header>nano jsx</header><main><p>hoge</p></main></div>')
expect(spy).not.toHaveBeenCalled()
})

0 comments on commit 196f49a

Please sign in to comment.