Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 | 9x 9x 9x 76x 76x 223x 95x 93x 93x 2x 9x 93x | import { queueWatchers } from '../Compute'
import { Observable } from '../Observable'
/**
* Reactive state that can be changed via `value` field with change tracking capability.
*
* @class State
* @extends Observable
* @template V - state value type
* @param {V} [initial] - initial state value
*
* @example
* // Create state
* const count = new State(0)
*
* // Subscribe to changes
* new Watch(() => console.log(count.value)) // logs: 0
*
* // Update value
* count.value++ // logs: 1
*/
export class State<V = never | unknown> extends Observable<V extends never ? unknown : V> {
/** Current value. No auto-subscription on direct access (unlike `value`). */
raw: V extends never ? unknown : V
/**
* Initial state value set during construction.
* Used by `reset()` to restore state to its original value.
* Allows checking if the state has been modified.
*
* @example
* const count = new State(0)
*
* const isChanged = count.initial === count.raw
*/
readonly initial: V extends never ? unknown : V
constructor (...args: V extends never | undefined ? [V?] : [V])
constructor (initial?: any) {
super()
this.raw = this.initial = initial
}
/**
* Current state value. Updates watchers only on actual changes (strict `!==`).
* Using `value` inside a `Watch` callback automatically subscribes to changes.
*
* @example
* new Watch(() => console.log(count.value)) // auto-subscribes to count
*
* @example
* count.value = 1 // triggers watchers
* count.value = 1 // no trigger
*/
get value () {
return super.value
}
set value (value: V extends never ? unknown : V) {
if (this.raw !== value) {
this.raw = value
this.update()
}
}
/**
* Sets the state value. Identical to the `value` setter but returns `void`.
* Useful as a shorthand in arrow functions: `() => state.set(value)` instead of `() => { state.value = value }`
*
* `state.set` cannot be used as a standalone function: `const set = state.set`
*/
set (value: V extends never ? unknown : V) {
this.value = value
}
/**
* Resets state to its initial value.
* Triggers watchers only if the current value differs from the initial value.
*
* @example
* const count = new State(0)
*
* new Watch(() => console.log(count.value)) // logs: 0
*
* count.value = 5 // logs: 5
*
* count.reset() // logs: 0
*/
reset () {
this.value = this.initial
}
/**
* Force triggers all watchers even if value didn't change.
*
* @example
* // Create state
* const log = new State([])
*
* // Subscribe to changes
* new Watch(() => console.log(log.value)) // logs: []
*
* log.value.push(1) // no logs
*
* // Update value
* count.update() // logs: [1]
*/
update () {
queueWatchers(this.observers)
}
}
|