watch-state 3.5.0 → 3.5.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
@@ -50,12 +50,12 @@
50
50
  <a href="https://www.npmjs.com/package/watch-state" target="_blank">
51
51
  <img src="https://img.shields.io/npm/v/watch-state.svg" alt="watch-state npm">
52
52
  </a>
53
- <a href="https://bundlephobia.com/result?p=watch-state" target="_blank">
54
- <img src="https://img.shields.io/bundlephobia/minzip/watch-state" alt="watch-state minzipped size">
55
- </a>
56
53
  <a href="https://www.npmtrends.com/watch-state" target="_blank">
57
54
  <img src="https://img.shields.io/npm/dm/watch-state.svg" alt="watch-state downloads">
58
55
  </a>
56
+ <a href="https://www.typescriptlang.org" target="_blank">
57
+ <img src="https://img.shields.io/npm/types/watch-state" alt="TypeSctipt">
58
+ </a>
59
59
  <a href="https://packagequality.com/#?package=watch-state" target="_blank">
60
60
  <img src="https://packagequality.com/shield/watch-state.svg" alt="watch-state quality">
61
61
  </a>
@@ -103,7 +103,7 @@ Was born during working on [@innet/dom](https://www.npmjs.com/package/@innet/dom
103
103
  <sup>**[ [Install](#install) ]**</sup>
104
104
  <sup>**[ [Usage](#usage) ]** [Simple example](#simple-example) • [Example Vanilla JS](#example-vanilla-js) • [Example React](#example-react) • [Example @innet/dom](#example-innetdom)</sup>
105
105
  <sup>**[ [Watch](#watch) ]** [Update argument](#update-argument) • [Force update of Watch](#force-update-of-watch) • [Destroy Watch](#destroy-watch) • [Deep/Nested watchers](#deepnested-watchers)</sup>
106
- <sup>**[ [State](#state) ]** [Get or Set value](#get-or-set-value) • [Force update of State](#force-update-of-state) • [Raw value](#raw-value)</sup>
106
+ <sup>**[ [State](#state) ]** [Get or Set value](#get-or-set-value) • [Force update of State](#force-update-of-state) • [Raw value](#raw-value) • [State.set (experimental)](#stateset-experimental)</sup>
107
107
  <sup>**[ [Compute](#compute) ]** [Lazy computation](#lazy-computation) • [Force update of Compute](#force-update-of-compute) • [Destroy Compute](#destroy-compute)</sup>
108
108
  <sup>**[ [Utils](#utils) ]** [onDestroy](#ondestroy) • [callEvent](#callevent) • [createEvent](#createevent) • [unwatch](#unwatch)</sup>
109
109
  <sup>**[ [Typescript](#typescript) ]**</sup>
@@ -134,6 +134,19 @@ html
134
134
 
135
135
  <sup>[Simple example](#simple-example) • [Example Vanilla JS](#example-vanilla-js) • [Example React](#example-react) • [Example @innet/dom](#example-innetdom)</sup>
136
136
 
137
+ The library is based on the core concepts of `Observable` (something that can be observed) and `Observer` (something that can observe). On top of these concepts, the core classes `State`, `Compute`, and `Watch` are built according to the following scheme:
138
+
139
+ ```
140
+ ┌────────────┐ ┌─────────────┐
141
+ │ Observable │ │ Observer │
142
+ │ (abstract) │ │ (interface) │
143
+ └──────┬─────┘ └──────┬──────┘
144
+ ┌────┴─────┐ ┌──────┴───┐
145
+ ┌────┴────┐ ┌───┴─┴───┐ ┌────┴────┐
146
+ │ State │ │ Compute │ │ Watch │
147
+ └─────────┘ └─────────┘ └─────────┘
148
+ ```
149
+
137
150
  ### Simple example
138
151
  ###### [🏠︎](#index) / [Usage](#usage) / Simple example [↓](#example-vanilla-js)
139
152
 
@@ -191,11 +204,11 @@ Simple reactive state without build tools or framework dependencies.
191
204
  ### Example React
192
205
  ###### [🏠︎](#index) / [Usage](#usage) / Example React [↑](#example-vanilla-js) [↓](#example-innetdom)
193
206
 
194
- `@watch-state/react` provides `useWatch()` hook that automatically subscribes React components to state changes and re-renders only when needed.
207
+ [@watch-state/react](https://www.npmjs.com/package/@watch-state/react) provides `useObservable()` hook that automatically subscribes React components to state changes and re-renders only when needed.
195
208
 
196
209
  ```tsx
197
210
  import { State } from 'watch-state'
198
- import { useWatch } from '@watch-state/react'
211
+ import { useObservable } from '@watch-state/react'
199
212
 
200
213
  const $count = new State(0)
201
214
 
@@ -204,7 +217,7 @@ const increase = () => {
204
217
  }
205
218
 
206
219
  export function CountButton () {
207
- const count = useWatch($count)
220
+ const count = useObservable($count)
208
221
 
209
222
  return <button onClick={increase}>{count}</button>
210
223
  }
@@ -383,14 +396,16 @@ state.value++
383
396
  ## State
384
397
  ###### [🏠︎](#index) / State [↑](#watch) [↓](#compute)
385
398
 
386
- <sup>[Get or Set value](#get-or-set-value) • [Force update of State](#force-update-of-state) • [Raw value](#raw-value)</sup>
399
+ <sup>[Get or Set value](#get-or-set-value) • [Force update of State](#force-update-of-state) • [Raw value](#raw-value) • [State.set (experimental)](#stateset-experimental)</sup>
387
400
 
388
401
  **Reactive primitive** that automatically notifies all subscribed watchers when `.value` changes.
389
402
 
390
403
  ### Get or Set value
391
404
  ###### [🏠︎](#index) / [State](#state) / Get or Set value [↓](#force-update-of-state)
392
405
 
393
- **Access or mutate the state value.** Reading `.value` inside `Watch` **auto-subscribes** to changes. Writing `.value` **triggers all watchers**.
406
+ **Access or mutate the state value.**
407
+
408
+ Reading `.value` inside `Observer` **auto-subscribes** to changes. Writing `.value` **triggers all watchers**.
394
409
 
395
410
  ```ts
396
411
  const count = new State(0)
@@ -420,9 +435,9 @@ log.update() // logs: [1]
420
435
  ```
421
436
 
422
437
  ### Raw value
423
- ###### [🏠︎](#index) / [State](#state) / Raw value [↑](#force-update-of-state)
438
+ ###### [🏠︎](#index) / [State](#state) / Raw value [↑](#force-update-of-state) [↓](#stateset-experimental)
424
439
 
425
- `rawValue` returns the current value but **doesn't subscribe** to changes — unlike `value` which auto-subscribes in `Watch`.
440
+ `rawValue` returns the current value but **doesn't subscribe** to changes — unlike `value`.
426
441
 
427
442
  ```ts
428
443
  const foo = new State(0)
@@ -436,6 +451,24 @@ bar.value++ // no logs
436
451
  foo.value++ // logs: 2, 1
437
452
  ```
438
453
 
454
+ ### State.set (experimental)
455
+ ###### [🏠︎](#index) / [State](#state) / State.set [↑](#raw-value)
456
+
457
+ `State.set` mirrors the behavior of the value setter but returns `void`.
458
+ It is useful as a shorthand in arrow functions: `() => state.set(nextValue)` instead of `() => { state.value = nextValue }`.
459
+
460
+ Note: `state.set` cannot be used as a standalone function; `const set = state.set` is not supported.
461
+
462
+ ```ts
463
+ const count = new State(0)
464
+
465
+ // Subscribing
466
+ new Watch(() => console.log(count.value))
467
+ // log: 0
468
+
469
+ count.set(1) // triggers: log: 1
470
+ ```
471
+
439
472
  ## Compute
440
473
  ###### [🏠︎](#index) / Compute [↑](#state) [↓](#utils)
441
474
 
package/State/State.d.ts CHANGED
@@ -32,6 +32,14 @@ export declare class State<V = unknown> extends Observable<V> {
32
32
  */
33
33
  get value(): V;
34
34
  set value(value: V);
35
+ /**
36
+ * @experimental
37
+ * Sets the state value. Identical to the `value` setter but returns `void`.
38
+ * Useful as a shorthand in arrow functions: `() => state.set(value)` instead of `() => { state.value = value }`
39
+ *
40
+ * `state.set` cannot be used as a standalone function: `const set = state.set`
41
+ */
42
+ set(value: V): void;
35
43
  /**
36
44
  * Force triggers all watchers even if value didn't change.
37
45
  *
@@ -46,6 +46,16 @@ class State extends Observable {
46
46
  this.update();
47
47
  }
48
48
  }
49
+ /**
50
+ * @experimental
51
+ * Sets the state value. Identical to the `value` setter but returns `void`.
52
+ * Useful as a shorthand in arrow functions: `() => state.set(value)` instead of `() => { state.value = value }`
53
+ *
54
+ * `state.set` cannot be used as a standalone function: `const set = state.set`
55
+ */
56
+ set(value) {
57
+ this.value = value;
58
+ }
49
59
  /**
50
60
  * Force triggers all watchers even if value didn't change.
51
61
  *
package/State/State.js CHANGED
@@ -50,6 +50,16 @@ class State extends Observable.Observable {
50
50
  this.update();
51
51
  }
52
52
  }
53
+ /**
54
+ * @experimental
55
+ * Sets the state value. Identical to the `value` setter but returns `void`.
56
+ * Useful as a shorthand in arrow functions: `() => state.set(value)` instead of `() => { state.value = value }`
57
+ *
58
+ * `state.set` cannot be used as a standalone function: `const set = state.set`
59
+ */
60
+ set(value) {
61
+ this.value = value;
62
+ }
53
63
  /**
54
64
  * Force triggers all watchers even if value didn't change.
55
65
  *
package/index.min.js CHANGED
@@ -1 +1 @@
1
- var WatchState=function(e){"use strict";const t={activeWatcher:void 0,eventDeep:0};function s(e){const{activeWatcher:s}=t;s&&(s.childrenObservers.add(e),s.destructors.add((()=>{s.childrenObservers.delete(e)})))}const r=[];let c;function n(e){const t=Boolean(r.length);if(r.push(e),!t)for(;c=r.shift();){c.childrenObservers.forEach((e=>{r.push(e)}));for(const e of c.destructors)c.destructors.delete(e),e();c.destroyed=!0}}const i=[];let a,o,h,u;function d(e){const t=Boolean(i.length);if(i.push(e),!t)for(;a=i.shift();){a.childrenObservers.forEach(n);for(const e of a.destructors)a.destructors.delete(e),e()}}function l(e,s){const r=t.activeWatcher;t.activeWatcher=e,s(),t.activeWatcher=r}class v{constructor(){this.observers=new Set}get value(){const{activeWatcher:e}=t;return e&&(this.observers.add(e),e.destructors.add((()=>{this.observers.delete(e)}))),this.rawValue}}function f(e){if(!e.size)return;const t=e.values().next().value;return e.delete(t),t}const p=new Set,b=new Set;function w(){if(!u){for(u=!0;(o=f(p))||(h=f(b));)o?o.invalid=!0:(d(h),h.update());u=!1}}function W(e){const s=!t.eventDeep&&!b.size&&!p.size,r=[...b];b.clear(),e.forEach((e=>{b.add(e),e instanceof D&&p.add(e)})),r.forEach((e=>b.add(e))),s&&w()}const y=[];let O;function S(e){const t=y.length;if(y.push(e),!t)for(;O=y.shift();)O instanceof D&&(y.push(...O.observers),O.invalid=!0)}class D extends v{get childWatchers(){return this.childrenObservers}constructor(e,t,r){super(),this.invalid=!0,this.updated=!1,this.destroyed=!1,this.isCache=!0,this.destructors=new Set,this.childrenObservers=new Set,this.watcher=e,t||s(this),r&&this.forceUpdate()}update(){S(this);const e=[...this.observers];let t;for(;t=e.pop();){if(!(t instanceof D))return this.forceUpdate();e.push(...t.observers)}}forceUpdate(){this.destroyed||(this.invalid=!1,l(this,(()=>{const e=this.watcher(!!this.updated&&(this.updated=!0));e!==this.rawValue&&(this.rawValue=e,W(this.observers))})))}get value(){return this.invalid&&this.forceUpdate(),this.destroyed?this.rawValue:super.value}destroy(){n(this)}}function g(e){const{activeWatcher:s}=t;t.activeWatcher=void 0;const r=e();return t.activeWatcher=s,r}return e.Cache=class extends D{},e.Compute=D,e.Observable=v,e.State=class extends v{constructor(e){super(),this.rawValue=e}get value(){return super.value}set value(e){this.rawValue!==e&&(this.rawValue=e,this.update())}update(){W(this.observers)}},e.Watch=class{get childWatchers(){return this.childrenObservers}constructor(e,t,r){this.watcher=e,this.destroyed=!1,this.destructors=new Set,this.childrenObservers=new Set,t||s(this),r||l(this,(()=>{e(!1)}))}destroy(){n(this)}update(){this.destroyed||l(this,(()=>{this.watcher(!0)}))}},e.bindObserver=s,e.callEvent=function(e){const s=g((()=>{t.eventDeep++;const s=e();return t.eventDeep--,s}));return t.eventDeep||w(),s},e.clearWatcher=d,e.createEvent=function(e){return function(...s){const r=g((()=>{t.eventDeep++;const r=e.apply(this,s);return t.eventDeep--,r}));return t.eventDeep||w(),r}},e.destroyWatchers=n,e.forceQueueWatchers=w,e.invalidateCache=function(e){S(e)},e.invalidateCompute=S,e.onDestroy=function(e){t.activeWatcher&&t.activeWatcher.destructors.add(e)},e.queueWatchers=W,e.scope=t,e.shiftSet=f,e.unwatch=g,e.watchWithScope=l,Object.defineProperty(e,"__esModule",{value:!0}),e}({});
1
+ var WatchState=function(e){"use strict";const t={activeWatcher:void 0,eventDeep:0};function s(e){const{activeWatcher:s}=t;s&&(s.childrenObservers.add(e),s.destructors.add((()=>{s.childrenObservers.delete(e)})))}const r=[];let c;function n(e){const t=Boolean(r.length);if(r.push(e),!t)for(;c=r.shift();){c.childrenObservers.forEach((e=>{r.push(e)}));for(const e of c.destructors)c.destructors.delete(e),e();c.destroyed=!0}}const i=[];let a,o,h,u;function d(e){const t=Boolean(i.length);if(i.push(e),!t)for(;a=i.shift();){a.childrenObservers.forEach(n);for(const e of a.destructors)a.destructors.delete(e),e()}}function l(e,s){const r=t.activeWatcher;t.activeWatcher=e,s(),t.activeWatcher=r}class v{constructor(){this.observers=new Set}get value(){const{activeWatcher:e}=t;return e&&(this.observers.add(e),e.destructors.add((()=>{this.observers.delete(e)}))),this.rawValue}}function f(e){if(!e.size)return;const t=e.values().next().value;return e.delete(t),t}const p=new Set,b=new Set;function w(){if(!u){for(u=!0;(o=f(p))||(h=f(b));)o?o.invalid=!0:(d(h),h.update());u=!1}}function W(e){const s=!t.eventDeep&&!b.size&&!p.size,r=[...b];b.clear(),e.forEach((e=>{b.add(e),e instanceof D&&p.add(e)})),r.forEach((e=>b.add(e))),s&&w()}const y=[];let O;function S(e){const t=y.length;if(y.push(e),!t)for(;O=y.shift();)O instanceof D&&(y.push(...O.observers),O.invalid=!0)}class D extends v{get childWatchers(){return this.childrenObservers}constructor(e,t,r){super(),this.invalid=!0,this.updated=!1,this.destroyed=!1,this.isCache=!0,this.destructors=new Set,this.childrenObservers=new Set,this.watcher=e,t||s(this),r&&this.forceUpdate()}update(){S(this);const e=[...this.observers];let t;for(;t=e.pop();){if(!(t instanceof D))return this.forceUpdate();e.push(...t.observers)}}forceUpdate(){this.destroyed||(this.invalid=!1,l(this,(()=>{const e=this.watcher(!!this.updated&&(this.updated=!0));e!==this.rawValue&&(this.rawValue=e,W(this.observers))})))}get value(){return this.invalid&&this.forceUpdate(),this.destroyed?this.rawValue:super.value}destroy(){n(this)}}function g(e){const{activeWatcher:s}=t;t.activeWatcher=void 0;const r=e();return t.activeWatcher=s,r}return e.Cache=class extends D{},e.Compute=D,e.Observable=v,e.State=class extends v{constructor(e){super(),this.rawValue=e}get value(){return super.value}set value(e){this.rawValue!==e&&(this.rawValue=e,this.update())}set(e){this.value=e}update(){W(this.observers)}},e.Watch=class{get childWatchers(){return this.childrenObservers}constructor(e,t,r){this.watcher=e,this.destroyed=!1,this.destructors=new Set,this.childrenObservers=new Set,t||s(this),r||l(this,(()=>{e(!1)}))}destroy(){n(this)}update(){this.destroyed||l(this,(()=>{this.watcher(!0)}))}},e.bindObserver=s,e.callEvent=function(e){const s=g((()=>{t.eventDeep++;const s=e();return t.eventDeep--,s}));return t.eventDeep||w(),s},e.clearWatcher=d,e.createEvent=function(e){return function(...s){const r=g((()=>{t.eventDeep++;const r=e.apply(this,s);return t.eventDeep--,r}));return t.eventDeep||w(),r}},e.destroyWatchers=n,e.forceQueueWatchers=w,e.invalidateCache=function(e){S(e)},e.invalidateCompute=S,e.onDestroy=function(e){t.activeWatcher&&t.activeWatcher.destructors.add(e)},e.queueWatchers=W,e.scope=t,e.shiftSet=f,e.unwatch=g,e.watchWithScope=l,Object.defineProperty(e,"__esModule",{value:!0}),e}({});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "watch-state",
3
- "version": "3.5.0",
3
+ "version": "3.5.2",
4
4
  "description": "CANT inc. state management system.",
5
5
  "author": "Mikhail Lysikov <d8corp@mail.ru>",
6
6
  "license": "MIT",
@@ -10,7 +10,6 @@
10
10
  "types": "index.d.ts",
11
11
  "unpkg": "index.min.js",
12
12
  "jsdelivr": "index.min.js",
13
- "browser": "index.min.js",
14
13
  "homepage": "https://github.com/d8corp/watch-state",
15
14
  "bugs": {
16
15
  "url": "https://github.com/d8corp/watch-state/issues"
@@ -52,7 +51,7 @@
52
51
  "import": {
53
52
  "./release/index.es6.js": "*"
54
53
  },
55
- "limit": "1.06 kB"
54
+ "limit": "1.07 kB"
56
55
  },
57
56
  {
58
57
  "name": "Core",
@@ -60,7 +59,7 @@
60
59
  "import": {
61
60
  "./release/index.es6.js": "{ Watch, State, Compute, createEvent }"
62
61
  },
63
- "limit": "843 B"
62
+ "limit": "850 B"
64
63
  }
65
64
  ]
66
65
  }