@tanstack/store 0.0.1-beta.89 → 0.0.1

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.
@@ -1,5 +1,5 @@
1
1
  /**
2
- * store
2
+ * @tanstack/store/src/index.ts
3
3
  *
4
4
  * Copyright (c) TanStack
5
5
  *
@@ -14,14 +14,12 @@ Object.defineProperty(exports, '__esModule', { value: true });
14
14
 
15
15
  class Store {
16
16
  listeners = new Set();
17
- #batching = false;
18
- #flushing = 0;
17
+ _batching = false;
18
+ _flushing = 0;
19
+ _nextPriority = null;
19
20
  constructor(initialState, options) {
20
21
  this.state = initialState;
21
22
  this.options = options;
22
- if (this.options?.onUpdate) {
23
- this.subscribe(this.options?.onUpdate);
24
- }
25
23
  }
26
24
  subscribe = listener => {
27
25
  this.listeners.add(listener);
@@ -31,25 +29,42 @@ class Store {
31
29
  unsub?.();
32
30
  };
33
31
  };
34
- setState = updater => {
32
+ setState = (updater, opts) => {
35
33
  const previous = this.state;
36
34
  this.state = this.options?.updateFn ? this.options.updateFn(previous)(updater) : updater(previous);
37
- this.#flush();
35
+ const priority = opts?.priority ?? this.options?.defaultPriority ?? 'high';
36
+ if (this._nextPriority === null) {
37
+ this._nextPriority = priority;
38
+ } else if (this._nextPriority === 'high') {
39
+ this._nextPriority = priority;
40
+ } else {
41
+ this._nextPriority = this.options?.defaultPriority ?? 'high';
42
+ }
43
+
44
+ // Always run onUpdate, regardless of batching
45
+ this.options?.onUpdate?.({
46
+ priority: this._nextPriority
47
+ });
48
+
49
+ // Attempt to flush
50
+ this._flush();
38
51
  };
39
- #flush = () => {
40
- if (this.#batching) return;
41
- const flushId = ++this.#flushing;
52
+ _flush = () => {
53
+ if (this._batching) return;
54
+ const flushId = ++this._flushing;
42
55
  this.listeners.forEach(listener => {
43
- if (this.#flushing !== flushId) return;
44
- listener();
56
+ if (this._flushing !== flushId) return;
57
+ listener({
58
+ priority: this._nextPriority ?? 'high'
59
+ });
45
60
  });
46
61
  };
47
62
  batch = cb => {
48
- if (this.#batching) return cb();
49
- this.#batching = true;
63
+ if (this._batching) return cb();
64
+ this._batching = true;
50
65
  cb();
51
- this.#batching = false;
52
- this.#flush();
66
+ this._batching = false;
67
+ this._flush();
53
68
  };
54
69
  }
55
70
 
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../../src/index.ts"],"sourcesContent":["export type AnyUpdater = (...args: any[]) => any\n\nexport type Listener = () => void\n\ninterface StoreOptions<\n TState,\n TUpdater extends AnyUpdater = (cb: TState) => TState,\n> {\n updateFn?: (previous: TState) => (updater: TUpdater) => TState\n onSubscribe?: (\n listener: Listener,\n store: Store<TState, TUpdater>,\n ) => () => void\n onUpdate?: () => void\n}\n\nexport class Store<\n TState,\n TUpdater extends AnyUpdater = (cb: TState) => TState,\n> {\n listeners = new Set<Listener>()\n state: TState\n options?: StoreOptions<TState, TUpdater>\n #batching = false\n #flushing = 0\n\n constructor(initialState: TState, options?: StoreOptions<TState, TUpdater>) {\n this.state = initialState\n this.options = options\n if (this.options?.onUpdate) {\n this.subscribe(this.options?.onUpdate)\n }\n }\n\n subscribe = (listener: Listener) => {\n this.listeners.add(listener)\n const unsub = this.options?.onSubscribe?.(listener, this)\n return () => {\n this.listeners.delete(listener)\n unsub?.()\n }\n }\n\n setState = (updater: TUpdater) => {\n const previous = this.state\n this.state = this.options?.updateFn\n ? this.options.updateFn(previous)(updater)\n : (updater as any)(previous)\n\n this.#flush()\n }\n\n #flush = () => {\n if (this.#batching) return\n const flushId = ++this.#flushing\n this.listeners.forEach((listener) => {\n if (this.#flushing !== flushId) return\n listener()\n })\n }\n\n batch = (cb: () => void) => {\n if (this.#batching) return cb()\n this.#batching = true\n cb()\n this.#batching = false\n this.#flush()\n }\n}\n"],"names":["Store","listeners","Set","constructor","initialState","options","state","onUpdate","subscribe","listener","add","unsub","onSubscribe","delete","setState","updater","previous","updateFn","flushId","forEach","batch","cb"],"mappings":";;;;;;;;;;;;;;AAgBO,MAAMA,KAAK,CAGhB;EACAC,SAAS,GAAG,IAAIC,GAAG,EAAY,CAAA;EAG/B,SAAS,GAAG,KAAK,CAAA;EACjB,SAAS,GAAG,CAAC,CAAA;AAEbC,EAAAA,WAAW,CAACC,YAAoB,EAAEC,OAAwC,EAAE;IAC1E,IAAI,CAACC,KAAK,GAAGF,YAAY,CAAA;IACzB,IAAI,CAACC,OAAO,GAAGA,OAAO,CAAA;AACtB,IAAA,IAAI,IAAI,CAACA,OAAO,EAAEE,QAAQ,EAAE;MAC1B,IAAI,CAACC,SAAS,CAAC,IAAI,CAACH,OAAO,EAAEE,QAAQ,CAAC,CAAA;AACxC,KAAA;AACF,GAAA;EAEAC,SAAS,GAAIC,QAAkB,IAAK;AAClC,IAAA,IAAI,CAACR,SAAS,CAACS,GAAG,CAACD,QAAQ,CAAC,CAAA;IAC5B,MAAME,KAAK,GAAG,IAAI,CAACN,OAAO,EAAEO,WAAW,GAAGH,QAAQ,EAAE,IAAI,CAAC,CAAA;AACzD,IAAA,OAAO,MAAM;AACX,MAAA,IAAI,CAACR,SAAS,CAACY,MAAM,CAACJ,QAAQ,CAAC,CAAA;AAC/BE,MAAAA,KAAK,IAAI,CAAA;KACV,CAAA;GACF,CAAA;EAEDG,QAAQ,GAAIC,OAAiB,IAAK;AAChC,IAAA,MAAMC,QAAQ,GAAG,IAAI,CAACV,KAAK,CAAA;IAC3B,IAAI,CAACA,KAAK,GAAG,IAAI,CAACD,OAAO,EAAEY,QAAQ,GAC/B,IAAI,CAACZ,OAAO,CAACY,QAAQ,CAACD,QAAQ,CAAC,CAACD,OAAO,CAAC,GACvCA,OAAO,CAASC,QAAQ,CAAC,CAAA;IAE9B,IAAI,CAAC,MAAM,EAAE,CAAA;GACd,CAAA;EAED,MAAM,GAAG,MAAM;AACb,IAAA,IAAI,IAAI,CAAC,SAAS,EAAE,OAAA;AACpB,IAAA,MAAME,OAAO,GAAG,EAAE,IAAI,CAAC,SAAS,CAAA;AAChC,IAAA,IAAI,CAACjB,SAAS,CAACkB,OAAO,CAAEV,QAAQ,IAAK;AACnC,MAAA,IAAI,IAAI,CAAC,SAAS,KAAKS,OAAO,EAAE,OAAA;AAChCT,MAAAA,QAAQ,EAAE,CAAA;AACZ,KAAC,CAAC,CAAA;GACH,CAAA;EAEDW,KAAK,GAAIC,EAAc,IAAK;AAC1B,IAAA,IAAI,IAAI,CAAC,SAAS,EAAE,OAAOA,EAAE,EAAE,CAAA;AAC/B,IAAA,IAAI,CAAC,SAAS,GAAG,IAAI,CAAA;AACrBA,IAAAA,EAAE,EAAE,CAAA;AACJ,IAAA,IAAI,CAAC,SAAS,GAAG,KAAK,CAAA;IACtB,IAAI,CAAC,MAAM,EAAE,CAAA;GACd,CAAA;AACH;;;;"}
1
+ {"version":3,"file":"index.js","sources":["../../src/index.ts"],"sourcesContent":["export type AnyUpdater = (...args: any[]) => any\n\nexport type Listener = (opts: { priority: Priority }) => void\n\nexport type Priority = 'high' | 'low'\n\ninterface StoreOptions<\n TState,\n TUpdater extends AnyUpdater = (cb: TState) => TState,\n> {\n updateFn?: (previous: TState) => (updater: TUpdater) => TState\n onSubscribe?: (\n listener: Listener,\n store: Store<TState, TUpdater>,\n ) => () => void\n onUpdate?: (opts: { priority: Priority }) => void\n defaultPriority?: Priority\n}\n\nexport class Store<\n TState,\n TUpdater extends AnyUpdater = (cb: TState) => TState,\n> {\n listeners = new Set<Listener>()\n state: TState\n options?: StoreOptions<TState, TUpdater>\n _batching = false\n _flushing = 0\n _nextPriority: null | Priority = null\n\n constructor(initialState: TState, options?: StoreOptions<TState, TUpdater>) {\n this.state = initialState\n this.options = options\n }\n\n subscribe = (listener: Listener) => {\n this.listeners.add(listener)\n const unsub = this.options?.onSubscribe?.(listener, this)\n return () => {\n this.listeners.delete(listener)\n unsub?.()\n }\n }\n\n setState = (\n updater: TUpdater,\n opts?: {\n priority: Priority\n },\n ) => {\n const previous = this.state\n this.state = this.options?.updateFn\n ? this.options.updateFn(previous)(updater)\n : (updater as any)(previous)\n\n const priority = opts?.priority ?? this.options?.defaultPriority ?? 'high'\n if (this._nextPriority === null) {\n this._nextPriority = priority\n } else if (this._nextPriority === 'high') {\n this._nextPriority = priority\n } else {\n this._nextPriority = this.options?.defaultPriority ?? 'high'\n }\n\n // Always run onUpdate, regardless of batching\n this.options?.onUpdate?.({\n priority: this._nextPriority,\n })\n\n // Attempt to flush\n this._flush()\n }\n\n _flush = () => {\n if (this._batching) return\n const flushId = ++this._flushing\n this.listeners.forEach((listener) => {\n if (this._flushing !== flushId) return\n listener({\n priority: this._nextPriority ?? 'high',\n })\n })\n }\n\n batch = (cb: () => void) => {\n if (this._batching) return cb()\n this._batching = true\n cb()\n this._batching = false\n this._flush()\n }\n}\n"],"names":["Store","listeners","Set","_batching","_flushing","_nextPriority","constructor","initialState","options","state","subscribe","listener","add","unsub","onSubscribe","delete","setState","updater","opts","previous","updateFn","priority","defaultPriority","onUpdate","_flush","flushId","forEach","batch","cb"],"mappings":";;;;;;;;;;;;;;AAmBO,MAAMA,KAAK,CAGhB;AACAC,EAAAA,SAAS,GAAG,IAAIC,GAAG,EAAY,CAAA;AAG/BC,EAAAA,SAAS,GAAG,KAAK,CAAA;AACjBC,EAAAA,SAAS,GAAG,CAAC,CAAA;AACbC,EAAAA,aAAa,GAAoB,IAAI,CAAA;AAErCC,EAAAA,WAAWA,CAACC,YAAoB,EAAEC,OAAwC,EAAE;IAC1E,IAAI,CAACC,KAAK,GAAGF,YAAY,CAAA;IACzB,IAAI,CAACC,OAAO,GAAGA,OAAO,CAAA;AACxB,GAAA;EAEAE,SAAS,GAAIC,QAAkB,IAAK;AAClC,IAAA,IAAI,CAACV,SAAS,CAACW,GAAG,CAACD,QAAQ,CAAC,CAAA;IAC5B,MAAME,KAAK,GAAG,IAAI,CAACL,OAAO,EAAEM,WAAW,GAAGH,QAAQ,EAAE,IAAI,CAAC,CAAA;AACzD,IAAA,OAAO,MAAM;AACX,MAAA,IAAI,CAACV,SAAS,CAACc,MAAM,CAACJ,QAAQ,CAAC,CAAA;AAC/BE,MAAAA,KAAK,IAAI,CAAA;KACV,CAAA;GACF,CAAA;AAEDG,EAAAA,QAAQ,GAAGA,CACTC,OAAiB,EACjBC,IAEC,KACE;AACH,IAAA,MAAMC,QAAQ,GAAG,IAAI,CAACV,KAAK,CAAA;IAC3B,IAAI,CAACA,KAAK,GAAG,IAAI,CAACD,OAAO,EAAEY,QAAQ,GAC/B,IAAI,CAACZ,OAAO,CAACY,QAAQ,CAACD,QAAQ,CAAC,CAACF,OAAO,CAAC,GACvCA,OAAO,CAASE,QAAQ,CAAC,CAAA;AAE9B,IAAA,MAAME,QAAQ,GAAGH,IAAI,EAAEG,QAAQ,IAAI,IAAI,CAACb,OAAO,EAAEc,eAAe,IAAI,MAAM,CAAA;AAC1E,IAAA,IAAI,IAAI,CAACjB,aAAa,KAAK,IAAI,EAAE;MAC/B,IAAI,CAACA,aAAa,GAAGgB,QAAQ,CAAA;AAC/B,KAAC,MAAM,IAAI,IAAI,CAAChB,aAAa,KAAK,MAAM,EAAE;MACxC,IAAI,CAACA,aAAa,GAAGgB,QAAQ,CAAA;AAC/B,KAAC,MAAM;MACL,IAAI,CAAChB,aAAa,GAAG,IAAI,CAACG,OAAO,EAAEc,eAAe,IAAI,MAAM,CAAA;AAC9D,KAAA;;AAEA;AACA,IAAA,IAAI,CAACd,OAAO,EAAEe,QAAQ,GAAG;MACvBF,QAAQ,EAAE,IAAI,CAAChB,aAAAA;AACjB,KAAC,CAAC,CAAA;;AAEF;IACA,IAAI,CAACmB,MAAM,EAAE,CAAA;GACd,CAAA;EAEDA,MAAM,GAAGA,MAAM;IACb,IAAI,IAAI,CAACrB,SAAS,EAAE,OAAA;AACpB,IAAA,MAAMsB,OAAO,GAAG,EAAE,IAAI,CAACrB,SAAS,CAAA;AAChC,IAAA,IAAI,CAACH,SAAS,CAACyB,OAAO,CAAEf,QAAQ,IAAK;AACnC,MAAA,IAAI,IAAI,CAACP,SAAS,KAAKqB,OAAO,EAAE,OAAA;AAChCd,MAAAA,QAAQ,CAAC;AACPU,QAAAA,QAAQ,EAAE,IAAI,CAAChB,aAAa,IAAI,MAAA;AAClC,OAAC,CAAC,CAAA;AACJ,KAAC,CAAC,CAAA;GACH,CAAA;EAEDsB,KAAK,GAAIC,EAAc,IAAK;AAC1B,IAAA,IAAI,IAAI,CAACzB,SAAS,EAAE,OAAOyB,EAAE,EAAE,CAAA;IAC/B,IAAI,CAACzB,SAAS,GAAG,IAAI,CAAA;AACrByB,IAAAA,EAAE,EAAE,CAAA;IACJ,IAAI,CAACzB,SAAS,GAAG,KAAK,CAAA;IACtB,IAAI,CAACqB,MAAM,EAAE,CAAA;GACd,CAAA;AACH;;;;"}
@@ -1,5 +1,5 @@
1
1
  /**
2
- * store
2
+ * @tanstack/store/src/index.ts
3
3
  *
4
4
  * Copyright (c) TanStack
5
5
  *
@@ -10,14 +10,12 @@
10
10
  */
