@pond-ts/react 0.18.0 → 0.20.0

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/CHANGELOG.md CHANGED
@@ -7,11 +7,76 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
7
7
  file covers both packages. Pre-1.0: minor bumps may include new features and
8
8
  type-level changes; patch bumps are strictly additive.
9
9
 
10
- [Unreleased]: https://github.com/pjm17971/pond-ts/compare/v0.18.0...HEAD
10
+ [Unreleased]: https://github.com/pjm17971/pond-ts/compare/v0.20.0...HEAD
11
+ [0.20.0]: https://github.com/pjm17971/pond-ts/compare/v0.19.0...v0.20.0
12
+ [0.19.0]: https://github.com/pjm17971/pond-ts/compare/v0.18.0...v0.19.0
11
13
  [0.18.0]: https://github.com/pjm17971/pond-ts/compare/v0.17.1...v0.18.0
12
14
 
13
15
  ## [Unreleased]
14
16
 
17
+ ## [0.20.0] — 2026-06-04
18
+
19
+ Two internal performance improvements driven by the dashboard experiment at
20
+ 256-host stress. **No public API changes** — both are behavior-preserving.
21
+
22
+ ### Changed
23
+
24
+ - **Column-native partition routing.** `partitionBy(...)` over a strict
25
+ time-keyed source now routes its source chunks into per-partition
26
+ **chunked** sub-series via a coalescing staging tier, replacing the
27
+ per-partition `Event[]` retention. A large drop in retained memory and
28
+ object count at high partition counts (gRPC bench at 256 partitions: 60×
29
+ fewer columnar stores, −99.4% `Event` retention, +24% sustained throughput)
30
+ ([#175](https://github.com/pjm17971/pond-ts/pull/175)). Behavior-preserving;
31
+ internal only — no public surface added.
32
+ - **`LiveView.toTimeSeries()` snapshot caching.** The built `TimeSeries` is
33
+ memoized against an internal mutation counter, so back-to-back
34
+ identical-state calls (multiple subscribers, framework commit batching,
35
+ StrictMode double-invoke) return the cached instance by reference instead of
36
+ rebuilding the whole snapshot — ~44 ms → ~0 at a 262k-event window. A
37
+ fresh-state call still builds; safe because `TimeSeries` is immutable
38
+ ([#180](https://github.com/pjm17971/pond-ts/pull/180)).
39
+
40
+ ## [0.19.0] — 2026-06-02
41
+
42
+ Adds an **experimental column-read surface to the live side** — read typed
43
+ columns straight off a `LiveView` without materializing a `TimeSeries`
44
+ snapshot — driven by the dashboard experiment's per-tick memo cost. Plus a
45
+ `useTimeSeries` schema-inference fix. The live column surface is
46
+ **experimental and expected to keep moving in 0.19.x**.
47
+
48
+ ### Added
49
+
50
+ - **`LiveView` column-read surface (experimental).** Read columns directly
51
+ off a windowed live view, the column-API counterpart to the batch
52
+ `TimeSeries` surface ([#179](https://github.com/pjm17971/pond-ts/pull/179)):
53
+ - `liveView.column(name)` — a numeric value column gathered from the view's
54
+ current events (string / array columns are a compile error; read those as
55
+ scalars or snapshot via `toTimeSeries()`).
56
+ - `liveView.keyColumn()` — the time axis (`TimeKeyColumn`; time-keyed views
57
+ only, enforced at compile time).
58
+ - `liveView.partitionBy(col).toMap(fn)` — a walk-now per-partition read
59
+ returning `Map<string, R>`, mirroring `TimeSeries.partitionBy().toMap()`
60
+ but without per-partition `TimeSeries` construction. Distinct from
61
+ `LiveSeries.partitionBy` (which is subscription-oriented). Throws on a
62
+ missing / key partition column rather than silently merging.
63
+ - `LiveColumnGroup` — the per-partition view passed to the `toMap` callback.
64
+ - **`@pond-ts/react`: `useLiveVersion(source, { throttle })` (experimental)**
65
+ — a `useSyncExternalStore`-based change signal that bumps on append **and**
66
+ eviction, so a component can read columns off a live view each render
67
+ without manufacturing a `TimeSeries` snapshot. Closes the
68
+ render-before-subscribe gap; throttling bounds only the React notification
69
+ ([#179](https://github.com/pjm17971/pond-ts/pull/179)).
70
+
71
+ ### Changed
72
+
73
+ - **`useTimeSeries` collapsed to a single generic** `<S extends SeriesSchema>`
74
+ so the schema infers from `input.schema`. The prior two-generic signature
75
+ lost `S` through the input-wrapper generic and resolved
76
+ `result.column('cpu')` to `never`; the accepted input type is unchanged, so
77
+ this is an inference fix — but a caller passing two explicit type arguments
78
+ must drop the second ([#176](https://github.com/pjm17971/pond-ts/pull/176)).
79
+
15
80
  ## [0.18.0] — 2026-05-30
16
81
 
17
82
  This release graduates the **Phase 4.7 columnar substrate** from
package/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # pond-ts
2
2
 
3
3
  **Highly optimised, fully typed Timeseries library for TypeScript**
4
-
4
+
5
5
  Schema-driven events, composable batch transforms, push-based streaming
6
6
  ingest, multi-entity partitioning, and an optional React integration —
7
7
  all strict TypeScript end to end, all immutable.
@@ -31,6 +31,11 @@ npm install @pond-ts/react # React hooks (optional)
31
31
  single node.js instance.)
32
32
  - **Triggers** — for control of rolling emission cadences. Synchronised
33
33
  partitioned rolling fires across partitions on every boundary.
34
+ - **Typed column extraction** — `series.column('cpu')` returns a
35
+ schema-narrowed typed column with single-pass reductions
36
+ (`min`/`max`/`sum`/`mean`/`stdev`/`median`/`percentile`/`minMax`),
37
+ index downsampling (`bin`), and a zero-copy `toFloat64Array()` for
38
+ canvas / WebGL draw loops — no per-event allocation on the hot path.
34
39
  - **No legacy baggage**
35
40
 
36
41
  ## Quick start: batch
package/dist/index.d.ts CHANGED
@@ -7,5 +7,6 @@ export { useLiveQuery } from './useLiveQuery.js';
7
7
  export { useLatest } from './useLatest.js';
8
8
  export { useCurrent, type UseCurrentOptions } from './useCurrent.js';
9
9
  export { useEventRate } from './useEventRate.js';
10
+ export { useLiveVersion, type UseLiveVersionOptions, } from './useLiveVersion.js';
10
11
  export { takeSnapshot } from './takeSnapshot.js';
11
12
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EACL,WAAW,EACX,KAAK,kBAAkB,EACvB,KAAK,cAAc,GACpB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,UAAU,EAAE,KAAK,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACrE,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EACL,WAAW,EACX,KAAK,kBAAkB,EACvB,KAAK,cAAc,GACpB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,UAAU,EAAE,KAAK,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACrE,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EACL,cAAc,EACd,KAAK,qBAAqB,GAC3B,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC"}
package/dist/index.js CHANGED
@@ -8,5 +8,6 @@ export { useLiveQuery } from './useLiveQuery.js';
8
8
  export { useLatest } from './useLatest.js';
9
9
  export { useCurrent } from './useCurrent.js';
10
10
  export { useEventRate } from './useEventRate.js';
11
+ export { useLiveVersion, } from './useLiveVersion.js';
11
12
  export { takeSnapshot } from './takeSnapshot.js';
12
13
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAE5D,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EACL,WAAW,GAGZ,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,UAAU,EAA0B,MAAM,iBAAiB,CAAC;AACrE,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAE5D,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EACL,WAAW,GAGZ,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,UAAU,EAA0B,MAAM,iBAAiB,CAAC;AACrE,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EACL,cAAc,GAEf,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC"}
@@ -0,0 +1,41 @@
1
+ import type { LiveSource, SeriesSchema } from 'pond-ts';
2
+ export interface UseLiveVersionOptions {
3
+ /**
4
+ * Minimum interval between React notifications, in ms. The version
5
+ * counter bumps *immediately* on every source change (no buffering);
6
+ * `throttle` only bounds how often React is told to re-render.
7
+ * `0` notifies synchronously per change. Default 100.
8
+ */
9
+ throttle?: number;
10
+ }
11
+ /**
12
+ * The React change signal for reading columns off a live source without
13
+ * manufacturing a `TimeSeries` snapshot (§A pull/read, experimental).
14
+ *
15
+ * `LiveSeries` / `LiveView` mutate in place, so a `useMemo([liveView])`
16
+ * keyed on the view never re-runs. This hook gives React a
17
+ * monotonically-increasing version that changes (at most once per
18
+ * `throttle`) whenever the source mutates — the missing invalidation
19
+ * trigger. Read columns straight off the live view, keyed on the
20
+ * returned version:
21
+ *
22
+ * ```tsx
23
+ * const view = useMemo(() => live.window('5m'), [live]);
24
+ * const v = useLiveVersion(view, { throttle: 200 });
25
+ * const series = useMemo(
26
+ * () => view.partitionBy('host').toMap((g) => ({
27
+ * ts: g.keyColumn().begin,
28
+ * cpu: g.column('cpu').toFloat64Array(),
29
+ * })),
30
+ * [view, v],
31
+ * );
32
+ * ```
33
+ *
34
+ * Tracks **both** append (`'event'`) and eviction (`'evict'`, on sources
35
+ * that emit it — e.g. `clear()` / retention prune), and advances the
36
+ * revision on subscribe so a change between render and the subscribe
37
+ * effect is still picked up (the `useSyncExternalStore` post-subscribe
38
+ * re-read). Experimental (0.19.0) — surface may change in 0.19.x.
39
+ */
40
+ export declare function useLiveVersion<S extends SeriesSchema>(source: LiveSource<S>, options?: UseLiveVersionOptions): number;
41
+ //# sourceMappingURL=useLiveVersion.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useLiveVersion.d.ts","sourceRoot":"","sources":["../src/useLiveVersion.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AASxD,MAAM,WAAW,qBAAqB;IACpC;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,cAAc,CAAC,CAAC,SAAS,YAAY,EACnD,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC,EACrB,OAAO,CAAC,EAAE,qBAAqB,GAC9B,MAAM,CA4ER"}
@@ -0,0 +1,104 @@
1
+ import { useMemo, useSyncExternalStore } from 'react';
2
+ // The capability marker pond-ts stamps on evict-emitting sources
3
+ // (`LiveSeries`, `LiveView`). It's a registered symbol
4
+ // (`Symbol.for('pond-ts:emitsEvict')` in pond-ts), so reconstructing it
5
+ // here yields the identical symbol — no import needed. The
6
+ // `clear-evicts-without-event` test guards against key drift.
7
+ const EMITS_EVICT = Symbol.for('pond-ts:emitsEvict');
8
+ /**
9
+ * The React change signal for reading columns off a live source without
10
+ * manufacturing a `TimeSeries` snapshot (§A pull/read, experimental).
11
+ *
12
+ * `LiveSeries` / `LiveView` mutate in place, so a `useMemo([liveView])`
13
+ * keyed on the view never re-runs. This hook gives React a
14
+ * monotonically-increasing version that changes (at most once per
15
+ * `throttle`) whenever the source mutates — the missing invalidation
16
+ * trigger. Read columns straight off the live view, keyed on the
17
+ * returned version:
18
+ *
19
+ * ```tsx
20
+ * const view = useMemo(() => live.window('5m'), [live]);
21
+ * const v = useLiveVersion(view, { throttle: 200 });
22
+ * const series = useMemo(
23
+ * () => view.partitionBy('host').toMap((g) => ({
24
+ * ts: g.keyColumn().begin,
25
+ * cpu: g.column('cpu').toFloat64Array(),
26
+ * })),
27
+ * [view, v],
28
+ * );
29
+ * ```
30
+ *
31
+ * Tracks **both** append (`'event'`) and eviction (`'evict'`, on sources
32
+ * that emit it — e.g. `clear()` / retention prune), and advances the
33
+ * revision on subscribe so a change between render and the subscribe
34
+ * effect is still picked up (the `useSyncExternalStore` post-subscribe
35
+ * re-read). Experimental (0.19.0) — surface may change in 0.19.x.
36
+ */
37
+ export function useLiveVersion(source, options) {
38
+ const throttleMs = options?.throttle ?? 100;
39
+ const store = useMemo(() => {
40
+ let version = 0; // bumped on every observed source mutation
41
+ let committed = 0; // last version React has been notified about
42
+ let timer = null;
43
+ let unsubSource = null;
44
+ const listeners = new Set();
45
+ const flush = () => {
46
+ timer = null;
47
+ committed = version;
48
+ for (const l of listeners)
49
+ l();
50
+ };
51
+ const onChange = () => {
52
+ version += 1;
53
+ if (throttleMs <= 0) {
54
+ flush();
55
+ }
56
+ else if (timer === null) {
57
+ timer = setTimeout(flush, throttleMs);
58
+ }
59
+ };
60
+ return {
61
+ subscribe(cb) {
62
+ listeners.add(cb);
63
+ if (unsubSource === null) {
64
+ const unsubEvent = source.on('event', onChange);
65
+ // Also track eviction (clear / retention prune) on sources that
66
+ // emit it — otherwise a `clear()` with no following append leaves
67
+ // a column reader stale.
68
+ let unsubEvict;
69
+ if (EMITS_EVICT in source) {
70
+ unsubEvict = source.on('evict', onChange);
71
+ }
72
+ unsubSource = () => {
73
+ unsubEvent();
74
+ unsubEvict?.();
75
+ };
76
+ }
77
+ // Close the render-before-subscribe gap: a mutation between render
78
+ // and this effect fires no observed callback, so advance the
79
+ // revision now. useSyncExternalStore re-reads getSnapshot after
80
+ // subscribe; the bumped value forces one re-render that re-reads
81
+ // the (now-current) view.
82
+ version += 1;
83
+ committed = version;
84
+ return () => {
85
+ listeners.delete(cb);
86
+ if (listeners.size === 0) {
87
+ unsubSource?.();
88
+ unsubSource = null;
89
+ if (timer !== null) {
90
+ clearTimeout(timer);
91
+ timer = null;
92
+ }
93
+ }
94
+ };
95
+ },
96
+ // Stable between notifications — only advances at flush / subscribe,
97
+ // exactly when React is told. (Returning the live `version` would
98
+ // violate the getSnapshot contract.)
99
+ getSnapshot: () => committed,
100
+ };
101
+ }, [source, throttleMs]);
102
+ return useSyncExternalStore(store.subscribe, store.getSnapshot, store.getSnapshot);
103
+ }
104
+ //# sourceMappingURL=useLiveVersion.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useLiveVersion.js","sourceRoot":"","sources":["../src/useLiveVersion.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import { TimeSeries } from 'pond-ts';
2
- import type { SeriesSchema } from 'pond-ts';
2
+ import type { SeriesSchema, TimeSeriesJsonInput, TimeZoneOptions } from 'pond-ts';
3
3
  /**
4
4
  * Memoized `TimeSeries.fromJSON(...)` for static or fetched data.
5
5
  *
@@ -7,6 +7,19 @@ import type { SeriesSchema } from 'pond-ts';
7
7
  * serialized via `JSON.stringify` as the cache key — fine for small to
8
8
  * moderate payloads. For large datasets, pass an explicit `key` (e.g. a fetch
9
9
  * URL or ETag) to avoid the serialization cost.
10
+ *
11
+ * The schema generic `S` is inferred directly from `input.schema` (a plain
12
+ * structural position), so an `as const` schema narrows the returned
13
+ * `TimeSeries<S>` fully — `result.column('cpu')` resolves to `Float64Column`,
14
+ * `result.at(i)!.get('cpu')` to `number | undefined`, etc. An earlier
15
+ * two-generic `<S, I extends Parameters<...>[0]>` shape lost `S` through the
16
+ * input-wrapper generic and collapsed schema-narrowed accessors to `never`
17
+ * (the loose `.get(string)` path masked it); the column API surfaced it. The
18
+ * accepted input type is unchanged — `Parameters<fromJSON<S>>[0]` already
19
+ * resolved to `TimeSeriesJsonInput<S> & { parse? }` — so this is purely an
20
+ * inference fix, not a surface change.
10
21
  */
11
- export declare function useTimeSeries<S extends SeriesSchema, I extends Parameters<typeof TimeSeries.fromJSON<S>>[0]>(input: I, key?: string): TimeSeries<S>;
22
+ export declare function useTimeSeries<S extends SeriesSchema>(input: TimeSeriesJsonInput<S> & {
23
+ parse?: TimeZoneOptions;
24
+ }, key?: string): TimeSeries<S>;
12
25
  //# sourceMappingURL=useTimeSeries.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"useTimeSeries.d.ts","sourceRoot":"","sources":["../src/useTimeSeries.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAE5C;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAC3B,CAAC,SAAS,YAAY,EACtB,CAAC,SAAS,UAAU,CAAC,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EACtD,KAAK,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,UAAU,CAAC,CAAC,CAAC,CAKvC"}
1
+ {"version":3,"file":"useTimeSeries.d.ts","sourceRoot":"","sources":["../src/useTimeSeries.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,KAAK,EACV,YAAY,EACZ,mBAAmB,EACnB,eAAe,EAChB,MAAM,SAAS,CAAC;AAEjB;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,aAAa,CAAC,CAAC,SAAS,YAAY,EAClD,KAAK,EAAE,mBAAmB,CAAC,CAAC,CAAC,GAAG;IAAE,KAAK,CAAC,EAAE,eAAe,CAAA;CAAE,EAC3D,GAAG,CAAC,EAAE,MAAM,GACX,UAAU,CAAC,CAAC,CAAC,CAKf"}
@@ -7,6 +7,17 @@ import { TimeSeries } from 'pond-ts';
7
7
  * serialized via `JSON.stringify` as the cache key — fine for small to
8
8
  * moderate payloads. For large datasets, pass an explicit `key` (e.g. a fetch
9
9
  * URL or ETag) to avoid the serialization cost.
10
+ *
11
+ * The schema generic `S` is inferred directly from `input.schema` (a plain
12
+ * structural position), so an `as const` schema narrows the returned
13
+ * `TimeSeries<S>` fully — `result.column('cpu')` resolves to `Float64Column`,
14
+ * `result.at(i)!.get('cpu')` to `number | undefined`, etc. An earlier
15
+ * two-generic `<S, I extends Parameters<...>[0]>` shape lost `S` through the
16
+ * input-wrapper generic and collapsed schema-narrowed accessors to `never`
17
+ * (the loose `.get(string)` path masked it); the column API surfaced it. The
18
+ * accepted input type is unchanged — `Parameters<fromJSON<S>>[0]` already
19
+ * resolved to `TimeSeriesJsonInput<S> & { parse? }` — so this is purely an
20
+ * inference fix, not a surface change.
10
21
  */
11
22
  export function useTimeSeries(input, key) {
12
23
  // eslint-disable-next-line react-hooks/exhaustive-deps
@@ -1 +1 @@
1
- {"version":3,"file":"useTimeSeries.js","sourceRoot":"","sources":["../src/useTimeSeries.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAChC,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAGrC;;;;;;;GAOG;AACH,MAAM,UAAU,aAAa,CAG3B,KAAQ,EAAE,GAAY;IACtB,uDAAuD;IACvD,MAAM,QAAQ,GAAG,GAAG,IAAI,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IAC9C,uDAAuD;IACvD,OAAO,OAAO,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAI,KAAK,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC;AAClE,CAAC"}
1
+ {"version":3,"file":"useTimeSeries.js","sourceRoot":"","sources":["../src/useTimeSeries.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAChC,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAOrC;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,UAAU,aAAa,CAC3B,KAA2D,EAC3D,GAAY;IAEZ,uDAAuD;IACvD,MAAM,QAAQ,GAAG,GAAG,IAAI,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IAC9C,uDAAuD;IACvD,OAAO,OAAO,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAI,KAAK,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC;AAClE,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pond-ts/react",
3
- "version": "0.18.0",
3
+ "version": "0.20.0",
4
4
  "description": "React hooks for pond-ts live time series",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -27,11 +27,12 @@
27
27
  "scripts": {
28
28
  "build": "tsc -p tsconfig.json",
29
29
  "prepack": "cp ../../README.md ./README.md && cp ../../LICENSE ./LICENSE && cp ../../CHANGELOG.md ./CHANGELOG.md && npm run build",
30
- "test": "vitest run",
30
+ "test": "npm run test:type && npm run test:runtime",
31
+ "test:type": "tsc -p tsconfig.types.json",
31
32
  "test:runtime": "vitest run"
32
33
  },
33
34
  "peerDependencies": {
34
- "pond-ts": "^0.18.0",
35
+ "pond-ts": "^0.20.0",
35
36
  "react": "^18.0.0 || ^19.0.0"
36
37
  },
37
38
  "devDependencies": {