@livestore/livestore 0.0.46-dev.4 → 0.0.47-dev.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/README.md +10 -0
- package/dist/.tsbuildinfo +1 -1
- package/dist/__tests__/react/fixture.d.ts +28 -12
- package/dist/__tests__/react/fixture.d.ts.map +1 -1
- package/dist/__tests__/react/fixture.js +27 -3
- package/dist/__tests__/react/fixture.js.map +1 -1
- package/dist/__tests__/react/utils/otel.d.ts +10 -0
- package/dist/__tests__/react/utils/otel.d.ts.map +1 -0
- package/dist/__tests__/react/utils/otel.js +42 -0
- package/dist/__tests__/react/utils/otel.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/react/LiveStoreProvider.js +39 -6
- package/dist/react/LiveStoreProvider.js.map +1 -1
- package/dist/react/LiveStoreProvider.test.d.ts +2 -0
- package/dist/react/LiveStoreProvider.test.d.ts.map +1 -0
- package/dist/react/LiveStoreProvider.test.js +40 -0
- package/dist/react/LiveStoreProvider.test.js.map +1 -0
- package/dist/react/components/LiveList.d.ts +21 -0
- package/dist/react/components/LiveList.d.ts.map +1 -0
- package/dist/react/components/LiveList.js +31 -0
- package/dist/react/components/LiveList.js.map +1 -0
- package/dist/react/index.d.ts +1 -1
- package/dist/react/index.d.ts.map +1 -1
- package/dist/react/index.js +1 -1
- package/dist/react/index.js.map +1 -1
- package/dist/react/useAtom.d.ts +1 -1
- package/dist/react/useAtom.d.ts.map +1 -1
- package/dist/react/useAtom.js +6 -1
- package/dist/react/useAtom.js.map +1 -1
- package/dist/react/useQuery.d.ts +4 -1
- package/dist/react/useQuery.d.ts.map +1 -1
- package/dist/react/useQuery.js +24 -19
- package/dist/react/useQuery.js.map +1 -1
- package/dist/react/useQuery.test.js +11 -11
- package/dist/react/useQuery.test.js.map +1 -1
- package/dist/react/useRow.d.ts.map +1 -1
- package/dist/react/useRow.js +14 -69
- package/dist/react/useRow.js.map +1 -1
- package/dist/react/useRow.test.js +440 -28
- package/dist/react/useRow.test.js.map +1 -1
- package/dist/react/useTemporaryQuery.d.ts +15 -3
- package/dist/react/useTemporaryQuery.d.ts.map +1 -1
- package/dist/react/useTemporaryQuery.js +60 -27
- package/dist/react/useTemporaryQuery.js.map +1 -1
- package/dist/react/useTemporaryQuery.test.js +10 -9
- package/dist/react/useTemporaryQuery.test.js.map +1 -1
- package/dist/reactive.d.ts +23 -5
- package/dist/reactive.d.ts.map +1 -1
- package/dist/reactive.js +44 -11
- package/dist/reactive.js.map +1 -1
- package/dist/reactive.test.js +1 -1
- package/dist/reactive.test.js.map +1 -1
- package/dist/reactiveQueries/base-class.d.ts +1 -1
- package/dist/reactiveQueries/base-class.d.ts.map +1 -1
- package/dist/reactiveQueries/base-class.js.map +1 -1
- package/dist/reactiveQueries/graphql.d.ts +2 -2
- package/dist/reactiveQueries/graphql.d.ts.map +1 -1
- package/dist/reactiveQueries/graphql.js +21 -11
- package/dist/reactiveQueries/graphql.js.map +1 -1
- package/dist/reactiveQueries/sql.d.ts +1 -1
- package/dist/reactiveQueries/sql.d.ts.map +1 -1
- package/dist/reactiveQueries/sql.js +15 -11
- package/dist/reactiveQueries/sql.js.map +1 -1
- package/dist/reactiveQueries/sql.test.js +1 -40
- package/dist/reactiveQueries/sql.test.js.map +1 -1
- package/dist/row-query.d.ts.map +1 -1
- package/dist/row-query.js +3 -1
- package/dist/row-query.js.map +1 -1
- package/dist/store.d.ts +7 -5
- package/dist/store.d.ts.map +1 -1
- package/dist/store.js +50 -38
- package/dist/store.js.map +1 -1
- package/package.json +11 -13
- package/src/__tests__/react/fixture.tsx +35 -2
- package/src/__tests__/react/utils/otel.ts +61 -0
- package/src/index.ts +12 -1
- package/src/react/LiveStoreProvider.test.tsx +63 -0
- package/src/react/LiveStoreProvider.tsx +42 -7
- package/src/react/components/LiveList.tsx +84 -0
- package/src/react/index.ts +1 -1
- package/src/react/useAtom.ts +6 -2
- package/src/react/useQuery.test.tsx +11 -11
- package/src/react/useQuery.ts +29 -22
- package/src/react/useRow.test.tsx +502 -30
- package/src/react/useRow.ts +19 -107
- package/src/react/useTemporaryQuery.test.tsx +17 -16
- package/src/react/useTemporaryQuery.ts +96 -28
- package/src/reactive.test.ts +1 -1
- package/src/reactive.ts +76 -15
- package/src/reactiveQueries/base-class.ts +2 -1
- package/src/reactiveQueries/graphql.ts +26 -16
- package/src/reactiveQueries/sql.test.ts +1 -54
- package/src/reactiveQueries/sql.ts +20 -14
- package/src/row-query.ts +3 -1
- package/src/store.ts +71 -49
- package/tsconfig.json +0 -1
- package/dist/react/components/DiffableList.d.ts +0 -20
- package/dist/react/components/DiffableList.d.ts.map +0 -1
- package/dist/react/components/DiffableList.js +0 -113
- package/dist/react/components/DiffableList.js.map +0 -1
- package/dist/react/utils/useCleanup.d.ts +0 -7
- package/dist/react/utils/useCleanup.d.ts.map +0 -1
- package/dist/react/utils/useCleanup.js +0 -19
- package/dist/react/utils/useCleanup.js.map +0 -1
- package/src/react/components/DiffableList.tsx +0 -192
- package/src/react/utils/useCleanup.ts +0 -25
|
@@ -1,192 +0,0 @@
|
|
|
1
|
-
import { FI } from '@livestore/fractional-index'
|
|
2
|
-
import { casesHandled } from '@livestore/utils'
|
|
3
|
-
import * as itsFine from 'its-fine'
|
|
4
|
-
import React from 'react'
|
|
5
|
-
import ReactDOM from 'react-dom/client'
|
|
6
|
-
|
|
7
|
-
import type { LiveQuery } from '../../reactiveQueries/base-class.js'
|
|
8
|
-
import { computed } from '../../reactiveQueries/js.js'
|
|
9
|
-
import { useQuery } from '../useQuery.js'
|
|
10
|
-
|
|
11
|
-
export type Props<TItem> = {
|
|
12
|
-
items$: LiveQuery<ReadonlyArray<TItem>>
|
|
13
|
-
/**
|
|
14
|
-
* @example
|
|
15
|
-
* ```tsx
|
|
16
|
-
* renderContainer={(children) => <ul>{children}</ul>}
|
|
17
|
-
* ```
|
|
18
|
-
*/
|
|
19
|
-
renderContainer: (ref: React.LegacyRef<any>) => React.ReactNode
|
|
20
|
-
// TODO refactor render-flag to allow for transition animations on add/remove
|
|
21
|
-
renderItem: (item: TItem, opts: { index: number; isInitialListRender: boolean }) => React.ReactNode
|
|
22
|
-
getKey: (item: TItem, index: number) => string | number
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export const DiffableList_ = <TItem,>({
|
|
26
|
-
items$,
|
|
27
|
-
renderContainer,
|
|
28
|
-
renderItem,
|
|
29
|
-
getKey,
|
|
30
|
-
}: Props<TItem>): React.ReactNode => {
|
|
31
|
-
const ref = React.useRef<HTMLElement>(null)
|
|
32
|
-
const container = renderContainer(ref)
|
|
33
|
-
|
|
34
|
-
const [hasMounted, setHasMounted] = React.useState(false)
|
|
35
|
-
|
|
36
|
-
React.useEffect(() => setHasMounted(true), [])
|
|
37
|
-
|
|
38
|
-
const keys$ = computed((get) => get(items$).map(getKey))
|
|
39
|
-
type RefEl = {
|
|
40
|
-
id: string | number
|
|
41
|
-
el: HTMLElement
|
|
42
|
-
item$: LiveQuery<TItem>
|
|
43
|
-
root: ReactDOM.Root
|
|
44
|
-
}
|
|
45
|
-
const elsRef = React.useRef<RefEl[]>([])
|
|
46
|
-
|
|
47
|
-
const ContextBridge = itsFine.useContextBridge()
|
|
48
|
-
|
|
49
|
-
const renderListEl = React.useCallback(
|
|
50
|
-
(parentEl: HTMLElement, index: number, item$: LiveQuery<TItem>) => {
|
|
51
|
-
const root = ReactDOM.createRoot(parentEl)
|
|
52
|
-
root.render(
|
|
53
|
-
<ContextBridge>
|
|
54
|
-
<ItemWrapper item$={item$} renderItem={renderItem} opts={{ index, isInitialListRender: !hasMounted }} />
|
|
55
|
-
</ContextBridge>,
|
|
56
|
-
)
|
|
57
|
-
|
|
58
|
-
return root
|
|
59
|
-
},
|
|
60
|
-
[ContextBridge, hasMounted, renderItem],
|
|
61
|
-
)
|
|
62
|
-
|
|
63
|
-
React.useLayoutEffect(() => {
|
|
64
|
-
if (ref.current === null) {
|
|
65
|
-
throw new Error('ref.current is null')
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
const keys = keys$.run()
|
|
69
|
-
|
|
70
|
-
for (let index = 0; index < keys.length; index++) {
|
|
71
|
-
const parentEl = document.createElement('div')
|
|
72
|
-
ref.current!.append(parentEl)
|
|
73
|
-
const item$ = computed((get) => get(items$)[index]!) as LiveQuery<TItem>
|
|
74
|
-
const root = renderListEl(parentEl, index, item$)
|
|
75
|
-
elsRef.current.push({ el: parentEl, item$, root, id: keys[index]! })
|
|
76
|
-
}
|
|
77
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
78
|
-
}, [])
|
|
79
|
-
|
|
80
|
-
React.useEffect(() => () => keys$.destroy(), [keys$])
|
|
81
|
-
|
|
82
|
-
React.useEffect(() => {
|
|
83
|
-
// const keys = keys$.run()
|
|
84
|
-
|
|
85
|
-
return keys$.subscribe((keys) => {
|
|
86
|
-
const prevKeys = elsRef.current.map((el) => el.id)
|
|
87
|
-
|
|
88
|
-
let arrayIsEqual = true
|
|
89
|
-
for (let i = 0; i < keys.length; i++) {
|
|
90
|
-
if (keys[i] !== prevKeys[i]) {
|
|
91
|
-
arrayIsEqual = false
|
|
92
|
-
break
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
if (arrayIsEqual) return
|
|
96
|
-
|
|
97
|
-
const previousAgg = FI.aggregateMake(prevKeys, FI.fractionalIndexImplNumber)
|
|
98
|
-
const { newEvents } = FI.getNewEvents(previousAgg, keys, FI.fractionalIndexImplNumber)
|
|
99
|
-
|
|
100
|
-
console.log('newEvents', newEvents)
|
|
101
|
-
|
|
102
|
-
for (const event of newEvents) {
|
|
103
|
-
switch (event.op) {
|
|
104
|
-
case 'remove': {
|
|
105
|
-
const { index } = event
|
|
106
|
-
const el = elsRef.current[index]!
|
|
107
|
-
el.root.unmount()
|
|
108
|
-
el.el.remove()
|
|
109
|
-
el.item$.destroy()
|
|
110
|
-
elsRef.current.splice(index, 1)
|
|
111
|
-
break
|
|
112
|
-
}
|
|
113
|
-
case 'add': {
|
|
114
|
-
const { index } = event
|
|
115
|
-
const parentEl = document.createElement('div')
|
|
116
|
-
ref.current!.append(parentEl)
|
|
117
|
-
const item$ = computed((get) => get(items$)[index]!) as LiveQuery<TItem>
|
|
118
|
-
const root = renderListEl(parentEl, index, item$)
|
|
119
|
-
elsRef.current.splice(index, 0, { el: parentEl, item$, root, id: keys[index]! })
|
|
120
|
-
break
|
|
121
|
-
}
|
|
122
|
-
case 'move': {
|
|
123
|
-
// const { newIndex, previousIndex } = event
|
|
124
|
-
|
|
125
|
-
// const el = elsRef.current[previousIndex]!
|
|
126
|
-
// const item$ = el.item$
|
|
127
|
-
// const root = el.root
|
|
128
|
-
// const elEl = el.el
|
|
129
|
-
|
|
130
|
-
// elsRef.current.splice(previousIndex, 1)
|
|
131
|
-
// elsRef.current.splice(newIndex, 0, { el: elEl, item$, root })
|
|
132
|
-
|
|
133
|
-
// ref.current!.insertBefore(elEl, elsRef.current[newIndex + 1]?.el)
|
|
134
|
-
|
|
135
|
-
// // move dom element
|
|
136
|
-
|
|
137
|
-
break
|
|
138
|
-
}
|
|
139
|
-
default: {
|
|
140
|
-
casesHandled(event)
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
})
|
|
145
|
-
|
|
146
|
-
// for (let index = 0; index < keys.length; index++) {
|
|
147
|
-
// if (prevKeys[index] === keys[index]) continue
|
|
148
|
-
|
|
149
|
-
// // check if `keys[index]` === `prevKeys[index + 1]`
|
|
150
|
-
// // which probably means that
|
|
151
|
-
// if (keys[index] === prevKeys[index + 1]) {
|
|
152
|
-
// // sp
|
|
153
|
-
// }
|
|
154
|
-
|
|
155
|
-
// prevKeys[index] = keys[index] as any
|
|
156
|
-
// }
|
|
157
|
-
|
|
158
|
-
// TODO in the future use a more efficient diffing algorithm that re-uses elements more optimally
|
|
159
|
-
// right now we're only looking one step ahead
|
|
160
|
-
|
|
161
|
-
// reconcile until `keys` and `prevKeys` are equal
|
|
162
|
-
|
|
163
|
-
// prevKeys = keys
|
|
164
|
-
}, [items$, keys$, renderListEl])
|
|
165
|
-
|
|
166
|
-
return <>{container}</>
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
export const DiffableList = <TItem,>({
|
|
170
|
-
items$,
|
|
171
|
-
renderContainer,
|
|
172
|
-
renderItem,
|
|
173
|
-
getKey,
|
|
174
|
-
}: Props<TItem>): React.ReactNode => (
|
|
175
|
-
<itsFine.FiberProvider>
|
|
176
|
-
<DiffableList_ items$={items$} renderContainer={renderContainer} renderItem={renderItem} getKey={getKey} />
|
|
177
|
-
</itsFine.FiberProvider>
|
|
178
|
-
)
|
|
179
|
-
|
|
180
|
-
const ItemWrapper = <TItem,>({
|
|
181
|
-
item$,
|
|
182
|
-
opts,
|
|
183
|
-
renderItem,
|
|
184
|
-
}: {
|
|
185
|
-
item$: LiveQuery<TItem>
|
|
186
|
-
opts: { index: number; isInitialListRender: boolean }
|
|
187
|
-
renderItem: (item: TItem, opts: { index: number; isInitialListRender: boolean }) => React.ReactNode
|
|
188
|
-
}) => {
|
|
189
|
-
const item = useQuery(item$)
|
|
190
|
-
|
|
191
|
-
return <>{renderItem(item, opts)}</>
|
|
192
|
-
}
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import React from 'react'
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Like cleanup callback of `React.useEffect` but running as part of the render loop.
|
|
5
|
-
*
|
|
6
|
-
* NOTE: This hook should not be used with React strict mode.
|
|
7
|
-
*/
|
|
8
|
-
export const useCleanup = (
|
|
9
|
-
/** Needs to be a `React.useCallback` value */
|
|
10
|
-
cleanupCallback: () => void,
|
|
11
|
-
) => {
|
|
12
|
-
const callbackRef = React.useRef(cleanupCallback)
|
|
13
|
-
|
|
14
|
-
if (callbackRef.current !== cleanupCallback) {
|
|
15
|
-
callbackRef.current()
|
|
16
|
-
callbackRef.current = cleanupCallback
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
React.useEffect(
|
|
20
|
-
() => () => {
|
|
21
|
-
callbackRef.current()
|
|
22
|
-
},
|
|
23
|
-
[],
|
|
24
|
-
)
|
|
25
|
-
}
|