@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.
Files changed (108) hide show
  1. package/README.md +10 -0
  2. package/dist/.tsbuildinfo +1 -1
  3. package/dist/__tests__/react/fixture.d.ts +28 -12
  4. package/dist/__tests__/react/fixture.d.ts.map +1 -1
  5. package/dist/__tests__/react/fixture.js +27 -3
  6. package/dist/__tests__/react/fixture.js.map +1 -1
  7. package/dist/__tests__/react/utils/otel.d.ts +10 -0
  8. package/dist/__tests__/react/utils/otel.d.ts.map +1 -0
  9. package/dist/__tests__/react/utils/otel.js +42 -0
  10. package/dist/__tests__/react/utils/otel.js.map +1 -0
  11. package/dist/index.d.ts +1 -1
  12. package/dist/index.d.ts.map +1 -1
  13. package/dist/index.js.map +1 -1
  14. package/dist/react/LiveStoreProvider.js +39 -6
  15. package/dist/react/LiveStoreProvider.js.map +1 -1
  16. package/dist/react/LiveStoreProvider.test.d.ts +2 -0
  17. package/dist/react/LiveStoreProvider.test.d.ts.map +1 -0
  18. package/dist/react/LiveStoreProvider.test.js +40 -0
  19. package/dist/react/LiveStoreProvider.test.js.map +1 -0
  20. package/dist/react/components/LiveList.d.ts +21 -0
  21. package/dist/react/components/LiveList.d.ts.map +1 -0
  22. package/dist/react/components/LiveList.js +31 -0
  23. package/dist/react/components/LiveList.js.map +1 -0
  24. package/dist/react/index.d.ts +1 -1
  25. package/dist/react/index.d.ts.map +1 -1
  26. package/dist/react/index.js +1 -1
  27. package/dist/react/index.js.map +1 -1
  28. package/dist/react/useAtom.d.ts +1 -1
  29. package/dist/react/useAtom.d.ts.map +1 -1
  30. package/dist/react/useAtom.js +6 -1
  31. package/dist/react/useAtom.js.map +1 -1
  32. package/dist/react/useQuery.d.ts +4 -1
  33. package/dist/react/useQuery.d.ts.map +1 -1
  34. package/dist/react/useQuery.js +24 -19
  35. package/dist/react/useQuery.js.map +1 -1
  36. package/dist/react/useQuery.test.js +11 -11
  37. package/dist/react/useQuery.test.js.map +1 -1
  38. package/dist/react/useRow.d.ts.map +1 -1
  39. package/dist/react/useRow.js +14 -69
  40. package/dist/react/useRow.js.map +1 -1
  41. package/dist/react/useRow.test.js +440 -28
  42. package/dist/react/useRow.test.js.map +1 -1
  43. package/dist/react/useTemporaryQuery.d.ts +15 -3
  44. package/dist/react/useTemporaryQuery.d.ts.map +1 -1
  45. package/dist/react/useTemporaryQuery.js +60 -27
  46. package/dist/react/useTemporaryQuery.js.map +1 -1
  47. package/dist/react/useTemporaryQuery.test.js +10 -9
  48. package/dist/react/useTemporaryQuery.test.js.map +1 -1
  49. package/dist/reactive.d.ts +23 -5
  50. package/dist/reactive.d.ts.map +1 -1
  51. package/dist/reactive.js +44 -11
  52. package/dist/reactive.js.map +1 -1
  53. package/dist/reactive.test.js +1 -1
  54. package/dist/reactive.test.js.map +1 -1
  55. package/dist/reactiveQueries/base-class.d.ts +1 -1
  56. package/dist/reactiveQueries/base-class.d.ts.map +1 -1
  57. package/dist/reactiveQueries/base-class.js.map +1 -1
  58. package/dist/reactiveQueries/graphql.d.ts +2 -2
  59. package/dist/reactiveQueries/graphql.d.ts.map +1 -1
  60. package/dist/reactiveQueries/graphql.js +21 -11
  61. package/dist/reactiveQueries/graphql.js.map +1 -1
  62. package/dist/reactiveQueries/sql.d.ts +1 -1
  63. package/dist/reactiveQueries/sql.d.ts.map +1 -1
  64. package/dist/reactiveQueries/sql.js +15 -11
  65. package/dist/reactiveQueries/sql.js.map +1 -1
  66. package/dist/reactiveQueries/sql.test.js +1 -40
  67. package/dist/reactiveQueries/sql.test.js.map +1 -1
  68. package/dist/row-query.d.ts.map +1 -1
  69. package/dist/row-query.js +3 -1
  70. package/dist/row-query.js.map +1 -1
  71. package/dist/store.d.ts +7 -5
  72. package/dist/store.d.ts.map +1 -1
  73. package/dist/store.js +50 -38
  74. package/dist/store.js.map +1 -1
  75. package/package.json +11 -13
  76. package/src/__tests__/react/fixture.tsx +35 -2
  77. package/src/__tests__/react/utils/otel.ts +61 -0
  78. package/src/index.ts +12 -1
  79. package/src/react/LiveStoreProvider.test.tsx +63 -0
  80. package/src/react/LiveStoreProvider.tsx +42 -7
  81. package/src/react/components/LiveList.tsx +84 -0
  82. package/src/react/index.ts +1 -1
  83. package/src/react/useAtom.ts +6 -2
  84. package/src/react/useQuery.test.tsx +11 -11
  85. package/src/react/useQuery.ts +29 -22
  86. package/src/react/useRow.test.tsx +502 -30
  87. package/src/react/useRow.ts +19 -107
  88. package/src/react/useTemporaryQuery.test.tsx +17 -16
  89. package/src/react/useTemporaryQuery.ts +96 -28
  90. package/src/reactive.test.ts +1 -1
  91. package/src/reactive.ts +76 -15
  92. package/src/reactiveQueries/base-class.ts +2 -1
  93. package/src/reactiveQueries/graphql.ts +26 -16
  94. package/src/reactiveQueries/sql.test.ts +1 -54
  95. package/src/reactiveQueries/sql.ts +20 -14
  96. package/src/row-query.ts +3 -1
  97. package/src/store.ts +71 -49
  98. package/tsconfig.json +0 -1
  99. package/dist/react/components/DiffableList.d.ts +0 -20
  100. package/dist/react/components/DiffableList.d.ts.map +0 -1
  101. package/dist/react/components/DiffableList.js +0 -113
  102. package/dist/react/components/DiffableList.js.map +0 -1
  103. package/dist/react/utils/useCleanup.d.ts +0 -7
  104. package/dist/react/utils/useCleanup.d.ts.map +0 -1
  105. package/dist/react/utils/useCleanup.js +0 -19
  106. package/dist/react/utils/useCleanup.js.map +0 -1
  107. package/src/react/components/DiffableList.tsx +0 -192
  108. 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
- }