atom.io 0.6.1 → 0.6.3

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 (90) hide show
  1. package/dist/index.d.mts +3 -3
  2. package/dist/index.d.ts +3 -3
  3. package/dist/index.js +7 -2
  4. package/dist/index.js.map +1 -1
  5. package/dist/index.mjs +7 -2
  6. package/dist/index.mjs.map +1 -1
  7. package/json/dist/index.js.map +1 -1
  8. package/json/dist/index.mjs.map +1 -1
  9. package/package.json +13 -3
  10. package/react/dist/index.js.map +1 -1
  11. package/react/dist/index.mjs.map +1 -1
  12. package/react-devtools/dist/index.js +32 -18
  13. package/react-devtools/dist/index.js.map +1 -1
  14. package/react-devtools/dist/index.mjs +32 -18
  15. package/react-devtools/dist/index.mjs.map +1 -1
  16. package/realtime/dist/index.js.map +1 -1
  17. package/realtime/dist/index.mjs.map +1 -1
  18. package/realtime-react/dist/index.js.map +1 -1
  19. package/realtime-react/dist/index.mjs.map +1 -1
  20. package/realtime-testing/dist/index.d.mts +49 -0
  21. package/realtime-testing/dist/index.d.ts +49 -0
  22. package/realtime-testing/dist/index.js +153 -0
  23. package/realtime-testing/dist/index.js.map +1 -0
  24. package/realtime-testing/dist/index.mjs +117 -0
  25. package/realtime-testing/dist/index.mjs.map +1 -0
  26. package/realtime-testing/package.json +15 -0
  27. package/src/atom.ts +15 -15
  28. package/src/index.ts +59 -59
  29. package/src/internal/atom-internal.ts +36 -36
  30. package/src/internal/families-internal.ts +114 -114
  31. package/src/internal/get.ts +83 -83
  32. package/src/internal/is-default.ts +17 -17
  33. package/src/internal/meta/attach-meta.ts +7 -7
  34. package/src/internal/meta/meta-state.ts +115 -115
  35. package/src/internal/operation.ts +93 -93
  36. package/src/internal/selector/create-read-write-selector.ts +46 -46
  37. package/src/internal/selector/create-readonly-selector.ts +37 -37
  38. package/src/internal/selector/lookup-selector-sources.ts +9 -9
  39. package/src/internal/selector/register-selector.ts +44 -44
  40. package/src/internal/selector/trace-selector-atoms.ts +30 -30
  41. package/src/internal/selector/update-selector-atoms.ts +25 -25
  42. package/src/internal/selector-internal.ts +37 -37
  43. package/src/internal/set.ts +78 -78
  44. package/src/internal/store.ts +118 -118
  45. package/src/internal/subscribe-internal.ts +62 -62
  46. package/src/internal/time-travel-internal.ts +76 -76
  47. package/src/internal/timeline/add-atom-to-timeline.ts +158 -153
  48. package/src/internal/timeline-internal.ts +80 -80
  49. package/src/internal/transaction/abort-transaction.ts +8 -8
  50. package/src/internal/transaction/apply-transaction.ts +41 -41
  51. package/src/internal/transaction/build-transaction.ts +28 -28
  52. package/src/internal/transaction/index.ts +7 -7
  53. package/src/internal/transaction/redo-transaction.ts +13 -13
  54. package/src/internal/transaction/undo-transaction.ts +13 -13
  55. package/src/internal/transaction-internal.ts +48 -48
  56. package/src/json/select-json.ts +12 -12
  57. package/src/logger.ts +30 -30
  58. package/src/react/store-context.tsx +4 -4
  59. package/src/react/store-hooks.ts +18 -18
  60. package/src/react-devtools/AtomIODevtools.tsx +83 -82
  61. package/src/react-devtools/StateEditor.tsx +53 -53
  62. package/src/react-devtools/TokenList.tsx +47 -42
  63. package/src/react-explorer/AtomIOExplorer.tsx +197 -185
  64. package/src/react-explorer/explorer-effects.ts +11 -11
  65. package/src/react-explorer/explorer-states.ts +186 -193
  66. package/src/react-explorer/index.ts +11 -11
  67. package/src/react-explorer/space-states.ts +48 -50
  68. package/src/react-explorer/view-states.ts +25 -25
  69. package/src/realtime/hook-composition/expose-family.ts +81 -81
  70. package/src/realtime/hook-composition/expose-single.ts +26 -26
  71. package/src/realtime/hook-composition/expose-timeline.ts +60 -0
  72. package/src/realtime/hook-composition/index.ts +2 -2
  73. package/src/realtime/hook-composition/receive-state.ts +18 -18
  74. package/src/realtime/hook-composition/receive-transaction.ts +8 -8
  75. package/src/realtime-react/realtime-context.tsx +17 -17
  76. package/src/realtime-react/realtime-hooks.ts +17 -17
  77. package/src/realtime-react/realtime-state.ts +4 -4
  78. package/src/realtime-react/use-pull-family-member.ts +15 -15
  79. package/src/realtime-react/use-pull-family.ts +13 -13
  80. package/src/realtime-react/use-pull.ts +12 -12
  81. package/src/realtime-react/use-push.ts +15 -15
  82. package/src/realtime-react/use-server-action.ts +21 -21
  83. package/src/realtime-testing/index.ts +1 -0
  84. package/src/realtime-testing/setup-realtime-test.tsx +160 -0
  85. package/src/selector.ts +25 -25
  86. package/src/silo.ts +38 -38
  87. package/src/subscribe.ts +68 -68
  88. package/src/timeline.ts +13 -13
  89. package/src/transaction.ts +28 -28
  90. package/src/web-effects/storage.ts +17 -17
