npm package: @knno/dom
Description: A small library for create web page
Author: Thor Qin
Latest version: 1.2.3

A small kit to simplify DOM operation.

# Install

```
npm i @knno/dom
```

# Wrap existing elements

```js
// query by selector 
dom.query('div.some-class > #id1')
// warp dom elements to Nodes object
const a = document.createElement('div')
const b = document.createElement('div')
dom.wrap(a)
dom.wrap(a, b)
dom.wrap(...document.querySelectorAll('div'))
```

# Build DOM tree

```js
// create a element and specify class name
dom.new('div', 'class1', 'class2', someClassName ...) 
dom.new('div', 'class1 class2')
// or
dom.div('class1', 'class2' ...)
dom.span('class1 class2 class3', someClassName)
...
// Example:
let input;
dom.div('container').css({
  display: 'flex',
  flexDirection: 'column',
}).append(
  dom.div('header').text('Title'),
  dom.div('content').append(
    dom.input().name('search').ref((ipt) => input = ipt),
    dom.button().text('Search').on('click', () => {
      const keyword = input.value();
      // do search operation ...
    })
  )
).appendTo(document.body)

```

# Convert HTML string to Nodes object 

```js
dom.html('<div>example</div>')
```

# Can work with jsdom
```js
const JSDom = require('jsdom')
const { createDom } = require('@knno/dom')

const jsDom = new JSDom.JSDOM();
const doc = jsDom.window.document;
const dom = createDom(doc)
...

console.log(jsDom.serialize());
```

# Support JSX

Enable JSX option.

```js
// Modify your tsconfig.json, add jsx related fields as follow:
{
  "compilerOptions": {
    // ...
    "moduleResolution": "nodenext",
    "jsx": "react",
    "jsxFactory": "h",
    "jsxFragmentFactory": "fragment",
  }
}
```

TSX code:

```tsx
// index.tsx
import { dom, render } from '@knno/dom';
import { h, fragment, JSXComponent, JSXProps } from '@knno/dom/jsx';

interface MyProp {
  title: string;
}

// create component by jsx
function C1(prop: MyProp) {
  return (
    <div>{prop.title}</div>
  )
}

// create component without jsx
function C2(prop: MyProp) {
  return dom.div().text(prop.title);
}

// use jsx fragments
function C3() {
  return (
    <>
      <C1 title="hello 3" />
      <C2 title="hello 4" />
    </>
  );
}

// create custom component by class 
interface CustomProp extends JSXProps<CustomComponent> {
  title: string;
  ontitlechanged?: (evt: CustomEvent<string>) => void;
}
class CustomComponent extends JSXComponent {
  constructor(props: CustomProp, children: Nodes[]) {
    super(<div style={{ border: '1px solid #ccc', padding: '1em' }}>
      <h1>{props.title}</h1>
      <div>{...children}</div>
    </div>, props);
  }

  changeTitle(ttile: string) {
    this.query(':scope>h1').text(ttile);
    this.emit('titlechanged', ttile);
  }
}

// entry
render(
  <main>
    <div onclick={() => console.log('click 1')}>
      <C1 title="hello 1" />
    </div>
    <div style={{ color: 'red' }}>
      <C2 title="hello 2" />
    </div>
    <div class="some class">
      <C3 />
    </div>
    <CustomComponent title="hello 5" onclick={function () {
      this.changeTitle('new title');
    }} ontitlechanged={function (evt) {
      console.log('title changed, new title is:', evt.detail);
    }}>
      <p>text body line 1</p>
      <p>text body line 2</p>
    </CustomComponent>
  </main>
);

```

# Support server side render

```tsx
import { renderToString } from '@knno/dom';
import { h, fragment } from '@knno/dom/jsx';

const text = renderToString(() => <div>Hello world!</div>)
console.log(text);
// or send text to client
```