Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: Shadow DOM without wrapping DIV element #146

Merged
merged 5 commits into from
Dec 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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()
})
Loading