@chronocide/hyper 0.3.1 → 0.3.2

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/README.md CHANGED
@@ -1,9 +1,9 @@
1
- <div style="text-align: center">
1
+ <div align="center">
2
2
  <h1>@chronocide/hyper</h1>
3
- <p>Tiny <b>TSX</b> DOM library.</p>
3
+ <p>Tiny DOM library</p>
4
4
  </div>
5
5
 
6
- <div style="text-align: center">
6
+ <div align="center">
7
7
  <a href="/LICENSE">
8
8
  <img alt="License AGPLv3" src="https://img.shields.io/badge/license-AGPLv3-blue.svg" />
9
9
  </a>
@@ -13,10 +13,13 @@
13
13
  </a>
14
14
  </div>
15
15
 
16
- Hyper is a tiny TypeScript library designed to ease working with the DOM. Hyper tries to be as simple as possible whilst maintaining good developer experience and currently features:
16
+ ---
17
17
 
18
- - Relies on native API's (DOM)
19
- - All state is stored within the DOM[*](#exception), no vDOM
18
+ `hyper` is a tiny TypeScript library designed to ease working with the DOM. `hyper` tries to be as simple as possible whilst maintaining good developer experience and currently features:
19
+
20
+ - Simple wrapper around native API's (DOM)
21
+ - No vDOM, all state is stored within the DOM[*](#exception)
22
+ - List caching
20
23
 
21
24
  <p id="exception"><code>document</code> is stored internally, this prevents binding it for every single call.</p>
22
25
 
@@ -28,7 +31,7 @@ npm i @chronocide/hyper
28
31
 
29
32
  ## Usage
30
33
 
31
- ```TS
34
+ ```ts
32
35
  import h from '@chronocide/hyper';
33
36
 
34
37
  const img = h('img')({ src: '/cat.png' })(); // HTMLImageElement
@@ -38,30 +41,31 @@ document.body.appendChild(img);
38
41
 
39
42
  ### List
40
43
 
41
- Components are cached and only updated if the data is changed, order does not matter. Data does not need to be unique, duplicate nodes are cloned.
44
+ List items can be cached using `list`, only updated if the data is changed; order does not matter. Data does not need to be unique, as duplicate nodes are cloned.
42
45
 
43
- ```TS
46
+ ```ts
44
47
  import type { Component } from '@chronocide/hyper';
45
- import { list } from '@chronocide/hyper';
48
+
49
+ import h, { list } from '@chronocide/hyper';
46
50
 
47
51
  type Planet = { id: string; name: string };
48
52
 
49
- const data: Planet[] = [
53
+ const planets: Planet[] = [
50
54
  { id: 'jupiter', name: 'Jupiter' },
51
55
  { id: 'mars', name: 'Mars' },
52
56
  { id: 'pluto', name: 'Pluto' }
53
57
  ];
54
58
 
55
- const ul = h('ul')()();
59
+ const ul = h('ul')()(); // <ul></ul>
56
60
  const component: Component<Planet> = planet => h('li')()(planet.name);
57
61
 
58
62
  const update = list<Planet>(component)(ul);
59
- update(data);
63
+ update(planets); // <ul><li>Jupiter</li><li>Mars</li><li>Pluto</li></ul>
60
64
  ```
61
65
 
62
- ### Testing
66
+ ## Testing
63
67
 
64
- Hyper relies on the DOM, which may not always be available. In those cases, it's possible to set a custom DOM using `env`:
68
+ `hyper` relies on the DOM, which may not always be available. In those cases, it's possible to set a custom DOM using `env`:
65
69
 
66
70
  ```TS
67
71
  import { env } from '@chronocide/hyper';
@@ -75,7 +79,7 @@ Examples can be found in the test files, such as [hyper.spec.ts](/src/hyper.spec
75
79
 
76
80
  ## Development
77
81
 
78
- Hyper uses `puppeteer` for browser testing and does not install Chrome by default. To run tests, create an `.env` file by running
82
+ `hyper` uses `puppeteer` for browser testing and does not install Chrome by default. To run tests, create an `.env` file using:
79
83
 
80
84
  ```sh
81
85
  npm run env
package/dist/hyper.d.ts CHANGED
@@ -1,24 +1,22 @@
1
- type Attributes = Record<string, unknown>;
2
-
3
- type Child = Node | string;
4
- type HTMLVoidElementTagName = 'area' | 'base' | 'br' | 'col' | 'embed' | 'hr' | 'img' | 'input' | 'link' | 'meta' | 'source' | 'track' | 'wbr';
5
-
6
- declare class Env {
7
- private _document;
8
- get document(): Document;
9
- set document(document: Document);
10
- constructor();
11
- }
12
-
13
- type Component<T> = (data: T) => Element;
14
- declare const _default$1: <T>(component: Component<T>) => (root: Element) => (next: T[]) => void;
15
-
16
- declare const env: Env;
17
- declare const _default: <T extends keyof HTMLElementTagNameMap>(tag: T) => <P extends Attributes>(attributes?: P | undefined) => (...children: T extends HTMLVoidElementTagName ? never[] : Child[]) => HTMLElementTagNameMap[T];
18
-
19
- declare const svg: <T extends keyof SVGElementTagNameMap>(tag: T) => <P extends Attributes>(attributes?: P | undefined) => (...children: Child[]) => SVGElementTagNameMap[T];
20
- declare const mathml: <T extends keyof MathMLElementEventMap>(tag: T) => <P extends Attributes>(attributes?: P | undefined) => (...children: Child[]) => MathMLElement;
21
- declare const xml: (tag: string) => <P extends Attributes>(attributes?: P) => (...children: Child[]) => HTMLElement;
22
-
23
- export { _default as default, env, _default$1 as list, mathml, svg, xml };
24
- export type { Attributes, Child, Component, HTMLVoidElementTagName };
1
+ type Attributes = Record<string, unknown>;
2
+ type Child = Node | string;
3
+ type HTMLVoidElementTagName = 'area' | 'base' | 'br' | 'col' | 'embed' | 'hr' | 'img' | 'input' | 'link' | 'meta' | 'source' | 'track' | 'wbr';
4
+ type Component<T> = (data: T) => Element;
5
+
6
+ declare class Env {
7
+ private _document;
8
+ get document(): Document;
9
+ set document(document: Document);
10
+ constructor();
11
+ }
12
+
13
+ declare const env: Env;
14
+ declare const _default: <T extends keyof HTMLElementTagNameMap>(tag: T) => <P extends Attributes>(attributes?: P | undefined) => (...children: T extends HTMLVoidElementTagName ? never[] : Child[]) => HTMLElementTagNameMap[T];
15
+
16
+ declare const svg: <T extends keyof SVGElementTagNameMap>(tag: T) => <P extends Attributes>(attributes?: P | undefined) => (...children: Child[]) => SVGElementTagNameMap[T];
17
+ declare const mathml: <T extends keyof MathMLElementEventMap>(tag: T) => <P extends Attributes>(attributes?: P | undefined) => (...children: Child[]) => MathMLElement;
18
+ declare const xml: (tag: string) => <P extends Attributes>(attributes?: P) => (...children: Child[]) => HTMLElement;
19
+ declare const list: <T>(component: Component<T>) => (root: Element) => (next: T[]) => void;
20
+
21
+ export { _default as default, env, list, mathml, svg, xml };
22
+ export type { Attributes, Child, Component, HTMLVoidElementTagName };
package/dist/hyper.js CHANGED
@@ -1,69 +1,68 @@
1
- const maybe = (fn) => (x) => {
2
- if (x === null || x === void 0) return null;
3
- return fn(x);
4
- };
5
-
6
- const attributes = (element) => (attributes2) => Object.entries(attributes2).forEach(([k, v]) => {
7
- if (typeof v === "string") element.setAttribute(k, v);
8
- if (typeof v === "number") element.setAttribute(k, `${v}`);
9
- if (v === true) element.toggleAttribute(k, v);
10
- });
11
-
12
- const create = (element) => (attributes$1) => (children) => {
13
- maybe(attributes(element))(attributes$1);
14
- element.append(...children);
15
- return element;
16
- };
17
- const html = (document) => (tag) => (attributes) => (...children) => create(document.createElement(tag))(attributes)(children);
18
- const svg$1 = (document) => (tag) => (attributes) => (...children) => create(document.createElementNS("http://www.w3.org/2000/svg", tag))(attributes)(children);
19
- const mathml$1 = (document) => (tag) => (attributes) => (...children) => create(document.createElementNS("http://www.w3.org/1998/Math/MathML", tag))(attributes)(children);
20
- const xml$1 = (document) => (tag) => (attributes) => (...children) => create(document.createElementNS("http://www.w3.org/1999/xhtml", tag))(attributes)(children);
21
-
22
- class Env {
23
- _document;
24
- get document() {
25
- if (!this._document) throw new Error("Missing document");
26
- return this._document;
27
- }
28
- set document(document2) {
29
- this._document = document2;
30
- }
31
- constructor() {
32
- this._document = typeof document === "undefined" ? null : document;
33
- }
34
- }
35
-
36
- var list = (component) => (root) => {
37
- const cache = /* @__PURE__ */ new Map();
38
- return (next) => {
39
- const refs = /* @__PURE__ */ new WeakSet();
40
- while (root.children.length > next.length) root.lastChild?.remove();
41
- next.forEach((data, i) => {
42
- const child = root.children.item(i);
43
- let element = cache.get(data);
44
- if (element === child) return;
45
- if (!element) {
46
- element = component(data);
47
- cache.set(data, element);
48
- }
49
- if (refs.has(element)) {
50
- element = element.cloneNode(true);
51
- } else {
52
- refs.add(element);
53
- }
54
- if (child) {
55
- root.replaceChild(element, child);
56
- } else {
57
- root.appendChild(element);
58
- }
59
- });
60
- };
61
- };
62
-
63
- const env = new Env();
64
- var hyper = (tag) => html(env.document)(tag);
65
- const svg = (tag) => svg$1(env.document)(tag);
66
- const mathml = (tag) => mathml$1(env.document)(tag);
67
- const xml = (tag) => xml$1(env.document)(tag);
68
-
69
- export { hyper as default, env, list, mathml, svg, xml };
1
+ const maybe = (fn) => (x) => {
2
+ if (x === null || x === void 0) return null;
3
+ return fn(x);
4
+ };
5
+
6
+ const setAttributes = (element) => (attributes) => Object.entries(attributes).forEach(([k, v]) => {
7
+ if (typeof v === "string") element.setAttribute(k, v);
8
+ if (typeof v === "number") element.setAttribute(k, `${v}`);
9
+ if (v === true) element.toggleAttribute(k, v);
10
+ });
11
+ const create = (element) => (attributes) => (children) => {
12
+ maybe(setAttributes(element))(attributes);
13
+ element.append(...children);
14
+ return element;
15
+ };
16
+ const html = (document) => (tag) => (attributes) => (...children) => create(document.createElement(tag))(attributes)(children);
17
+ const svg$1 = (document) => (tag) => (attributes) => (...children) => create(document.createElementNS("http://www.w3.org/2000/svg", tag))(attributes)(children);
18
+ const mathml$1 = (document) => (tag) => (attributes) => (...children) => create(document.createElementNS("http://www.w3.org/1998/Math/MathML", tag))(attributes)(children);
19
+ const xml$1 = (document) => (tag) => (attributes) => (...children) => create(document.createElementNS("http://www.w3.org/1999/xhtml", tag))(attributes)(children);
20
+ const list$1 = (component) => (root) => {
21
+ const cache = /* @__PURE__ */ new Map();
22
+ return (next) => {
23
+ const refs = /* @__PURE__ */ new WeakSet();
24
+ while (root.children.length > next.length) root.lastChild?.remove();
25
+ next.forEach((data, i) => {
26
+ const child = root.children.item(i);
27
+ let element = cache.get(data);
28
+ if (element === child) return;
29
+ if (!element) {
30
+ element = component(data);
31
+ cache.set(data, element);
32
+ }
33
+ if (refs.has(element)) {
34
+ element = element.cloneNode(true);
35
+ } else {
36
+ refs.add(element);
37
+ }
38
+ if (child) {
39
+ root.replaceChild(element, child);
40
+ } else {
41
+ root.appendChild(element);
42
+ }
43
+ });
44
+ };
45
+ };
46
+
47
+ class Env {
48
+ _document;
49
+ get document() {
50
+ if (!this._document) throw new Error("Missing document");
51
+ return this._document;
52
+ }
53
+ set document(document2) {
54
+ this._document = document2;
55
+ }
56
+ constructor() {
57
+ this._document = typeof document === "undefined" ? null : document;
58
+ }
59
+ }
60
+
61
+ const env = new Env();
62
+ var hyper = (tag) => html(env.document)(tag);
63
+ const svg = (tag) => svg$1(env.document)(tag);
64
+ const mathml = (tag) => mathml$1(env.document)(tag);
65
+ const xml = (tag) => xml$1(env.document)(tag);
66
+ const list = list$1;
67
+
68
+ export { hyper as default, env, list, mathml, svg, xml };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@chronocide/hyper",
3
- "version": "0.3.1",
3
+ "version": "0.3.2",
4
4
  "type": "module",
5
5
  "types": "dist/hyper.d.ts",
6
6
  "exports": {
@@ -11,24 +11,26 @@
11
11
  "dist/**/*"
12
12
  ],
13
13
  "engines": {
14
- "node": ">=20.0.0"
14
+ "node": ">=24.11.1"
15
15
  },
16
16
  "author": "Chronocide",
17
17
  "license": "AGPL-3.0-only",
18
18
  "scripts": {
19
- "env": "node --experimental-strip-types --no-warnings scripts/env.ts",
20
- "test": "node --env-file=.env --experimental-strip-types --no-warnings --test src/**/*.spec.ts",
19
+ "env": "node scripts/env.ts",
20
+ "test": "node --env-file=.env --test src/**/*.spec.ts",
21
21
  "build": "rollup -c",
22
22
  "preversion": "npm run test",
23
23
  "version": "npm run build && git add -A dist",
24
24
  "postversion": "git push && git push --tags"
25
25
  },
26
+ "optionalDependencies": {
27
+ "eslint": "^9.28.0",
28
+ "@chronocide/eslint-config": "github:chronoDave/eslint-config"
29
+ },
26
30
  "devDependencies": {
27
- "@chronocide/eslint-config": "github:chronoDave/eslint-config",
28
31
  "@types/jsdom": "^21.1.7",
29
32
  "@types/node": "^22.15.29",
30
33
  "esbuild": "^0.25.5",
31
- "eslint": "^9.28.0",
32
34
  "jsdom": "^26.1.0",
33
35
  "puppeteer-core": "^24.14.0",
34
36
  "rollup": "^4.42.0",