Skip to content

Commit

Permalink
resolve #8
Browse files Browse the repository at this point in the history
  • Loading branch information
loreanvictor committed Jul 4, 2023
1 parent 616e2d9 commit bbcc149
Show file tree
Hide file tree
Showing 15 changed files with 234 additions and 66 deletions.
83 changes: 62 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,19 +40,23 @@ define('say-hi', ({ to }) => {
- [Contents](#contents)
- [Installation](#installation)
- [Usage](#usage)
- [Provided Hooks](#provided-hooks)
- [onCleanup](#oncleanup)
- [onAttribute](#onattribute)
- [Common Hooks](#common-hooks)
<!-- - [onAttribute](#onattribute)
- [onProperty](#onproperty)
- [on](#on)
- [useDispatch](#usedispatch)
- [currentNode](#currentnode) -->
- [Lifecycle Hooks](#lifecycle-hooks)
<!-- - [onCleanup](#oncleanup)
- [onRendered](#onrendered)
- [onConnected](#onconnected)
- [onDisconnected](#ondisconnected)
- [onAttributeChanged](#onattributechanged)
- [onPropertyChanged](#onpropertychanged)
- [onRendered](#onrendered)
- [currentNode](#currentnode)
- [ownerDocument](#ownerdocument)
- [onPropertyChanged](#onpropertychanged) -->
- [Hooks for SSR](#hooks-for-ssr)
<!-- - [ownerDocument](#ownerdocument)
- [onHydrated](#onhydrated)
- [onFirstRender](#onfirstrender) -->
- [Rules for Hooks](#rules-for-hooks)
- [Custom Hooks](#custom-hooks)
- [Server Side Rendering](#server-side-rendering)
Expand Down Expand Up @@ -150,14 +154,9 @@ el.setProperty('myProp', { whatever: 'you want' })
<br>

## Provided Hooks
## Common Hooks

### onCleanup
```ts
onCleanup(hook: () => void)
```

Is called after the element is removed from the document and not added back immediately.
The following hooks are commonly used by components:

<br>

Expand Down Expand Up @@ -228,6 +227,30 @@ define('my-el', () => {

</div>

### currentNode

```ts
currentNode(): HTMLElement | undefined
```

Returns the current element being rendered, undefined if used out of a component function. Useful for custom hooks who need
to conduct an operation during rendering (for hooks that operate after rendering, use `.onRendered()`).

<br>

## Lifecycle Hooks

Use the following hooks to tap into life cycle events of custom elements:

<br>

### onCleanup
```ts
onCleanup(hook: () => void)
```

Is called after the element is removed from the document and not added back immediately.

<br>

### onConnected
Expand Down Expand Up @@ -285,22 +308,40 @@ Is called after the returned DOM is attached to the element's [shadow root](http

<br>

### currentNode

```ts
currentNode(): HTMLElement | undefined
```
## Hooks for SSR

Returns the current element being rendered, undefined if used out of a component function. Useful for custom hooks who need
to conduct an operation during rendering (for hooks that operate after rendering, use `.onRendered()`).
The following hooks are useful for server side rendering:

<br>

### ownerDocument

```ts
ownerDocument(): Document
```

Returns the document that the element is in. Useful for components (and hooks) that want to be operable in environments where there is no global document object (e.g. during SSR).
Returns the document that the element is in. Useful for components (and hooks) that want to be operable in environments where there is no global document object.

<br>

### onHydrated

```ts
onHydrated(hook: (node: HTMLElement) => void)
```

Is called when the element is hydrated on the client.

<br>

### onFirstRender

```ts
onFirstRender(hook: (node: HTMLElement) => void)
```

Is called when the element is rendered for the first time (either on the server or on the client).

<br>

Expand Down
18 changes: 9 additions & 9 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "minicomp",
"version": "0.3.6",
"version": "0.3.7",
"description": "Minimalistic library for creating Web Components",
"main": "dist/commonjs/index.js",
"module": "dist/es/index.js",
Expand Down Expand Up @@ -51,7 +51,7 @@
"jest-environment-jsdom": "^29.3.1",
"jsdom": "^21.1.0",
"quel": "^0.3.2",
"rehtm": "^0.2.0",
"rehtm": "^0.3.2",
"sleep-promise": "^9.1.0",
"ts-inference-check": "^0.2.1",
"ts-jest": "^29.0.3",
Expand Down
7 changes: 4 additions & 3 deletions src/component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,11 @@ export function component(
this._attributeChanged = hooks.onAttributeChanged
this._propertyChanged = hooks.onPropertyChanged

// TODO: test this using happy-dom (https://www.npmjs.com/package/happy-dom)
/* istanbul ignore if */
let hydrated = false

if (isSSRTemplate(node) && this._shouldHydrate) {
node.hydrateRoot(this._root)
hydrated = true
} else {
if (typeof node === 'string') {
this._root.innerHTML = node
Expand All @@ -76,7 +77,7 @@ export function component(
}
}

hooks.onRendered && hooks.onRendered(this)
hooks.onRendered && hooks.onRendered(this, hydrated)
}

this._connected && this._connected(this)
Expand Down
2 changes: 1 addition & 1 deletion src/hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export const ATTRIBUTE_REMOVED = Symbol()
export type ConnectedHook = (node: HTMLElement) => void
export type DisconnectedHook = (node: HTMLElement) => void
export type AdoptedHook = (node: HTMLElement) => void
export type RenderedHook = (node: HTMLElement) => void
export type RenderedHook = (node: HTMLElement, hydrated: boolean) => void
export type AttributeChangedHook = (name: string, value: string | typeof ATTRIBUTE_REMOVED, node: HTMLElement) => void
export type PropertyChangedHook = (name: string, value: unknown, node: HTMLElement) => void
export type Hook =
Expand Down
2 changes: 2 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,6 @@ export * from './attribute'
export * from './on'
export * from './property'
export * from './dispatch'
export * from './ssr-hooks'


19 changes: 19 additions & 0 deletions src/ssr-hooks.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { onRendered } from './hooks'


export function onHydrated(hook: (node: HTMLElement) => void) {
onRendered((node, hydrated) => {
if (hydrated) {
hook(node)
}
})
}


export function onFirstRender(hook: (node: HTMLElement) => void) {
onRendered((node, hydrated) => {
if (!hydrated) {
hook(node)
}
})
}
3 changes: 1 addition & 2 deletions src/test/define.ssr-test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
jest.mock('htm/mini', () => require('htm/mini/index.umd.js'))

import './polyfill'

import { JSDOM } from 'jsdom'
import { using, define, definable } from '../define'
Expand Down
6 changes: 1 addition & 5 deletions src/test/define.test.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
jest.mock('htm/mini', () => require('htm/mini/index.umd.js'))

import { TextEncoder, TextDecoder } from 'util'
global.TextEncoder = TextEncoder
global.TextDecoder = TextDecoder as any
import './polyfill'

import { JSDOM } from 'jsdom'
import { template } from 'rehtm'
Expand Down
4 changes: 3 additions & 1 deletion src/test/exports.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {
onPropertyChanged, currentNode, hooksMeta, ownerDocument,
ATTRIBUTE_REMOVED, onAttribute, onProperty, onCleanup, on,
component, FunctionalComponent, ClassBasedComponent,
useDispatch,
useDispatch, onHydrated, onFirstRender,
} from '../index'


Expand All @@ -29,6 +29,8 @@ test('stuff are exported properly.', () => {
expect(onCleanup).toBeDefined()
expect(on).toBeDefined()
expect(useDispatch).toBeDefined()
expect(onHydrated).toBeDefined()
expect(onFirstRender).toBeDefined()

expect(component).toBeDefined()
expect(<FunctionalComponent>{}).toBeDefined()
Expand Down
44 changes: 44 additions & 0 deletions src/test/hooks/on-first-render.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { polyfillDSD } from '../polyfill'

import { JSDOM } from 'jsdom'
import { re } from 'rehtm'

import { using } from '../../define'
import { onFirstRender } from '../../ssr-hooks'


describe(onFirstRender, () => {
test('is not called when hydrated.', () => {
const cb = jest.fn()

const window = new JSDOM('<ofr-1><template shadowrootmode="open"><div>Hellow</div></template></ofr-1>').window as any
polyfillDSD(window.document)

const { template } = re(window.document)

using({ window }).define('ofr-1', () => {
onFirstRender(cb)

return template`<div>Hi!</div>`
})

expect(cb).not.toHaveBeenCalled()
})

test('is called when not hydrated.', () => {
const cb = jest.fn()

const window = new JSDOM('<ofr-2></ofr-2>').window as any
polyfillDSD(window.document)

const { template } = re(window.document)

using({ window }).define('ofr-2', () => {
onFirstRender(cb)

return template`<div>Hi!</div>`
})

expect(cb).toHaveBeenCalledWith(window.document.querySelector('ofr-2'))
})
})
44 changes: 44 additions & 0 deletions src/test/hooks/on-hydrated.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { polyfillDSD } from '../polyfill'

import { JSDOM } from 'jsdom'
import { re } from 'rehtm'

import { using } from '../../define'
import { onHydrated } from '../../ssr-hooks'


describe(onHydrated, () => {
test('is called when hydrated.', () => {
const cb = jest.fn()

const window = new JSDOM('<oh-1><template shadowrootmode="open"><div>Hellow</div></template></oh-1>').window as any
polyfillDSD(window.document)

const { template } = re(window.document)

using({ window }).define('oh-1', () => {
onHydrated(cb)

return template`<div>Hi!</div>`
})

expect(cb).toHaveBeenCalledWith(window.document.querySelector('oh-1'))
})

test('is not called when not hydrated.', () => {
const cb = jest.fn()

const window = new JSDOM('<oh-2></oh-2>').window as any
polyfillDSD(window.document)

const { template } = re(window.document)

using({ window }).define('oh-2', () => {
onHydrated(cb)

return template`<div>Hi!</div>`
})

expect(cb).not.toHaveBeenCalled()
})
})

0 comments on commit bbcc149

Please sign in to comment.