@thi.ng/wasm-api-dom
Advanced tools
Comparing version 0.11.104 to 1.0.0
# Change Log | ||
- **Last updated**: 2024-08-10T15:03:07Z | ||
- **Last updated**: 2024-08-18T14:11:34Z | ||
- **Generator**: [thi.ng/monopub](https://thi.ng/monopub) | ||
@@ -12,2 +12,17 @@ | ||
# [1.0.0](https://github.com/thi-ng/umbrella/tree/@thi.ng/wasm-api-dom@1.0.0) (2024-08-18) | ||
#### 🛑 Breaking changes | ||
- update WasmDom, add WasmDomModule spec ([51bedd2](https://github.com/thi-ng/umbrella/commit/51bedd2)) | ||
- BREAKING CHANGE: update WasmDom, add WasmDomModule spec | ||
#### ⏱ Performance improvements | ||
- update typedefs, optimize/minimize generated TS code ([08c6e01](https://github.com/thi-ng/umbrella/commit/08c6e01)) | ||
#### ♻️ Refactoring | ||
- regenerate types ([ef98da6](https://github.com/thi-ng/umbrella/commit/ef98da6)) | ||
### [0.11.89](https://github.com/thi-ng/umbrella/tree/@thi.ng/wasm-api-dom@0.11.89) (2024-04-22) | ||
@@ -14,0 +29,0 @@ |
19
dom.d.ts
import type { NumOrString } from "@thi.ng/api"; | ||
import { type IWasmAPI, type ReadonlyWasmString, type WasmBridge, type WasmType } from "@thi.ng/wasm-api"; | ||
import { type IWasmAPI, type ReadonlyWasmString, type WasmBridge, type WasmModuleSpec, type WasmType } from "@thi.ng/wasm-api"; | ||
import { ObjectIndex } from "@thi.ng/wasm-api/object-index"; | ||
import { type CreateElementOpts, type WasmDomExports, type WasmDomImports, type Event as WasmEvent } from "./api.js"; | ||
/** | ||
* WASM module descriptor for use as dependency object for other module | ||
* definitions or direct use with | ||
* [`WasmBridge`](https://docs.thi.ng/umbrella/wasm-api/classes/WasmBridge.html). | ||
* | ||
* @remarks | ||
* Module defines the following dependencies: | ||
* | ||
* - none | ||
* | ||
* See | ||
* [`WasmModuleSpec`](https://docs.thi.ng/umbrella/wasm-api/interfaces/WasmModuleSpec.html) | ||
* for more details. | ||
*/ | ||
export declare const WasmDomModule: WasmModuleSpec<WasmDomExports>; | ||
/** @internal */ | ||
@@ -13,4 +28,2 @@ interface WasmListener { | ||
export declare class WasmDom implements IWasmAPI<WasmDomExports> { | ||
static readonly id = "dom"; | ||
readonly id = "dom"; | ||
parent: WasmBridge<WasmDomExports>; | ||
@@ -17,0 +30,0 @@ $Event: WasmType<WasmEvent>; |
@@ -16,2 +16,6 @@ import { adaptDPI } from "@thi.ng/canvas"; | ||
} from "./api.js"; | ||
const WasmDomModule = { | ||
id: "dom", | ||
factory: () => new WasmDom() | ||
}; | ||
const __listeners = "__wasm_listeners"; | ||
@@ -38,4 +42,2 @@ const EVENT_MAP = [ | ||
class WasmDom { | ||
static id = "dom"; | ||
id = WasmDom.id; | ||
parent; | ||
@@ -331,3 +333,4 @@ $Event; | ||
export { | ||
WasmDom | ||
WasmDom, | ||
WasmDomModule | ||
}; |
/** | ||
* Generated by @thi.ng/wasm-api-bindgen at 2023-03-26T00:14:48.760Z | ||
* Generated by @thi.ng/wasm-api-bindgen at 2024-08-17T15:49:39.193Z | ||
* DO NOT EDIT! | ||
@@ -136,3 +136,3 @@ */ | ||
*/ | ||
value: WasmStringPtr; | ||
readonly value: WasmStringPtr; | ||
/** | ||
@@ -162,3 +162,3 @@ * Length of the value string | ||
*/ | ||
key: Uint8Array; | ||
readonly key: Uint8Array; | ||
/** | ||
@@ -398,10 +398,10 @@ * Number of characters of the `key` string | ||
export interface EventBody extends WasmTypeBase { | ||
drag: DragEvent; | ||
input: InputEvent; | ||
key: KeyEvent; | ||
mouse: MouseEvent; | ||
pointer: PointerEvent; | ||
scroll: ScrollEvent; | ||
touch: TouchEvent; | ||
wheel: WheelEvent; | ||
readonly drag: DragEvent; | ||
readonly input: InputEvent; | ||
readonly key: KeyEvent; | ||
readonly mouse: MouseEvent; | ||
readonly pointer: PointerEvent; | ||
readonly scroll: ScrollEvent; | ||
readonly touch: TouchEvent; | ||
readonly wheel: WheelEvent; | ||
} | ||
@@ -436,3 +436,3 @@ export declare const $EventBody: WasmTypeConstructor<EventBody>; | ||
*/ | ||
body: EventBody; | ||
readonly body: EventBody; | ||
} | ||
@@ -444,21 +444,2 @@ export declare const $Event: WasmTypeConstructor<Event>; | ||
export interface EventListener extends WasmTypeBase { | ||
/** | ||
* Event listener function. Takes an event and optional pointer to user supplied | ||
* arbitrary context data provided when registering the handler via | ||
* `addListener()` | ||
* | ||
* @remarks | ||
* Zig type: `u32` | ||
*/ | ||
callback: number; | ||
/** | ||
* Optional type erased pointer to arbitrary user context. This pointer can be | ||
* cast back into the desired type using this form: | ||
* `@ptrCast(?*Foo, @alignCast(@alignOf(Foo), raw))` | ||
* Also see: `wasmapi.ptrCast()` | ||
* | ||
* @remarks | ||
* Zig type: `?u32` | ||
*/ | ||
ctx: number; | ||
} | ||
@@ -475,23 +456,23 @@ export declare const $EventListener: WasmTypeConstructor<EventListener>; | ||
*/ | ||
tag: WasmStringPtr; | ||
readonly tag: WasmStringPtr; | ||
/** | ||
* Namespace URI or wellknown registered alias (e.g. svg, xlink, xmlns) | ||
*/ | ||
ns: WasmStringPtr; | ||
readonly ns: WasmStringPtr; | ||
/** | ||
* ID attrib | ||
*/ | ||
id: WasmStringPtr; | ||
readonly id: WasmStringPtr; | ||
/** | ||
* Element class attrib | ||
*/ | ||
class: WasmStringPtr; | ||
readonly class: WasmStringPtr; | ||
/** | ||
* Element inner text body | ||
*/ | ||
text: WasmStringPtr; | ||
readonly text: WasmStringPtr; | ||
/** | ||
* Element inner HTML body | ||
*/ | ||
html: WasmStringPtr; | ||
readonly html: WasmStringPtr; | ||
/** | ||
@@ -504,3 +485,3 @@ * Parent element ID. If >=0 the new element will be attached to that parent | ||
*/ | ||
parent: number; | ||
readonly parent: number; | ||
/** | ||
@@ -512,3 +493,3 @@ * Insertion index for new element or -1 to append (default) | ||
*/ | ||
index: number; | ||
readonly index: number; | ||
/** | ||
@@ -518,3 +499,3 @@ * Optional slice of child element specs, which will be automatically attached | ||
*/ | ||
children: CreateElementOpts[]; | ||
readonly children: CreateElementOpts[]; | ||
/** | ||
@@ -524,3 +505,3 @@ * Optional slice of attribute definitions for this element. Also see provided | ||
*/ | ||
attribs: Attrib[]; | ||
readonly attribs: Attrib[]; | ||
} | ||
@@ -539,3 +520,3 @@ export declare const $CreateElementOpts: WasmTypeConstructor<CreateElementOpts>; | ||
*/ | ||
width: number; | ||
readonly width: number; | ||
/** | ||
@@ -547,11 +528,11 @@ * Canvas height (in CSS pixels) | ||
*/ | ||
height: number; | ||
readonly height: number; | ||
/** | ||
* Element ID attrib | ||
*/ | ||
id: WasmStringPtr; | ||
readonly id: WasmStringPtr; | ||
/** | ||
* Element class attrib | ||
*/ | ||
class: WasmStringPtr; | ||
readonly class: WasmStringPtr; | ||
/** | ||
@@ -563,3 +544,3 @@ * Same as CreateElementOpts.parent | ||
*/ | ||
parent: number; | ||
readonly parent: number; | ||
/** | ||
@@ -571,3 +552,3 @@ * Same as CreateElementOpts.index | ||
*/ | ||
index: number; | ||
readonly index: number; | ||
/** | ||
@@ -580,3 +561,3 @@ * Device pixel ratio for computing physical pixel dimensions, see | ||
*/ | ||
dpr: number; | ||
readonly dpr: number; | ||
/** | ||
@@ -586,3 +567,3 @@ * Optional slice of attribute definitions for this element. Also see provided | ||
*/ | ||
attribs: Attrib[]; | ||
readonly attribs: Attrib[]; | ||
} | ||
@@ -594,18 +575,18 @@ export declare const $CreateCanvasOpts: WasmTypeConstructor<CreateCanvasOpts>; | ||
export interface Attrib extends WasmTypeBase { | ||
name: WasmStringPtr; | ||
value: AttribValue; | ||
kind: AttribType; | ||
readonly name: WasmStringPtr; | ||
readonly value: AttribValue; | ||
readonly kind: AttribType; | ||
} | ||
export declare const $Attrib: WasmTypeConstructor<Attrib>; | ||
export interface AttribValue extends WasmTypeBase { | ||
event: EventListener; | ||
readonly event: EventListener; | ||
/** | ||
* Zig type: `u8` | ||
*/ | ||
flag: number; | ||
readonly flag: number; | ||
/** | ||
* Zig type: `f64` | ||
*/ | ||
num: number; | ||
str: WasmStringPtr; | ||
readonly num: number; | ||
readonly str: WasmStringPtr; | ||
} | ||
@@ -612,0 +593,0 @@ export declare const $AttribValue: WasmTypeConstructor<AttribValue>; |
import { Pointer, WasmStringPtr } from "@thi.ng/wasm-api"; | ||
import { __array, __instanceArray, __slice32, __primslice32 } from "@thi.ng/wasm-api/memory"; | ||
var EventType = /* @__PURE__ */ ((EventType2) => { | ||
@@ -49,5 +50,3 @@ EventType2[EventType2["UNKOWN"] = -1] = "UNKOWN"; | ||
instanceArray(base, num) { | ||
const items = []; | ||
for (; num-- > 0; base += 16) items.push(this.instance(base)); | ||
return items; | ||
return __instanceArray(this, base, num); | ||
}, | ||
@@ -109,5 +108,3 @@ instance: (base) => { | ||
instanceArray(base, num) { | ||
const items = []; | ||
for (; num-- > 0; base += 8) items.push(this.instance(base)); | ||
return items; | ||
return __instanceArray(this, base, num); | ||
}, | ||
@@ -177,5 +174,3 @@ instance: (base) => { | ||
instanceArray(base, num) { | ||
const items = []; | ||
for (; num-- > 0; base += 12) items.push(this.instance(base)); | ||
return items; | ||
return __instanceArray(this, base, num); | ||
}, | ||
@@ -224,5 +219,3 @@ instance: (base) => { | ||
instanceArray(base, num) { | ||
const items = []; | ||
for (; num-- > 0; base += 19) items.push(this.instance(base)); | ||
return items; | ||
return __instanceArray(this, base, num); | ||
}, | ||
@@ -273,5 +266,3 @@ instance: (base) => { | ||
instanceArray(base, num) { | ||
const items = []; | ||
for (; num-- > 0; base += 8) items.push(this.instance(base)); | ||
return items; | ||
return __instanceArray(this, base, num); | ||
}, | ||
@@ -334,5 +325,3 @@ instance: (base) => { | ||
instanceArray(base, num) { | ||
const items = []; | ||
for (; num-- > 0; base += 24) items.push(this.instance(base)); | ||
return items; | ||
return __instanceArray(this, base, num); | ||
}, | ||
@@ -442,5 +431,3 @@ instance: (base) => { | ||
instanceArray(base, num) { | ||
const items = []; | ||
for (; num-- > 0; base += 8) items.push(this.instance(base)); | ||
return items; | ||
return __instanceArray(this, base, num); | ||
}, | ||
@@ -483,5 +470,3 @@ instance: (base) => { | ||
instanceArray(base, num) { | ||
const items = []; | ||
for (; num-- > 0; base += 6) items.push(this.instance(base)); | ||
return items; | ||
return __instanceArray(this, base, num); | ||
}, | ||
@@ -530,5 +515,3 @@ instance: (base) => { | ||
instanceArray(base, num) { | ||
const items = []; | ||
for (; num-- > 0; base += 10) items.push(this.instance(base)); | ||
return items; | ||
return __instanceArray(this, base, num); | ||
}, | ||
@@ -597,5 +580,3 @@ instance: (base) => { | ||
instanceArray(base, num) { | ||
const items = []; | ||
for (; num-- > 0; base += 24) items.push(this.instance(base)); | ||
return items; | ||
return __instanceArray(this, base, num); | ||
}, | ||
@@ -613,46 +594,22 @@ instance: (base) => { | ||
}, | ||
set drag(x) { | ||
mem.u8.set(x.__bytes, base); | ||
}, | ||
get input() { | ||
return $InputEvent(mem).instance(base); | ||
}, | ||
set input(x) { | ||
mem.u8.set(x.__bytes, base); | ||
}, | ||
get key() { | ||
return $KeyEvent(mem).instance(base); | ||
}, | ||
set key(x) { | ||
mem.u8.set(x.__bytes, base); | ||
}, | ||
get mouse() { | ||
return $MouseEvent(mem).instance(base); | ||
}, | ||
set mouse(x) { | ||
mem.u8.set(x.__bytes, base); | ||
}, | ||
get pointer() { | ||
return $PointerEvent(mem).instance(base); | ||
}, | ||
set pointer(x) { | ||
mem.u8.set(x.__bytes, base); | ||
}, | ||
get scroll() { | ||
return $ScrollEvent(mem).instance(base); | ||
}, | ||
set scroll(x) { | ||
mem.u8.set(x.__bytes, base); | ||
}, | ||
get touch() { | ||
return $TouchEvent(mem).instance(base); | ||
}, | ||
set touch(x) { | ||
mem.u8.set(x.__bytes, base); | ||
}, | ||
get wheel() { | ||
return $WheelEvent(mem).instance(base); | ||
}, | ||
set wheel(x) { | ||
mem.u8.set(x.__bytes, base); | ||
} | ||
@@ -670,5 +627,3 @@ }; | ||
instanceArray(base, num) { | ||
const items = []; | ||
for (; num-- > 0; base += 32) items.push(this.instance(base)); | ||
return items; | ||
return __instanceArray(this, base, num); | ||
}, | ||
@@ -697,5 +652,2 @@ instance: (base) => { | ||
return $EventBody(mem).instance(base + 8); | ||
}, | ||
set body(x) { | ||
mem.u8.set(x.__bytes, base + 8); | ||
} | ||
@@ -713,5 +665,3 @@ }; | ||
instanceArray(base, num) { | ||
const items = []; | ||
for (; num-- > 0; base += 8) items.push(this.instance(base)); | ||
return items; | ||
return __instanceArray(this, base, num); | ||
}, | ||
@@ -725,14 +675,2 @@ instance: (base) => { | ||
return mem.u8.subarray(base, base + 8); | ||
}, | ||
get callback() { | ||
return mem.u32[base >>> 2]; | ||
}, | ||
set callback(x) { | ||
mem.u32[base >>> 2] = x; | ||
}, | ||
get ctx() { | ||
return mem.u32[base + 4 >>> 2]; | ||
}, | ||
set ctx(x) { | ||
mem.u32[base + 4 >>> 2] = x; | ||
} | ||
@@ -750,5 +688,3 @@ }; | ||
instanceArray(base, num) { | ||
const items = []; | ||
for (; num-- > 0; base += 48) items.push(this.instance(base)); | ||
return items; | ||
return __instanceArray(this, base, num); | ||
}, | ||
@@ -790,26 +726,10 @@ instance: (base) => { | ||
}, | ||
set parent(x) { | ||
mem.i32[base + 24 >>> 2] = x; | ||
}, | ||
get index() { | ||
return mem.i32[base + 28 >>> 2]; | ||
}, | ||
set index(x) { | ||
mem.i32[base + 28 >>> 2] = x; | ||
}, | ||
get children() { | ||
const addr = mem.u32[base + 32 >>> 2]; | ||
const len = mem.u32[base + 36 >>> 2]; | ||
const inst = $CreateElementOpts(mem); | ||
const buf = []; | ||
for (let i = 0; i < len; i++) buf.push(inst.instance(addr + i * 48)); | ||
return buf; | ||
return __slice32(mem, $CreateElementOpts, base + 32); | ||
}, | ||
get attribs() { | ||
const addr = mem.u32[base + 40 >>> 2]; | ||
const len = mem.u32[base + 44 >>> 2]; | ||
const inst = $Attrib(mem); | ||
const buf = []; | ||
for (let i = 0; i < len; i++) buf.push(inst.instance(addr + i * 24)); | ||
return buf; | ||
return __slice32(mem, $Attrib, base + 40); | ||
} | ||
@@ -827,5 +747,3 @@ }; | ||
instanceArray(base, num) { | ||
const items = []; | ||
for (; num-- > 0; base += 32) items.push(this.instance(base)); | ||
return items; | ||
return __instanceArray(this, base, num); | ||
}, | ||
@@ -845,11 +763,5 @@ instance: (base) => { | ||
}, | ||
set width(x) { | ||
mem.u16[base >>> 1] = x; | ||
}, | ||
get height() { | ||
return mem.u16[base + 2 >>> 1]; | ||
}, | ||
set height(x) { | ||
mem.u16[base + 2 >>> 1] = x; | ||
}, | ||
get id() { | ||
@@ -864,24 +776,10 @@ return $id || ($id = new WasmStringPtr(mem, base + 4, true)); | ||
}, | ||
set parent(x) { | ||
mem.i32[base + 12 >>> 2] = x; | ||
}, | ||
get index() { | ||
return mem.i32[base + 16 >>> 2]; | ||
}, | ||
set index(x) { | ||
mem.i32[base + 16 >>> 2] = x; | ||
}, | ||
get dpr() { | ||
return mem.u8[base + 20]; | ||
}, | ||
set dpr(x) { | ||
mem.u8[base + 20] = x; | ||
}, | ||
get attribs() { | ||
const addr = mem.u32[base + 24 >>> 2]; | ||
const len = mem.u32[base + 28 >>> 2]; | ||
const inst = $Attrib(mem); | ||
const buf = []; | ||
for (let i = 0; i < len; i++) buf.push(inst.instance(addr + i * 24)); | ||
return buf; | ||
return __slice32(mem, $Attrib, base + 24); | ||
} | ||
@@ -899,5 +797,3 @@ }; | ||
instanceArray(base, num) { | ||
const items = []; | ||
for (; num-- > 0; base += 24) items.push(this.instance(base)); | ||
return items; | ||
return __instanceArray(this, base, num); | ||
}, | ||
@@ -919,10 +815,4 @@ instance: (base) => { | ||
}, | ||
set value(x) { | ||
mem.u8.set(x.__bytes, base + 8); | ||
}, | ||
get kind() { | ||
return mem.u8[base + 16]; | ||
}, | ||
set kind(x) { | ||
mem.u8[base + 16] = x; | ||
} | ||
@@ -940,5 +830,3 @@ }; | ||
instanceArray(base, num) { | ||
const items = []; | ||
for (; num-- > 0; base += 8) items.push(this.instance(base)); | ||
return items; | ||
return __instanceArray(this, base, num); | ||
}, | ||
@@ -957,17 +845,8 @@ instance: (base) => { | ||
}, | ||
set event(x) { | ||
mem.u8.set(x.__bytes, base); | ||
}, | ||
get flag() { | ||
return mem.u8[base]; | ||
}, | ||
set flag(x) { | ||
mem.u8[base] = x; | ||
}, | ||
get num() { | ||
return mem.f64[base >>> 3]; | ||
}, | ||
set num(x) { | ||
mem.f64[base >>> 3] = x; | ||
}, | ||
get str() { | ||
@@ -974,0 +853,0 @@ return $str || ($str = new WasmStringPtr(mem, base, true)); |
{ | ||
"name": "@thi.ng/wasm-api-dom", | ||
"version": "0.11.104", | ||
"version": "1.0.0", | ||
"description": "Browser DOM bridge API for hybrid TypeScript & WASM (Zig) applications", | ||
@@ -43,11 +43,11 @@ "type": "module", | ||
"dependencies": { | ||
"@thi.ng/api": "^8.11.8", | ||
"@thi.ng/canvas": "^0.5.1", | ||
"@thi.ng/errors": "^2.5.14", | ||
"@thi.ng/prefixes": "^2.3.25", | ||
"@thi.ng/wasm-api": "^1.6.7" | ||
"@thi.ng/api": "^8.11.9", | ||
"@thi.ng/canvas": "^0.5.2", | ||
"@thi.ng/errors": "^2.5.15", | ||
"@thi.ng/prefixes": "^2.3.26", | ||
"@thi.ng/wasm-api": "^2.0.0" | ||
}, | ||
"devDependencies": { | ||
"@microsoft/api-extractor": "^7.47.5", | ||
"@thi.ng/wasm-api-bindgen": "^0.5.13", | ||
"@thi.ng/wasm-api-bindgen": "^0.6.0", | ||
"esbuild": "^0.23.0", | ||
@@ -101,6 +101,5 @@ "typedoc": "^0.26.5", | ||
"parent": "@thi.ng/wasm-api", | ||
"status": "alpha", | ||
"year": 2022 | ||
}, | ||
"gitHead": "e914ebbd81c56783c39cf746548c547cbacadc96\n" | ||
"gitHead": "f6e26ea1142525171de5d36b9c3119f2782bb437\n" | ||
} |
@@ -10,3 +10,3 @@ <!-- This file is generated - DO NOT EDIT! --> | ||
> [!NOTE] | ||
> This is one of 198 standalone projects, maintained as part | ||
> This is one of 199 standalone projects, maintained as part | ||
> of the [@thi.ng/umbrella](https://github.com/thi-ng/umbrella/) monorepo | ||
@@ -290,3 +290,3 @@ > and anti-framework. | ||
**ALPHA** - bleeding edge / work-in-progress | ||
**STABLE** - used in production | ||
@@ -315,3 +315,3 @@ [Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=%5Bwasm-api-dom%5D+in%3Atitle) | ||
Package sizes (brotli'd, pre-treeshake): ESM: 4.25 KB | ||
Package sizes (brotli'd, pre-treeshake): ESM: 4.04 KB | ||
@@ -330,3 +330,3 @@ ## Dependencies | ||
Four projects in this repo's | ||
Five projects in this repo's | ||
[/examples](https://github.com/thi-ng/umbrella/tree/develop/examples) | ||
@@ -341,2 +341,3 @@ directory are using this package: | ||
| <img src="https://raw.githubusercontent.com/thi-ng/umbrella/develop/assets/examples/zig-todo-list.png" width="240"/> | Zig-based To-Do list, DOM creation, local storage task persistence | [Demo](https://demo.thi.ng/umbrella/zig-todo-list/) | [Source](https://github.com/thi-ng/umbrella/tree/develop/examples/zig-todo-list) | | ||
| <img src="https://raw.githubusercontent.com/thi-ng/umbrella/develop/assets/examples/zig-webgl.avif" width="240"/> | Basic Zig/WebAssembly WebGL demo | [Demo](https://demo.thi.ng/umbrella/zig-webgl/) | [Source](https://github.com/thi-ng/umbrella/tree/develop/examples/zig-webgl) | | ||
@@ -343,0 +344,0 @@ ## API |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
0
370
115557
2032
63
+ Added@thi.ng/wasm-api@2.2.4(transitive)
- Removed@thi.ng/wasm-api@1.6.7(transitive)
Updated@thi.ng/api@^8.11.9
Updated@thi.ng/canvas@^0.5.2
Updated@thi.ng/errors@^2.5.15
Updated@thi.ng/prefixes@^2.3.26
Updated@thi.ng/wasm-api@^2.0.0