11
11
  class Store {
12
12
  listeners = new Set();
13
- #batching = false;
14
- #flushing = 0;
13
+ _batching = false;
14
+ _flushing = 0;
15
+ _nextPriority = null;
15
16
  constructor(initialState, options) {
16
17
  this.state = initialState;
17
18
  this.options = options;
18
- if (this.options?.onUpdate) {
19
- this.subscribe(this.options?.onUpdate);
20
- }
21
19
  }
22
20
  subscribe = listener => {
23
21
  this.listeners.add(listener);
@@ -27,25 +25,42 @@ class Store {
27
25
  unsub?.();
28
26
  };
29
27
  };
30
- setState = updater => {
28
+ setState = (updater, opts) => {
31
29
  const previous = this.state;
32
30
  this.state = this.options?.updateFn ? this.options.updateFn(previous)(updater) : updater(previous);
33
- this.#flush();
31
+ const priority = opts?.priority ?? this.options?.defaultPriority ?? 'high';
32
+ if (this._nextPriority === null) {
33
+ this._nextPriority = priority;
34
+ } else if (this._nextPriority === 'high') {
35
+ this._nextPriority = priority;
36
+ } else {
37
+ this._nextPriority = this.options?.defaultPriority ?? 'high';
38
+ }
39
+
40
+ // Always run onUpdate, regardless of batching
41
+ this.options?.onUpdate?.({
42
+ priority: this._nextPriority
43
+ });
44
+
45
+ // Attempt to flush
46
+ this._flush();
34
47
  };
35
- #flush = () => {
36
- if (this.#batching) return;
37
- const flushId = ++this.#flushing;
48
+ _flush = () => {
49
+ if (this._batching) return;
50
+ const flushId = ++this._flushing;
38
51
  this.listeners.forEach(listener => {
39
- if (this.#flushing !== flushId) return;
40
- listener();
52
+ if (this._flushing !== flushId) return;
53
+ listener({
54
+ priority: this._nextPriority ?? 'high'
55
+ });
41
56
  });
42
57
  };
43
58
  batch = cb => {
44
- if (this.#batching) return cb();
45
- this.#batching = true;
59
+ if (this._batching) return cb();
60
+ this._batching = true;
46
61
  cb();
47
- this.#batching = false;
48
- this.#flush();
62
+ this._batching = false;
63
+ this._flush();
49
64
  };
50
65
  }
51
66
 
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../../src/index.ts"],"sourcesContent":["export type AnyUpdater = (...args: any[]) => any\n\nexport type Listener = () => void\n\ninterface StoreOptions<\n TState,\n TUpdater extends AnyUpdater = (cb: TState) => TState,\n> {\n updateFn?: (previous: TState) => (updater: TUpdater) => TState\n onSubscribe?: (\n listener: Listener,\n store: Store<TState, TUpdater>,\n ) => () => void\n onUpdate?: () => void\n}\n\nexport class Store<\n TState,\n TUpdater extends AnyUpdater = (cb: TState) => TState,\n> {\n listeners = new Set<Listener>()\n state: TState\n options?: StoreOptions<TState, TUpdater>\n #batching = false\n #flushing = 0\n\n constructor(initialState: TState, options?: StoreOptions<TState, TUpdater>) {\n this.state = initialState\n this.options = options\n if (this.options?.onUpdate) {\n this.subscribe(this.options?.onUpdate)\n }\n }\n\n subscribe = (listener: Listener) => {\n this.listeners.add(listener)\n const unsub = this.options?.onSubscribe?.(listener, this)\n return () => {\n this.listeners.delete(listener)\n unsub?.()\n }\n }\n\n setState = (updater: TUpdater) => {\n const previous = this.state\n this.state = this.options?.updateFn\n ? this.options.updateFn(previous)(updater)\n : (updater as any)(previous)\n\n this.#flush()\n }\n\n #flush = () => {\n if (this.#batching) return\n const flushId = ++this.#flushing\n this.listeners.forEach((listener) => {\n if (this.#flushing !== flushId) return\n listener()\n })\n }\n\n batch = (cb: () => void) => {\n if (this.#batching) return cb()\n this.#batching = true\n cb()\n this.#batching = false\n this.#flush()\n }\n}\n"],"names":["Store","listeners","Set","constructor","initialState","options","state","onUpdate","subscribe","listener","add","unsub","onSubscribe","delete","setState","updater","previous","updateFn","flushId","forEach","batch","cb"],"mappings":";;;;;;;;;;AAgBO,MAAMA,KAAK,CAGhB;EACAC,SAAS,GAAG,IAAIC,GAAG,EAAY,CAAA;EAG/B,SAAS,GAAG,KAAK,CAAA;EACjB,SAAS,GAAG,CAAC,CAAA;AAEbC,EAAAA,WAAW,CAACC,YAAoB,EAAEC,OAAwC,EAAE;IAC1E,IAAI,CAACC,KAAK,GAAGF,YAAY,CAAA;IACzB,IAAI,CAACC,OAAO,GAAGA,OAAO,CAAA;AACtB,IAAA,IAAI,IAAI,CAACA,OAAO,EAAEE,QAAQ,EAAE;MAC1B,IAAI,CAACC,SAAS,CAAC,IAAI,CAACH,OAAO,EAAEE,QAAQ,CAAC,CAAA;AACxC,KAAA;AACF,GAAA;EAEAC,SAAS,GAAIC,QAAkB,IAAK;AAClC,IAAA,IAAI,CAACR,SAAS,CAACS,GAAG,CAACD,QAAQ,CAAC,CAAA;IAC5B,MAAME,KAAK,GAAG,IAAI,CAACN,OAAO,EAAEO,WAAW,GAAGH,QAAQ,EAAE,IAAI,CAAC,CAAA;AACzD,IAAA,OAAO,MAAM;AACX,MAAA,IAAI,CAACR,SAAS,CAACY,MAAM,CAACJ,QAAQ,CAAC,CAAA;AAC/BE,MAAAA,KAAK,IAAI,CAAA;KACV,CAAA;GACF,CAAA;EAEDG,QAAQ,GAAIC,OAAiB,IAAK;AAChC,IAAA,MAAMC,QAAQ,GAAG,IAAI,CAACV,KAAK,CAAA;IAC3B,IAAI,CAACA,KAAK,GAAG,IAAI,CAACD,OAAO,EAAEY,QAAQ,GAC/B,IAAI,CAACZ,OAAO,CAACY,QAAQ,CAACD,QAAQ,CAAC,CAACD,OAAO,CAAC,GACvCA,OAAO,CAASC,QAAQ,CAAC,CAAA;IAE9B,IAAI,CAAC,MAAM,EAAE,CAAA;GACd,CAAA;EAED,MAAM,GAAG,MAAM;AACb,IAAA,IAAI,IAAI,CAAC,SAAS,EAAE,OAAA;AACpB,IAAA,MAAME,OAAO,GAAG,EAAE,IAAI,CAAC,SAAS,CAAA;AAChC,IAAA,IAAI,CAACjB,SAAS,CAACkB,OAAO,CAAEV,QAAQ,IAAK;AACnC,MAAA,IAAI,IAAI,CAAC,SAAS,KAAKS,OAAO,EAAE,OAAA;AAChCT,MAAAA,QAAQ,EAAE,CAAA;AACZ,KAAC,CAAC,CAAA;GACH,CAAA;EAEDW,KAAK,GAAIC,EAAc,IAAK;AAC1B,IAAA,IAAI,IAAI,CAAC,SAAS,EAAE,OAAOA,EAAE,EAAE,CAAA;AAC/B,IAAA,IAAI,CAAC,SAAS,GAAG,IAAI,CAAA;AACrBA,IAAAA,EAAE,EAAE,CAAA;AACJ,IAAA,IAAI,CAAC,SAAS,GAAG,KAAK,CAAA;IACtB,IAAI,CAAC,MAAM,EAAE,CAAA;GACd,CAAA;AACH;;;;"}
1
+ {"version":3,"file":"index.js","sources":["../../src/index.ts"],"sourcesContent":["export type AnyUpdater = (...args: any[]) => any\n\nexport type Listener = (opts: { priority: Priority }) => void\n\nexport type Priority = 'high' | 'low'\n\ninterface StoreOptions<\n TState,\n TUpdater extends AnyUpdater = (cb: TState) => TState,\n> {\n updateFn?: (previous: TState) => (updater: TUpdater) => TState\n onSubscribe?: (\n listener: Listener,\n store: Store<TState, TUpdater>,\n ) => () => void\n onUpdate?: (opts: { priority: Priority }) => void\n defaultPriority?: Priority\n}\n\nexport class Store<\n TState,\n TUpdater extends AnyUpdater = (cb: TState) => TState,\n> {\n listeners = new Set<Listener>()\n state: TState\n options?: StoreOptions<TState, TUpdater>\n _batching = false\n _flushing = 0\n _nextPriority: null | Priority = null\n\n constructor(initialState: TState, options?: StoreOptions<TState, TUpdater>) {\n this.state = initialState\n this.options = options\n }\n\n subscribe = (listener: Listener) => {\n this.listeners.add(listener)\n const unsub = this.options?.onSubscribe?.(listener, this)\n return () => {\n this.listeners.delete(listener)\n unsub?.()\n }\n }\n\n setState = (\n updater: TUpdater,\n opts?: {\n priority: Priority\n },\n ) => {\n const previous = this.state\n this.state = this.options?.updateFn\n ? this.options.updateFn(previous)(updater)\n : (updater as any)(previous)\n\n const priority = opts?.priority ?? this.options?.defaultPriority ?? 'high'\n if (this._nextPriority === null) {\n this._nextPriority = priority\n } else if (this._nextPriority === 'high') {\n this._nextPriority = priority\n } else {\n this._nextPriority = this.options?.defaultPriority ?? 'high'\n }\n\n // Always run onUpdate, regardless of batching\n this.options?.onUpdate?.({\n priority: this._nextPriority,\n })\n\n // Attempt to flush\n this._flush()\n }\n\n _flush = () => {\n if (this._batching) return\n const flushId = ++this._flushing\n this.listeners.forEach((listener) => {\n if (this._flushing !== flushId) return\n listener({\n priority: this._nextPriority ?? 'high',\n })\n })\n }\n\n batch = (cb: () => void) => {\n if (this._batching) return cb()\n this._batching = true\n cb()\n this._batching = false\n this._flush()\n }\n}\n"],"names":["Store","listeners","Set","_batching","_flushing","_nextPriority","constructor","initialState","options","state","subscribe","listener","add","unsub","onSubscribe","delete","setState","updater","opts","previous","updateFn","priority","defaultPriority","onUpdate","_flush","flushId","forEach","batch","cb"],"mappings":";;;;;;;;;;AAmBO,MAAMA,KAAK,CAGhB;AACAC,EAAAA,SAAS,GAAG,IAAIC,GAAG,EAAY,CAAA;AAG/BC,EAAAA,SAAS,GAAG,KAAK,CAAA;AACjBC,EAAAA,SAAS,GAAG,CAAC,CAAA;AACbC,EAAAA,aAAa,GAAoB,IAAI,CAAA;AAErCC,EAAAA,WAAWA,CAACC,YAAoB,EAAEC,OAAwC,EAAE;IAC1E,IAAI,CAACC,KAAK,GAAGF,YAAY,CAAA;IACzB,IAAI,CAACC,OAAO,GAAGA,OAAO,CAAA;AACxB,GAAA;EAEAE,SAAS,GAAIC,QAAkB,IAAK;AAClC,IAAA,IAAI,CAACV,SAAS,CAACW,GAAG,CAACD,QAAQ,CAAC,CAAA;IAC5B,MAAME,KAAK,GAAG,IAAI,CAACL,OAAO,EAAEM,WAAW,GAAGH,QAAQ,EAAE,IAAI,CAAC,CAAA;AACzD,IAAA,OAAO,MAAM;AACX,MAAA,IAAI,CAACV,SAAS,CAACc,MAAM,CAACJ,QAAQ,CAAC,CAAA;AAC/BE,MAAAA,KAAK,IAAI,CAAA;KACV,CAAA;GACF,CAAA;AAEDG,EAAAA,QAAQ,GAAGA,CACTC,OAAiB,EACjBC,IAEC,KACE;AACH,IAAA,MAAMC,QAAQ,GAAG,IAAI,CAACV,KAAK,CAAA;IAC3B,IAAI,CAACA,KAAK,GAAG,IAAI,CAACD,OAAO,EAAEY,QAAQ,GAC/B,IAAI,CAACZ,OAAO,CAACY,QAAQ,CAACD,QAAQ,CAAC,CAACF,OAAO,CAAC,GACvCA,OAAO,CAASE,QAAQ,CAAC,CAAA;AAE9B,IAAA,MAAME,QAAQ,GAAGH,IAAI,EAAEG,QAAQ,IAAI,IAAI,CAACb,OAAO,EAAEc,eAAe,IAAI,MAAM,CAAA;AAC1E,IAAA,IAAI,IAAI,CAACjB,aAAa,KAAK,IAAI,EAAE;MAC/B,IAAI,CAACA,aAAa,GAAGgB,QAAQ,CAAA;AAC/B,KAAC,MAAM,IAAI,IAAI,CAAChB,aAAa,KAAK,MAAM,EAAE;MACxC,IAAI,CAACA,aAAa,GAAGgB,QAAQ,CAAA;AAC/B,KAAC,MAAM;MACL,IAAI,CAAChB,aAAa,GAAG,IAAI,CAACG,OAAO,EAAEc,eAAe,IAAI,MAAM,CAAA;AAC9D,KAAA;;AAEA;AACA,IAAA,IAAI,CAACd,OAAO,EAAEe,QAAQ,GAAG;MACvBF,QAAQ,EAAE,IAAI,CAAChB,aAAAA;AACjB,KAAC,CAAC,CAAA;;AAEF;IACA,IAAI,CAACmB,MAAM,EAAE,CAAA;GACd,CAAA;EAEDA,MAAM,GAAGA,MAAM;IACb,IAAI,IAAI,CAACrB,SAAS,EAAE,OAAA;AACpB,IAAA,MAAMsB,OAAO,GAAG,EAAE,IAAI,CAACrB,SAAS,CAAA;AAChC,IAAA,IAAI,CAACH,SAAS,CAACyB,OAAO,CAAEf,QAAQ,IAAK;AACnC,MAAA,IAAI,IAAI,CAACP,SAAS,KAAKqB,OAAO,EAAE,OAAA;AAChCd,MAAAA,QAAQ,CAAC;AACPU,QAAAA,QAAQ,EAAE,IAAI,CAAChB,aAAa,IAAI,MAAA;AAClC,OAAC,CAAC,CAAA;AACJ,KAAC,CAAC,CAAA;GACH,CAAA;EAEDsB,KAAK,GAAIC,EAAc,IAAK;AAC1B,IAAA,IAAI,IAAI,CAACzB,SAAS,EAAE,OAAOyB,EAAE,EAAE,CAAA;IAC/B,IAAI,CAACzB,SAAS,GAAG,IAAI,CAAA;AACrByB,IAAAA,EAAE,EAAE,CAAA;IACJ,IAAI,CAACzB,SAAS,GAAG,KAAK,CAAA;IACtB,IAAI,CAACqB,MAAM,EAAE,CAAA;GACd,CAAA;AACH;;;;"}
@@ -4024,7 +4024,7 @@ var drawChart = (function (exports) {
4024
4024
  </script>
4025
4025
  <script>
4026
4026
  /*<!--*/
4027
- const data = {"version":2,"tree":{"name":"root","children":[{"name":"index.production.js","children":[{"name":"packages/store/src/index.ts","uid":"b161-1"}]}],"isRoot":true},"nodeParts":{"b161-1":{"renderedLength":1096,"gzipLength":376,"brotliLength":0,"mainUid":"b161-0"}},"nodeMetas":{"b161-0":{"id":"/packages/store/src/index.ts","moduleParts":{"index.production.js":"b161-1"},"imported":[],"importedBy":[],"isEntry":true}},"env":{"rollup":"2.79.1"},"options":{"gzip":true,"brotli":false,"sourcemap":false}};
4027
+ const data = {"version":2,"tree":{"name":"root","children":[{"name":"index.production.js","children":[{"name":"packages/store/src/index.ts","uid":"1b85-1"}]}],"isRoot":true},"nodeParts":{"1b85-1":{"renderedLength":1603,"gzipLength":519,"brotliLength":0,"mainUid":"1b85-0"}},"nodeMetas":{"1b85-0":{"id":"/packages/store/src/index.ts","moduleParts":{"index.production.js":"1b85-1"},"imported":[],"importedBy":[],"isEntry":true}},"env":{"rollup":"2.79.1"},"options":{"gzip":true,"brotli":false,"sourcemap":false}};
4028
4028
 
4029
4029
  const run = () => {
4030
4030
  const width = window.innerWidth;
@@ -8,7 +8,7 @@
8
8
  "children": [
9
9
  {
10
10
  "name": "packages/store/src/index.ts",
11
- "uid": "b161-3"
11
+ "uid": "1b85-3"
12
12
  }
13
13
  ]
14
14
  }
@@ -16,18 +16,18 @@
16
16
  "isRoot": true
17
17
  },
18
18
  "nodeParts": {
19
- "b161-3": {
20
- "renderedLength": 1096,
21
- "gzipLength": 376,
19
+ "1b85-3": {
20
+ "renderedLength": 1603,
21
+ "gzipLength": 519,
22
22
  "brotliLength": 0,
23
- "mainUid": "b161-2"
23
+ "mainUid": "1b85-2"
24
24
  }
25
25
  },
26
26
  "nodeMetas": {
27
- "b161-2": {
27
+ "1b85-2": {
28
28
  "id": "/packages/store/src/index.ts",
29
29
  "moduleParts": {
30
- "index.production.js": "b161-3"
30
+ "index.production.js": "1b85-3"
31
31
  },
32
32
  "imported": [],
33
33
  "importedBy": [],
@@ -1,5 +1,5 @@
1
1
  /**
2
- * store
2
+ * @tanstack/store/src/index.ts
3
3
  *
4
4
  * Copyright (c) TanStack
5
5
  *
@@ -9,21 +9,32 @@
9
9
  * @license MIT
10
10
  */
11
11
  type AnyUpdater = (...args: any[]) => any;
12
- type Listener = () => void;
12
+ type Listener = (opts: {
13
+ priority: Priority;
14
+ }) => void;
15
+ type Priority = 'high' | 'low';
13
16
  interface StoreOptions<TState, TUpdater extends AnyUpdater = (cb: TState) => TState> {
14
17
  updateFn?: (previous: TState) => (updater: TUpdater) => TState;
15
18
  onSubscribe?: (listener: Listener, store: Store<TState, TUpdater>) => () => void;
16
- onUpdate?: () => void;
19
+ onUpdate?: (opts: {
20
+ priority: Priority;
21
+ }) => void;
22
+ defaultPriority?: Priority;
17
23
  }
18
24
  declare class Store<TState, TUpdater extends AnyUpdater = (cb: TState) => TState> {
19
- #private;
20
25
  listeners: Set<Listener>;
21
26
  state: TState;
22
27
  options?: StoreOptions<TState, TUpdater>;
28
+ _batching: boolean;
29
+ _flushing: number;
30
+ _nextPriority: null | Priority;
23
31
  constructor(initialState: TState, options?: StoreOptions<TState, TUpdater>);
24
32
  subscribe: (listener: Listener) => () => void;
25
- setState: (updater: TUpdater) => void;
33
+ setState: (updater: TUpdater, opts?: {
34
+ priority: Priority;
35
+ }) => void;
36
+ _flush: () => void;
26
37
  batch: (cb: () => void) => void;
27
38
  }
28
39
 
29
- export { AnyUpdater, Listener, Store };
40
+ export { AnyUpdater, Listener, Priority, Store };
@@ -1,5 +1,5 @@
1
1
  /**
2
- * store
2
+ * @tanstack/store/src/index.ts
3
3
  *
4
4
  * Copyright (c) TanStack
5
5
  *
@@ -16,14 +16,12 @@
16
16
 
17
17
  class Store {
18
18
  listeners = new Set();
19
- #batching = false;
20
- #flushing = 0;
19
+ _batching = false;
20
+ _flushing = 0;
21
+ _nextPriority = null;
21
22
  constructor(initialState, options) {
22
23
  this.state = initialState;
23
24
  this.options = options;
24
- if (this.options?.onUpdate) {
25
- this.subscribe(this.options?.onUpdate);
26
- }
27
25
  }
28
26
  subscribe = listener => {
29
27
  this.listeners.add(listener);
@@ -33,25 +31,42 @@
33
31
  unsub?.();
34
32
  };
35
33
  };
36
- setState = updater => {
34
+ setState = (updater, opts) => {
37
35
  const previous = this.state;
38
36
  this.state = this.options?.updateFn ? this.options.updateFn(previous)(updater) : updater(previous);
39
- this.#flush();
37
+ const priority = opts?.priority ?? this.options?.defaultPriority ?? 'high';
38
+ if (this._nextPriority === null) {
39
+ this._nextPriority = priority;
40
+ } else if (this._nextPriority === 'high') {
41
+ this._nextPriority = priority;
42
+ } else {
43
+ this._nextPriority = this.options?.defaultPriority ?? 'high';
44
+ }
45
+
46
+ // Always run onUpdate, regardless of batching
47
+ this.options?.onUpdate?.({
48
+ priority: this._nextPriority
49
+ });
50
+
51
+ // Attempt to flush
52
+ this._flush();
40
53
  };
41
- #flush = () => {
42
- if (this.#batching) return;
43
- const flushId = ++this.#flushing;
54
+ _flush = () => {
55
+ if (this._batching) return;
56
+ const flushId = ++this._flushing;
44
57
  this.listeners.forEach(listener => {
45
- if (this.#flushing !== flushId) return;
46
- listener();
58
+ if (this._flushing !== flushId) return;
59
+ listener({
60
+ priority: this._nextPriority ?? 'high'
61
+ });
47
62
  });
48
63
  };
49
64
  batch = cb => {
50
- if (this.#batching) return cb();
51
- this.#batching = true;
65
+ if (this._batching) return cb();
66
+ this._batching = true;
52
67
  cb();
53
- this.#batching = false;
54
- this.#flush();
68
+ this._batching = false;
69
+ this._flush();
55
70
  };
56
71
  }
57
72
 
@@ -1 +1 @@
1
- {"version":3,"file":"index.development.js","sources":["../../src/index.ts"],"sourcesContent":["export type AnyUpdater = (...args: any[]) => any\n\nexport type Listener = () => void\n\ninterface StoreOptions<\n TState,\n TUpdater extends AnyUpdater = (cb: TState) => TState,\n> {\n updateFn?: (previous: TState) => (updater: TUpdater) => TState\n onSubscribe?: (\n listener: Listener,\n store: Store<TState, TUpdater>,\n ) => () => void\n onUpdate?: () => void\n}\n\nexport class Store<\n TState,\n TUpdater extends AnyUpdater = (cb: TState) => TState,\n> {\n listeners = new Set<Listener>()\n state: TState\n options?: StoreOptions<TState, TUpdater>\n #batching = false\n #flushing = 0\n\n constructor(initialState: TState, options?: StoreOptions<TState, TUpdater>) {\n this.state = initialState\n this.options = options\n if (this.options?.onUpdate) {\n this.subscribe(this.options?.onUpdate)\n }\n }\n\n subscribe = (listener: Listener) => {\n this.listeners.add(listener)\n const unsub = this.options?.onSubscribe?.(listener, this)\n return () => {\n this.listeners.delete(listener)\n unsub?.()\n }\n }\n\n setState = (updater: TUpdater) => {\n const previous = this.state\n this.state = this.options?.updateFn\n ? this.options.updateFn(previous)(updater)\n : (updater as any)(previous)\n\n this.#flush()\n }\n\n #flush = () => {\n if (this.#batching) return\n const flushId = ++this.#flushing\n this.listeners.forEach((listener) => {\n if (this.#flushing !== flushId) return\n listener()\n })\n }\n\n batch = (cb: () => void) => {\n if (this.#batching) return cb()\n this.#batching = true\n cb()\n this.#batching = false\n this.#flush()\n }\n}\n"],"names":["Store","listeners","Set","constructor","initialState","options","state","onUpdate","subscribe","listener","add","unsub","onSubscribe","delete","setState","updater","previous","updateFn","flushId","forEach","batch","cb"],"mappings":";;;;;;;;;;;;;;;;EAgBO,MAAMA,KAAK,CAGhB;IACAC,SAAS,GAAG,IAAIC,GAAG,EAAY,CAAA;IAG/B,SAAS,GAAG,KAAK,CAAA;IACjB,SAAS,GAAG,CAAC,CAAA;EAEbC,EAAAA,WAAW,CAACC,YAAoB,EAAEC,OAAwC,EAAE;MAC1E,IAAI,CAACC,KAAK,GAAGF,YAAY,CAAA;MACzB,IAAI,CAACC,OAAO,GAAGA,OAAO,CAAA;EACtB,IAAA,IAAI,IAAI,CAACA,OAAO,EAAEE,QAAQ,EAAE;QAC1B,IAAI,CAACC,SAAS,CAAC,IAAI,CAACH,OAAO,EAAEE,QAAQ,CAAC,CAAA;EACxC,KAAA;EACF,GAAA;IAEAC,SAAS,GAAIC,QAAkB,IAAK;EAClC,IAAA,IAAI,CAACR,SAAS,CAACS,GAAG,CAACD,QAAQ,CAAC,CAAA;MAC5B,MAAME,KAAK,GAAG,IAAI,CAACN,OAAO,EAAEO,WAAW,GAAGH,QAAQ,EAAE,IAAI,CAAC,CAAA;EACzD,IAAA,OAAO,MAAM;EACX,MAAA,IAAI,CAACR,SAAS,CAACY,MAAM,CAACJ,QAAQ,CAAC,CAAA;EAC/BE,MAAAA,KAAK,IAAI,CAAA;OACV,CAAA;KACF,CAAA;IAEDG,QAAQ,GAAIC,OAAiB,IAAK;EAChC,IAAA,MAAMC,QAAQ,GAAG,IAAI,CAACV,KAAK,CAAA;MAC3B,IAAI,CAACA,KAAK,GAAG,IAAI,CAACD,OAAO,EAAEY,QAAQ,GAC/B,IAAI,CAACZ,OAAO,CAACY,QAAQ,CAACD,QAAQ,CAAC,CAACD,OAAO,CAAC,GACvCA,OAAO,CAASC,QAAQ,CAAC,CAAA;MAE9B,IAAI,CAAC,MAAM,EAAE,CAAA;KACd,CAAA;IAED,MAAM,GAAG,MAAM;EACb,IAAA,IAAI,IAAI,CAAC,SAAS,EAAE,OAAA;EACpB,IAAA,MAAME,OAAO,GAAG,EAAE,IAAI,CAAC,SAAS,CAAA;EAChC,IAAA,IAAI,CAACjB,SAAS,CAACkB,OAAO,CAAEV,QAAQ,IAAK;EACnC,MAAA,IAAI,IAAI,CAAC,SAAS,KAAKS,OAAO,EAAE,OAAA;EAChCT,MAAAA,QAAQ,EAAE,CAAA;EACZ,KAAC,CAAC,CAAA;KACH,CAAA;IAEDW,KAAK,GAAIC,EAAc,IAAK;EAC1B,IAAA,IAAI,IAAI,CAAC,SAAS,EAAE,OAAOA,EAAE,EAAE,CAAA;EAC/B,IAAA,IAAI,CAAC,SAAS,GAAG,IAAI,CAAA;EACrBA,IAAAA,EAAE,EAAE,CAAA;EACJ,IAAA,IAAI,CAAC,SAAS,GAAG,KAAK,CAAA;MACtB,IAAI,CAAC,MAAM,EAAE,CAAA;KACd,CAAA;EACH;;;;;;;;;;"}
1
+ {"version":3,"file":"index.development.js","sources":["../../src/index.ts"],"sourcesContent":["export type AnyUpdater = (...args: any[]) => any\n\nexport type Listener = (opts: { priority: Priority }) => void\n\nexport type Priority = 'high' | 'low'\n\ninterface StoreOptions<\n TState,\n TUpdater extends AnyUpdater = (cb: TState) => TState,\n> {\n updateFn?: (previous: TState) => (updater: TUpdater) => TState\n onSubscribe?: (\n listener: Listener,\n store: Store<TState, TUpdater>,\n ) => () => void\n onUpdate?: (opts: { priority: Priority }) => void\n defaultPriority?: Priority\n}\n\nexport class Store<\n TState,\n TUpdater extends AnyUpdater = (cb: TState) => TState,\n> {\n listeners = new Set<Listener>()\n state: TState\n options?: StoreOptions<TState, TUpdater>\n _batching = false\n _flushing = 0\n _nextPriority: null | Priority = null\n\n constructor(initialState: TState, options?: StoreOptions<TState, TUpdater>) {\n this.state = initialState\n this.options = options\n }\n\n subscribe = (listener: Listener) => {\n this.listeners.add(listener)\n const unsub = this.options?.onSubscribe?.(listener, this)\n return () => {\n this.listeners.delete(listener)\n unsub?.()\n }\n }\n\n setState = (\n updater: TUpdater,\n opts?: {\n priority: Priority\n },\n ) => {\n const previous = this.state\n this.state = this.options?.updateFn\n ? this.options.updateFn(previous)(updater)\n : (updater as any)(previous)\n\n const priority = opts?.priority ?? this.options?.defaultPriority ?? 'high'\n if (this._nextPriority === null) {\n this._nextPriority = priority\n } else if (this._nextPriority === 'high') {\n this._nextPriority = priority\n } else {\n this._nextPriority = this.options?.defaultPriority ?? 'high'\n }\n\n // Always run onUpdate, regardless of batching\n this.options?.onUpdate?.({\n priority: this._nextPriority,\n })\n\n // Attempt to flush\n this._flush()\n }\n\n _flush = () => {\n if (this._batching) return\n const flushId = ++this._flushing\n this.listeners.forEach((listener) => {\n if (this._flushing !== flushId) return\n listener({\n priority: this._nextPriority ?? 'high',\n })\n })\n }\n\n batch = (cb: () => void) => {\n if (this._batching) return cb()\n this._batching = true\n cb()\n this._batching = false\n this._flush()\n }\n}\n"],"names":["Store","listeners","Set","_batching","_flushing","_nextPriority","constructor","initialState","options","state","subscribe","listener","add","unsub","onSubscribe","delete","setState","updater","opts","previous","updateFn","priority","defaultPriority","onUpdate","_flush","flushId","forEach","batch","cb"],"mappings":";;;;;;;;;;;;;;;;EAmBO,MAAMA,KAAK,CAGhB;EACAC,EAAAA,SAAS,GAAG,IAAIC,GAAG,EAAY,CAAA;EAG/BC,EAAAA,SAAS,GAAG,KAAK,CAAA;EACjBC,EAAAA,SAAS,GAAG,CAAC,CAAA;EACbC,EAAAA,aAAa,GAAoB,IAAI,CAAA;EAErCC,EAAAA,WAAWA,CAACC,YAAoB,EAAEC,OAAwC,EAAE;MAC1E,IAAI,CAACC,KAAK,GAAGF,YAAY,CAAA;MACzB,IAAI,CAACC,OAAO,GAAGA,OAAO,CAAA;EACxB,GAAA;IAEAE,SAAS,GAAIC,QAAkB,IAAK;EAClC,IAAA,IAAI,CAACV,SAAS,CAACW,GAAG,CAACD,QAAQ,CAAC,CAAA;MAC5B,MAAME,KAAK,GAAG,IAAI,CAACL,OAAO,EAAEM,WAAW,GAAGH,QAAQ,EAAE,IAAI,CAAC,CAAA;EACzD,IAAA,OAAO,MAAM;EACX,MAAA,IAAI,CAACV,SAAS,CAACc,MAAM,CAACJ,QAAQ,CAAC,CAAA;EAC/BE,MAAAA,KAAK,IAAI,CAAA;OACV,CAAA;KACF,CAAA;EAEDG,EAAAA,QAAQ,GAAGA,CACTC,OAAiB,EACjBC,IAEC,KACE;EACH,IAAA,MAAMC,QAAQ,GAAG,IAAI,CAACV,KAAK,CAAA;MAC3B,IAAI,CAACA,KAAK,GAAG,IAAI,CAACD,OAAO,EAAEY,QAAQ,GAC/B,IAAI,CAACZ,OAAO,CAACY,QAAQ,CAACD,QAAQ,CAAC,CAACF,OAAO,CAAC,GACvCA,OAAO,CAASE,QAAQ,CAAC,CAAA;EAE9B,IAAA,MAAME,QAAQ,GAAGH,IAAI,EAAEG,QAAQ,IAAI,IAAI,CAACb,OAAO,EAAEc,eAAe,IAAI,MAAM,CAAA;EAC1E,IAAA,IAAI,IAAI,CAACjB,aAAa,KAAK,IAAI,EAAE;QAC/B,IAAI,CAACA,aAAa,GAAGgB,QAAQ,CAAA;EAC/B,KAAC,MAAM,IAAI,IAAI,CAAChB,aAAa,KAAK,MAAM,EAAE;QACxC,IAAI,CAACA,aAAa,GAAGgB,QAAQ,CAAA;EAC/B,KAAC,MAAM;QACL,IAAI,CAAChB,aAAa,GAAG,IAAI,CAACG,OAAO,EAAEc,eAAe,IAAI,MAAM,CAAA;EAC9D,KAAA;;EAEA;EACA,IAAA,IAAI,CAACd,OAAO,EAAEe,QAAQ,GAAG;QACvBF,QAAQ,EAAE,IAAI,CAAChB,aAAAA;EACjB,KAAC,CAAC,CAAA;;EAEF;MACA,IAAI,CAACmB,MAAM,EAAE,CAAA;KACd,CAAA;IAEDA,MAAM,GAAGA,MAAM;MACb,IAAI,IAAI,CAACrB,SAAS,EAAE,OAAA;EACpB,IAAA,MAAMsB,OAAO,GAAG,EAAE,IAAI,CAACrB,SAAS,CAAA;EAChC,IAAA,IAAI,CAACH,SAAS,CAACyB,OAAO,CAAEf,QAAQ,IAAK;EACnC,MAAA,IAAI,IAAI,CAACP,SAAS,KAAKqB,OAAO,EAAE,OAAA;EAChCd,MAAAA,QAAQ,CAAC;EACPU,QAAAA,QAAQ,EAAE,IAAI,CAAChB,aAAa,IAAI,MAAA;EAClC,OAAC,CAAC,CAAA;EACJ,KAAC,CAAC,CAAA;KACH,CAAA;IAEDsB,KAAK,GAAIC,EAAc,IAAK;EAC1B,IAAA,IAAI,IAAI,CAACzB,SAAS,EAAE,OAAOyB,EAAE,EAAE,CAAA;MAC/B,IAAI,CAACzB,SAAS,GAAG,IAAI,CAAA;EACrByB,IAAAA,EAAE,EAAE,CAAA;MACJ,IAAI,CAACzB,SAAS,GAAG,KAAK,CAAA;MACtB,IAAI,CAACqB,MAAM,EAAE,CAAA;KACd,CAAA;EACH;;;;;;;;;;"}
@@ -1,5 +1,5 @@
1
1
  /**
2
- * store
2
+ * @tanstack/store/src/index.ts
3
3
  *
4
4
  * Copyright (c) TanStack
5
5
  *
@@ -8,5 +8,5 @@
8
8
  *
9
9
  * @license MIT
10
10
  */
11
- !function(t,s){"object"==typeof exports&&"undefined"!=typeof module?s(exports):"function"==typeof define&&define.amd?define(["exports"],s):s((t="undefined"!=typeof globalThis?globalThis:t||self).Store={})}(this,(function(t){"use strict";t.Store=class{listeners=new Set;#t=!1;#s=0;constructor(t,s){this.state=t,this.options=s,this.options?.onUpdate&&this.subscribe(this.options?.onUpdate)}subscribe=t=>{this.listeners.add(t);const s=this.options?.onSubscribe?.(t,this);return()=>{this.listeners.delete(t),s?.()}};setState=t=>{const s=this.state;this.state=this.options?.updateFn?this.options.updateFn(s)(t):t(s),this.#e()};#e=()=>{if(this.#t)return;const t=++this.#s;this.listeners.forEach((s=>{this.#s===t&&s()}))};batch=t=>{if(this.#t)return t();this.#t=!0,t(),this.#t=!1,this.#e()}},Object.defineProperty(t,"__esModule",{value:!0})}));
11
+ !function(t,i){"object"==typeof exports&&"undefined"!=typeof module?i(exports):"function"==typeof define&&define.amd?define(["exports"],i):i((t="undefined"!=typeof globalThis?globalThis:t||self).Store={})}(this,(function(t){"use strict";t.Store=class{listeners=new Set;_batching=!1;_flushing=0;_nextPriority=null;constructor(t,i){this.state=t,this.options=i}subscribe=t=>{this.listeners.add(t);const i=this.options?.onSubscribe?.(t,this);return()=>{this.listeners.delete(t),i?.()}};setState=(t,i)=>{const s=this.state;this.state=this.options?.updateFn?this.options.updateFn(s)(t):t(s);const e=i?.priority??this.options?.defaultPriority??"high";null===this._nextPriority||"high"===this._nextPriority?this._nextPriority=e:this._nextPriority=this.options?.defaultPriority??"high",this.options?.onUpdate?.({priority:this._nextPriority}),this._flush()};_flush=()=>{if(this._batching)return;const t=++this._flushing;this.listeners.forEach((i=>{this._flushing===t&&i({priority:this._nextPriority??"high"})}))};batch=t=>{if(this._batching)return t();this._batching=!0,t(),this._batching=!1,this._flush()}},Object.defineProperty(t,"__esModule",{value:!0})}));
12
12
  //# sourceMappingURL=index.production.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.production.js","sources":["../../src/index.ts"],"sourcesContent":["export type AnyUpdater = (...args: any[]) => any\n\nexport type Listener = () => void\n\ninterface StoreOptions<\n TState,\n TUpdater extends AnyUpdater = (cb: TState) => TState,\n> {\n updateFn?: (previous: TState) => (updater: TUpdater) => TState\n onSubscribe?: (\n listener: Listener,\n store: Store<TState, TUpdater>,\n ) => () => void\n onUpdate?: () => void\n}\n\nexport class Store<\n TState,\n TUpdater extends AnyUpdater = (cb: TState) => TState,\n> {\n listeners = new Set<Listener>()\n state: TState\n options?: StoreOptions<TState, TUpdater>\n #batching = false\n #flushing = 0\n\n constructor(initialState: TState, options?: StoreOptions<TState, TUpdater>) {\n this.state = initialState\n this.options = options\n if (this.options?.onUpdate) {\n this.subscribe(this.options?.onUpdate)\n }\n }\n\n subscribe = (listener: Listener) => {\n this.listeners.add(listener)\n const unsub = this.options?.onSubscribe?.(listener, this)\n return () => {\n this.listeners.delete(listener)\n unsub?.()\n }\n }\n\n setState = (updater: TUpdater) => {\n const previous = this.state\n this.state = this.options?.updateFn\n ? this.options.updateFn(previous)(updater)\n : (updater as any)(previous)\n\n this.#flush()\n }\n\n #flush = () => {\n if (this.#batching) return\n const flushId = ++this.#flushing\n this.listeners.forEach((listener) => {\n if (this.#flushing !== flushId) return\n listener()\n })\n }\n\n batch = (cb: () => void) => {\n if (this.#batching) return cb()\n this.#batching = true\n cb()\n this.#batching = false\n this.#flush()\n }\n}\n"],"names":["listeners","Set","batching","flushing","constructor","initialState","options","this","state","onUpdate","subscribe","listener","add","unsub","onSubscribe","delete","setState","updater","previous","updateFn","flush","flushId","forEach","batch","cb"],"mappings":";;;;;;;;;;qPAgBO,MAILA,UAAY,IAAIC,IAGhBC,IAAY,EACZC,GAAY,EAEZC,YAAYC,EAAsBC,GAChCC,KAAKC,MAAQH,EACbE,KAAKD,QAAUA,EACXC,KAAKD,SAASG,UAChBF,KAAKG,UAAUH,KAAKD,SAASG,SAEjC,CAEAC,UAAaC,IACXJ,KAAKP,UAAUY,IAAID,GACnB,MAAME,EAAQN,KAAKD,SAASQ,cAAcH,EAAUJ,MACpD,MAAO,KACLA,KAAKP,UAAUe,OAAOJ,GACtBE,KAAS,CACV,EAGHG,SAAYC,IACV,MAAMC,EAAWX,KAAKC,MACtBD,KAAKC,MAAQD,KAAKD,SAASa,SACvBZ,KAAKD,QAAQa,SAASD,EAAtBX,CAAgCU,GAC/BA,EAAgBC,GAErBX,MAAKa,GAAQ,EAGfA,GAAS,KACP,GAAIb,MAAKL,EAAW,OACpB,MAAMmB,IAAYd,MAAKJ,EACvBI,KAAKP,UAAUsB,SAASX,IAClBJ,MAAKJ,IAAckB,GACvBV,GAAU,GACV,EAGJY,MAASC,IACP,GAAIjB,MAAKL,EAAW,OAAOsB,IAC3BjB,MAAKL,GAAY,EACjBsB,IACAjB,MAAKL,GAAY,EACjBK,MAAKa,GAAQ"}
1
+ {"version":3,"file":"index.production.js","sources":["../../src/index.ts"],"sourcesContent":["export type AnyUpdater = (...args: any[]) => any\n\nexport type Listener = (opts: { priority: Priority }) => void\n\nexport type Priority = 'high' | 'low'\n\ninterface StoreOptions<\n TState,\n TUpdater extends AnyUpdater = (cb: TState) => TState,\n> {\n updateFn?: (previous: TState) => (updater: TUpdater) => TState\n onSubscribe?: (\n listener: Listener,\n store: Store<TState, TUpdater>,\n ) => () => void\n onUpdate?: (opts: { priority: Priority }) => void\n defaultPriority?: Priority\n}\n\nexport class Store<\n TState,\n TUpdater extends AnyUpdater = (cb: TState) => TState,\n> {\n listeners = new Set<Listener>()\n state: TState\n options?: StoreOptions<TState, TUpdater>\n _batching = false\n _flushing = 0\n _nextPriority: null | Priority = null\n\n constructor(initialState: TState, options?: StoreOptions<TState, TUpdater>) {\n this.state = initialState\n this.options = options\n }\n\n subscribe = (listener: Listener) => {\n this.listeners.add(listener)\n const unsub = this.options?.onSubscribe?.(listener, this)\n return () => {\n this.listeners.delete(listener)\n unsub?.()\n }\n }\n\n setState = (\n updater: TUpdater,\n opts?: {\n priority: Priority\n },\n ) => {\n const previous = this.state\n this.state = this.options?.updateFn\n ? this.options.updateFn(previous)(updater)\n : (updater as any)(previous)\n\n const priority = opts?.priority ?? this.options?.defaultPriority ?? 'high'\n if (this._nextPriority === null) {\n this._nextPriority = priority\n } else if (this._nextPriority === 'high') {\n this._nextPriority = priority\n } else {\n this._nextPriority = this.options?.defaultPriority ?? 'high'\n }\n\n // Always run onUpdate, regardless of batching\n this.options?.onUpdate?.({\n priority: this._nextPriority,\n })\n\n // Attempt to flush\n this._flush()\n }\n\n _flush = () => {\n if (this._batching) return\n const flushId = ++this._flushing\n this.listeners.forEach((listener) => {\n if (this._flushing !== flushId) return\n listener({\n priority: this._nextPriority ?? 'high',\n })\n })\n }\n\n batch = (cb: () => void) => {\n if (this._batching) return cb()\n this._batching = true\n cb()\n this._batching = false\n this._flush()\n }\n}\n"],"names":["listeners","Set","_batching","_flushing","_nextPriority","constructor","initialState","options","this","state","subscribe","listener","add","unsub","onSubscribe","delete","setState","updater","opts","previous","updateFn","priority","defaultPriority","onUpdate","_flush","flushId","forEach","batch","cb"],"mappings":";;;;;;;;;;qPAmBO,MAILA,UAAY,IAAIC,IAGhBC,WAAY,EACZC,UAAY,EACZC,cAAiC,KAEjCC,YAAYC,EAAsBC,GAChCC,KAAKC,MAAQH,EACbE,KAAKD,QAAUA,CACjB,CAEAG,UAAaC,IACXH,KAAKR,UAAUY,IAAID,GACnB,MAAME,EAAQL,KAAKD,SAASO,cAAcH,EAAUH,MACpD,MAAO,KACLA,KAAKR,UAAUe,OAAOJ,GACtBE,KAAS,CACV,EAGHG,SAAWA,CACTC,EACAC,KAIA,MAAMC,EAAWX,KAAKC,MACtBD,KAAKC,MAAQD,KAAKD,SAASa,SACvBZ,KAAKD,QAAQa,SAASD,EAAtBX,CAAgCS,GAC/BA,EAAgBE,GAErB,MAAME,EAAWH,GAAMG,UAAYb,KAAKD,SAASe,iBAAmB,OACzC,OAAvBd,KAAKJ,eAEyB,SAAvBI,KAAKJ,cADdI,KAAKJ,cAAgBiB,EAIrBb,KAAKJ,cAAgBI,KAAKD,SAASe,iBAAmB,OAIxDd,KAAKD,SAASgB,WAAW,CACvBF,SAAUb,KAAKJ,gBAIjBI,KAAKgB,QAAQ,EAGfA,OAASA,KACP,GAAIhB,KAAKN,UAAW,OACpB,MAAMuB,IAAYjB,KAAKL,UACvBK,KAAKR,UAAU0B,SAASf,IAClBH,KAAKL,YAAcsB,GACvBd,EAAS,CACPU,SAAUb,KAAKJ,eAAiB,QAChC,GACF,EAGJuB,MAASC,IACP,GAAIpB,KAAKN,UAAW,OAAO0B,IAC3BpB,KAAKN,WAAY,EACjB0B,IACApB,KAAKN,WAAY,EACjBM,KAAKgB,QAAQ"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tanstack/store",
3
3
  "author": "Tanner Linsley",
4
- "version": "0.0.1-beta.89",
4
+ "version": "0.0.1",
5
5
  "license": "MIT",
6
6
  "repository": "tanstack/store",
7
7
  "homepage": "https://tanstack.com/store",
@@ -30,6 +30,8 @@
30
30
  ],
31
31
  "sideEffects": false,
32
32
  "scripts": {
33
- "build": "rollup --config rollup.config.js"
33
+ "build": "rollup --config rollup.config.js",
34
+ "test": "vitest",
35
+ "test:dev": "vitest --watch"
34
36
  }
35
37
  }
package/src/index.ts CHANGED
@@ -1,6 +1,8 @@
1
1
  export type AnyUpdater = (...args: any[]) => any
2
2
 
3
- export type Listener = () => void
3
+ export type Listener = (opts: { priority: Priority }) => void
4
+
5
+ export type Priority = 'high' | 'low'
4
6
 
5
7
  interface StoreOptions<
6
8
  TState,
@@ -11,7 +13,8 @@ interface StoreOptions<
11
13
  listener: Listener,
12
14
  store: Store<TState, TUpdater>,
13
15
  ) => () => void
14
- onUpdate?: () => void
16
+ onUpdate?: (opts: { priority: Priority }) => void
17
+ defaultPriority?: Priority
15
18
  }
16
19
 
17
20
  export class Store<
@@ -21,15 +24,13 @@ export class Store<
21
24
  listeners = new Set<Listener>()
22
25
  state: TState
23
26
  options?: StoreOptions<TState, TUpdater>
24
- #batching = false
25
- #flushing = 0
27
+ _batching = false
28
+ _flushing = 0
29
+ _nextPriority: null | Priority = null
26
30
 
27
31
  constructor(initialState: TState, options?: StoreOptions<TState, TUpdater>) {
28
32
  this.state = initialState
29
33
  this.options = options
30
- if (this.options?.onUpdate) {
31
- this.subscribe(this.options?.onUpdate)
32
- }
33
34
  }
34
35
 
35
36
  subscribe = (listener: Listener) => {
@@ -41,29 +42,51 @@ export class Store<
41
42
  }
42
43
  }
43
44
 
44
- setState = (updater: TUpdater) => {
45
+ setState = (
46
+ updater: TUpdater,
47
+ opts?: {
48
+ priority: Priority
49
+ },
50
+ ) => {
45
51
  const previous = this.state
46
52
  this.state = this.options?.updateFn
47
53
  ? this.options.updateFn(previous)(updater)
48
54
  : (updater as any)(previous)
49
55
 
50
- this.#flush()
56
+ const priority = opts?.priority ?? this.options?.defaultPriority ?? 'high'
57
+ if (this._nextPriority === null) {
58
+ this._nextPriority = priority
59
+ } else if (this._nextPriority === 'high') {
60
+ this._nextPriority = priority
61
+ } else {
62
+ this._nextPriority = this.options?.defaultPriority ?? 'high'
63
+ }
64
+
65
+ // Always run onUpdate, regardless of batching
66
+ this.options?.onUpdate?.({
67
+ priority: this._nextPriority,
68
+ })
69
+
70
+ // Attempt to flush
71
+ this._flush()
51
72
  }
52
73
 
53
- #flush = () => {
54
- if (this.#batching) return
55
- const flushId = ++this.#flushing
74
+ _flush = () => {
75
+ if (this._batching) return
76
+ const flushId = ++this._flushing
56
77
  this.listeners.forEach((listener) => {
57
- if (this.#flushing !== flushId) return
58
- listener()
78
+ if (this._flushing !== flushId) return
79
+ listener({
80
+ priority: this._nextPriority ?? 'high',
81
+ })
59
82
  })
60
83
  }
61
84
 
62
85
  batch = (cb: () => void) => {
63
- if (this.#batching) return cb()
64
- this.#batching = true
86
+ if (this._batching) return cb()
87
+ this._batching = true
65
88
  cb()
66
- this.#batching = false
67
- this.#flush()
89
+ this._batching = false
90
+ this._flush()
68
91
  }
69
92
  }