@@ -12,197 +12,209 @@ import { setState } from ".."
12
12
  import { runTransaction } from "../transaction"
13
13
 
14
14
  export type ExplorerOptions = {
15
- key: string
16
- Components?: {
17
- SpaceWrapper: WC
18
- CloseSpaceButton: FC<{ onClick: () => void }>
19
- }
20
- storeHooks: StoreHooks
15
+ key: string
16
+ Components?: {
17
+ SpaceWrapper: WC
18
+ CloseSpaceButton: FC<{ onClick: () => void }>
19
+ }
20
+ storeHooks: StoreHooks
21
21
  }
22
22
 
23
23
  const DEFAULT_COMPONENTS: ExplorerOptions[`Components`] = {
24
- SpaceWrapper: ({ children }) => <div>{children}</div>,
25
- CloseSpaceButton: ({ onClick }) => <button onClick={onClick}>X</button>,
24
+ SpaceWrapper: ({ children }) => <div>{children}</div>,
25
+ CloseSpaceButton: ({ onClick }) => (
26
+ <button type="button" onClick={onClick}>
27
+ X
28
+ </button>
29
+ ),
26
30
  }
27
31
 
28
32
  export const composeExplorer = ({
29
- key,
30
- Components,
31
- storeHooks: { useO, useIO },
33
+ key,
34
+ Components,
35
+ storeHooks: { useO, useIO },
32
36
  }: ExplorerOptions): ReturnType<typeof attachExplorerState> & {
33
- Explorer: FC<{ children: ReactNode }>
34
- useSetTitle: (viewId: string) => void
37
+ Explorer: FC<{ children: ReactNode }>
38
+ useSetTitle: (viewId: string) => void
35
39
  } => {
36
- const { SpaceWrapper, CloseSpaceButton } = {
37
- ...DEFAULT_COMPONENTS,
38
- ...Components,
39
- }
40
-
41
- const state = attachExplorerState(key)
42
-
43
- const {
44
- addSpace,
45
- addView,
46
- allViewsState,
47
- findSpaceFocusedViewState,
48
- findSpaceLayoutNode,
49
- findSpaceViewsState,
50
- findViewFocusedState,
51
- findViewState,
52
- removeSpace,
53
- removeView,
54
- spaceLayoutState,
55
- viewIndexState,
56
- } = state
57
-
58
- const View: FC<{
59
- children: ReactNode
60
- viewId: string
61
- }> = ({ children, viewId }) => {
62
- const location = useLocation()
63
- const viewState = findViewState(viewId)
64
- const [view, setView] = useIO(viewState)
65
- useEffect(() => {
66
- setView((view) => ({ ...view, location }))
67
- }, [location.key])
68
- return (
69
- <div className="view">
70
- <header>
71
- <h1>{view.title}</h1>
72
- <CloseSpaceButton onClick={() => runTransaction(removeView)(viewId)} />
73
- </header>
74
- <main>{children}</main>
75
- <footer>
76
- <nav>
77
- {location.pathname.split(`/`).map((pathPiece, idx, array) =>
78
- pathPiece === `` && idx === 1 ? null : (
79
- <Link
80
- to={array.slice(0, idx + 1).join(`/`)}
81
- key={`${pathPiece}_${viewId}`}
82
- >
83
- {idx === 0 ? `home` : pathPiece}/
84
- </Link>
85
- )
86
- )}
87
- </nav>
88
- </footer>
89
- </div>
90
- )
91
- }
92
-
93
- const Tab: FC<{ viewId: string; spaceId: string }> = ({ viewId, spaceId }) => {
94
- const view = useO(findViewState(viewId))
95
- const [spaceFocusedView, setSpaceFocusedView] = useIO(
96
- findSpaceFocusedViewState(spaceId)
97
- )
98
- return (
99
- <div
100
- className={`tab ${spaceFocusedView === viewId ? `focused` : ``}`}
101
- onClick={() => setSpaceFocusedView(viewId)}
102
- >
103
- {view.title}
104
- </div>
105
- )
106
- }
107
-
108
- const TabBar: FC<{
109
- spaceId: string
110
- viewIds: string[]
111
- }> = ({ spaceId, viewIds }) => {
112
- return (
113
- <nav className="tab-bar">
114
- {viewIds.map((viewId) => (
115
- <Tab key={viewId} viewId={viewId} spaceId={spaceId} />
116
- ))}
117
- </nav>
118
- )
119
- }
120
-
121
- const Space: FC<{
122
- children: ReactNode
123
- focusedViewId: string
124
- spaceId: string
125
- viewIds: string[]
126
- }> = ({ children, focusedViewId, spaceId, viewIds }) => {
127
- const view = useO(findViewState(focusedViewId))
128
- return (
129
- <div className="space">
130
- <ErrorBoundary>
131
- <MemoryRouter
132
- initialEntries={view.location ? [view.location.pathname] : []}
133
- >
134
- <TabBar spaceId={spaceId} viewIds={viewIds} />
135
- <View viewId={focusedViewId}>{children}</View>
136
- </MemoryRouter>
137
- </ErrorBoundary>
138
- </div>
139
- )
140
- }
141
-
142
- const Spaces: FC<{ children: ReactNode; spaceId?: string }> = ({
143
- children,
144
- spaceId = `root`,
145
- }) => {
146
- const spaceLayout = useO(findSpaceLayoutNode(spaceId))
147
- const viewIds = useO(findSpaceViewsState(spaceId))
148
- const focusedViewId = useO(findSpaceFocusedViewState(spaceId))
149
- console.log({ spaceLayout, viewIds, focusedViewId })
150
- return (
151
- <div className="spaces">
152
- {spaceLayout.childSpaceIds.length === 0 ? (
153
- focusedViewId ? (
154
- <Space
155
- focusedViewId={focusedViewId}
156
- spaceId={spaceId}
157
- viewIds={viewIds}
158
- >
159
- {children}
160
- </Space>
161
- ) : (
162
- `no view`
163
- )
164
- ) : (
165
- spaceLayout.childSpaceIds.map((childSpaceId) => (
166
- <Spaces key={childSpaceId} spaceId={childSpaceId}>
167
- {children}
168
- </Spaces>
169
- ))
170
- )}
171
- <button onClick={() => runTransaction(addView)({ spaceId })}>
172
- + View
173
- </button>
174
- <button onClick={() => runTransaction(addSpace)({ parentId: spaceId })}>
175
- + Space
176
- </button>
177
- </div>
178
- )
179
- }
180
-
181
- const Explorer: FC<{ children: ReactNode }> = ({ children }) => {
182
- return <Spaces>{children}</Spaces>
183
- }
184
-
185
- const useSetTitle = (title: string): void => {
186
- let location: ReturnType<typeof useLocation>
187
- try {
188
- location = useLocation()
189
- } catch (thrown) {
190
- console.warn(
191
- `Failed to set title to "${title}"; useSetTitle must be called within the children of Explorer`
192
- )
193
- return
194
- }
195
- const views = useO(allViewsState)
196
- const locationView = views.find(
197
- ([, view]) => view.location.key === location.key
198
- )
199
- const viewId = locationView?.[0] ?? null
200
- useEffect(() => {
201
- if (viewId) {
202
- setState(findViewState(viewId), (v) => ({ ...v, title }))
203
- }
204
- }, [viewId])
205
- }
206
-
207
- return { Explorer, useSetTitle, ...state }
40
+ const { SpaceWrapper, CloseSpaceButton } = {
41
+ ...DEFAULT_COMPONENTS,
42
+ ...Components,
43
+ }
44
+
45
+ const state = attachExplorerState(key)
46
+
47
+ const {
48
+ addSpace,
49
+ addView,
50
+ allViewsState,
51
+ findSpaceFocusedViewState,
52
+ findSpaceLayoutNode,
53
+ findSpaceViewsState,
54
+ findViewFocusedState,
55
+ findViewState,
56
+ removeSpace,
57
+ removeView,
58
+ spaceLayoutState,
59
+ viewIndexState,
60
+ } = state
61
+
62
+ const View: FC<{
63
+ children: ReactNode
64
+ viewId: string
65
+ }> = ({ children, viewId }) => {
66
+ const location = useLocation()
67
+ const viewState = findViewState(viewId)
68
+ const [view, setView] = useIO(viewState)
69
+ useEffect(() => {
70
+ setView((view) => ({ ...view, location }))
71
+ }, [location.key])
72
+ return (
73
+ <div className="view">
74
+ <header>
75
+ <h1>{view.title}</h1>
76
+ <CloseSpaceButton onClick={() => runTransaction(removeView)(viewId)} />
77
+ </header>
78
+ <main>{children}</main>
79
+ <footer>
80
+ <nav>
81
+ {location.pathname.split(`/`).map((pathPiece, idx, array) =>
82
+ pathPiece === `` && idx === 1 ? null : (
83
+ <Link
84
+ to={array.slice(0, idx + 1).join(`/`)}
85
+ key={`${pathPiece}_${viewId}`}
86
+ >
87
+ {idx === 0 ? `home` : pathPiece}/
88
+ </Link>
89
+ ),
90
+ )}
91
+ </nav>
92
+ </footer>
93
+ </div>
94
+ )
95
+ }
96
+
97
+ const Tab: FC<{ viewId: string; spaceId: string }> = ({ viewId, spaceId }) => {
98
+ const view = useO(findViewState(viewId))
99
+ const [spaceFocusedView, setSpaceFocusedView] = useIO(
100
+ findSpaceFocusedViewState(spaceId),
101
+ )
102
+ const handleClick = () => setSpaceFocusedView(viewId)
103
+ return (
104
+ <div
105
+ className={`tab ${spaceFocusedView === viewId ? `focused` : ``}`}
106
+ onClick={handleClick}
107
+ onKeyUp={handleClick}
108
+ >
109
+ {view.title}
110
+ </div>
111
+ )
112
+ }
113
+
114
+ const TabBar: FC<{
115
+ spaceId: string
116
+ viewIds: string[]
117
+ }> = ({ spaceId, viewIds }) => {
118
+ return (
119
+ <nav className="tab-bar">
120
+ {viewIds.map((viewId) => (
121
+ <Tab key={viewId} viewId={viewId} spaceId={spaceId} />
122
+ ))}
123
+ </nav>
124
+ )
125
+ }
126
+
127
+ const Space: FC<{
128
+ children: ReactNode
129
+ focusedViewId: string
130
+ spaceId: string
131
+ viewIds: string[]
132
+ }> = ({ children, focusedViewId, spaceId, viewIds }) => {
133
+ const view = useO(findViewState(focusedViewId))
134
+ return (
135
+ <div className="space">
136
+ <ErrorBoundary>
137
+ <MemoryRouter
138
+ initialEntries={view.location ? [view.location.pathname] : []}
139
+ >
140
+ <TabBar spaceId={spaceId} viewIds={viewIds} />
141
+ <View viewId={focusedViewId}>{children}</View>
142
+ </MemoryRouter>
143
+ </ErrorBoundary>
144
+ </div>
145
+ )
146
+ }
147
+
148
+ const Spaces: FC<{ children: ReactNode; spaceId?: string }> = ({
149
+ children,
150
+ spaceId = `root`,
151
+ }) => {
152
+ const spaceLayout = useO(findSpaceLayoutNode(spaceId))
153
+ const viewIds = useO(findSpaceViewsState(spaceId))
154
+ const focusedViewId = useO(findSpaceFocusedViewState(spaceId))
155
+ console.log({ spaceLayout, viewIds, focusedViewId })
156
+ return (
157
+ <div className="spaces">
158
+ {spaceLayout.childSpaceIds.length === 0 ? (
159
+ focusedViewId ? (
160
+ <Space
161
+ focusedViewId={focusedViewId}
162
+ spaceId={spaceId}
163
+ viewIds={viewIds}
164
+ >
165
+ {children}
166
+ </Space>
167
+ ) : (
168
+ `no view`
169
+ )
170
+ ) : (
171
+ spaceLayout.childSpaceIds.map((childSpaceId) => (
172
+ <Spaces key={childSpaceId} spaceId={childSpaceId}>
173
+ {children}
174
+ </Spaces>
175
+ ))
176
+ )}
177
+ <button
178
+ type="button"
179
+ onClick={() => runTransaction(addView)({ spaceId })}
180
+ >
181
+ + View
182
+ </button>
183
+ <button
184
+ type="button"
185
+ onClick={() => runTransaction(addSpace)({ parentId: spaceId })}
186
+ >
187
+ + Space
188
+ </button>
189
+ </div>
190
+ )
191
+ }
192
+
193
+ const Explorer: FC<{ children: ReactNode }> = ({ children }) => {
194
+ return <Spaces>{children}</Spaces>
195
+ }
196
+
197
+ const useSetTitle = (title: string): void => {
198
+ let location: ReturnType<typeof useLocation>
199
+ try {
200
+ location = useLocation()
201
+ } catch (thrown) {
202
+ console.warn(
203
+ `Failed to set title to "${title}"; useSetTitle must be called within the children of Explorer`,
204
+ )
205
+ return
206
+ }
207
+ const views = useO(allViewsState)
208
+ const locationView = views.find(
209
+ ([, view]) => view.location.key === location.key,
210
+ )
211
+ const viewId = locationView?.[0] ?? null
212
+ useEffect(() => {
213
+ if (viewId) {
214
+ setState(findViewState(viewId), (v) => ({ ...v, title }))
215
+ }
216
+ }, [viewId])
217
+ }
218
+
219
+ return { Explorer, useSetTitle, ...state }
208
220
  }
@@ -6,15 +6,15 @@ import { parseJson, stringifyJson } from "~/packages/anvl/src/json"
6
6
  import { persistAtom } from "../web-effects"
7
7
 
8
8
  export const persistStringSetAtom = persistAtom<Set<string>>(localStorage)({
9
- stringify: (set) => stringifyJson([...set]),
10
- parse: (string) => {
11
- try {
12
- const json = parseJson(string)
13
- const array = isArray(isString)(json) ? json : []
14
- return new Set(array)
15
- } catch (thrown) {
16
- console.error(`Error parsing spaceIndexState from localStorage`)
17
- return new Set()
18
- }
19
- },
9
+ stringify: (set) => stringifyJson([...set]),
10
+ parse: (string) => {
11
+ try {
12
+ const json = parseJson(string)
13
+ const array = isArray(isString)(json) ? json : []
14
+ return new Set(array)
15
+ } catch (thrown) {
16
+ console.error(`Error parsing spaceIndexState from localStorage`)
17
+ return new Set()
18
+ }
19
+ },
20
20
  })