Skip to content

Commit bb629bf

Browse files
committed
feat: use lit-store internally instead of reyling on vanilla store dependency
1 parent 2e5d3fe commit bb629bf

4 files changed

Lines changed: 91 additions & 12 deletions

File tree

packages/lit-table/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@
5757
"build": "tsdown"
5858
},
5959
"dependencies": {
60-
"@tanstack/store": "^0.11.0",
60+
"@tanstack/lit-store": "^0.13.2",
6161
"@tanstack/table-core": "workspace:*"
6262
},
6363
"devDependencies": {

packages/lit-table/src/TableController.ts

Lines changed: 76 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
11
import { constructTable } from '@tanstack/table-core'
2+
import { TanStackStoreSelector } from '@tanstack/lit-store'
23
import { litReactivity } from './reactivity'
34
import { FlexRender } from './flexRender'
4-
import type { Atom, ReadonlyAtom, ReadonlyStore, Store } from '@tanstack/store'
5+
import type {
6+
Atom,
7+
ReadonlyAtom,
8+
ReadonlyStore,
9+
Store,
10+
} from '@tanstack/lit-store'
511
import type {
612
NoInfer,
713
RowData,
@@ -146,6 +152,13 @@ export class TableController<
146152
private _storeSubscription?: { unsubscribe: () => void }
147153
private _optionsSubscription?: { unsubscribe: () => void }
148154
private _notifier = 0
155+
private _selectorCache = new WeakMap<
156+
SubscribeSource<unknown>,
157+
Map<
158+
((state: unknown) => unknown) | undefined,
159+
TanStackStoreSelector<unknown>
160+
>
161+
>()
149162

150163
constructor(host: ReactiveControllerHost) {
151164
;(this.host = host).addController(this)
@@ -205,23 +218,28 @@ export class TableController<
205218
const tableInstance = this._table
206219

207220
// Attach Subscribe function
208-
const Subscribe = function Subscribe(props: {
221+
const Subscribe = ((props: {
209222
source?: SubscribeSource<unknown>
210223
selector?: (state: unknown) => unknown
211224
children:
212225
| ((state: Readonly<unknown>) => TemplateResult | string)
213226
| TemplateResult
214227
| string
215-
}): TemplateResult | string {
228+
}): TemplateResult | string => {
216229
const source = props.source ?? tableInstance.store
217-
const value = source.get()
218-
const selectedState =
219-
props.selector !== undefined ? props.selector(value) : value
230+
231+
const storeSelector: TanStackStoreSelector<unknown> =
232+
this._getOrCreateSelector(source, props.selector)
233+
234+
// TODO: update to newest version of Tanstack Store: https://github.com/TanStack/store/pull/329
235+
const selectedState = storeSelector.value
236+
220237
if (typeof props.children === 'function') {
221238
return props.children(selectedState as Readonly<unknown>)
222239
}
240+
223241
return props.children
224-
} as LitTable<TFeatures, TData, TSelected>['Subscribe']
242+
}) as LitTable<TFeatures, TData, TSelected>['Subscribe']
225243

226244
return {
227245
...this._table,
@@ -257,5 +275,56 @@ export class TableController<
257275
this._storeSubscription = undefined
258276
this._optionsSubscription?.unsubscribe()
259277
this._optionsSubscription = undefined
278+
this._selectorCache = new WeakMap()
279+
}
280+
281+
/**
282+
* Get or create a TanStackStoreSelector for the given source and selector.
283+
*
284+
* Caches selectors by source (WeakMap) and selector function to avoid
285+
* creating new controllers on every render cycle.
286+
*
287+
* @param source The atom or store to subscribe to
288+
* @param selector Optional selector function to select a slice of the source state
289+
* @returns A cached TanStackStoreSelector instance that subscribes to the source and applies the selector
290+
*/
291+
private _getOrCreateSelector = (
292+
source?: SubscribeSource<unknown>,
293+
selector?: (state: unknown) => unknown,
294+
): TanStackStoreSelector<unknown> => {
295+
if (!source) {
296+
return new TanStackStoreSelector(this.host, () => source, selector)
297+
}
298+
299+
if (!this._selectorCache.has(source)) {
300+
this._selectorCache.set(source, new Map())
301+
}
302+
const selectorMap = this._selectorCache.get(source)
303+
304+
// Get or create the selector for this source + selector combination
305+
if (selectorMap?.has(selector)) {
306+
return (
307+
selectorMap.get(selector) ??
308+
this.createSelectorForSource(source, selector)
309+
)
310+
}
311+
312+
const storeSelector = this.createSelectorForSource(source, selector)
313+
selectorMap?.set(selector, storeSelector)
314+
315+
return storeSelector
316+
}
317+
318+
/**
319+
* Create a new TanStackStoreSelector for the given source and selector without caching.
320+
* @param source The atom or store to subscribe to
321+
* @param selector Optional selector function to select a slice of the source state
322+
* @returns A new TanStackStoreSelector instance that subscribes to the source and applies the selector
323+
*/
324+
private createSelectorForSource = (
325+
source: SubscribeSource<unknown>,
326+
selector?: (state: unknown) => unknown,
327+
): TanStackStoreSelector<unknown> => {
328+
return new TanStackStoreSelector(this.host, () => source, selector)
260329
}
261330
}

packages/lit-table/src/reactivity.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { batch, createAtom } from '@tanstack/store'
1+
import { batch, createAtom } from '@tanstack/lit-store'
22
import type {
33
TableAtomOptions,
44
TableReactivityBindings,

pnpm-lock.yaml

Lines changed: 13 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)