atom.io 0.6.2 → 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 (110) hide show
  1. package/dist/index.d.mts +2 -2
  2. package/dist/index.d.ts +2 -2
  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.d.mts +18 -0
  8. package/json/dist/index.d.ts +18 -0
  9. package/json/dist/index.js +51 -0
  10. package/json/dist/index.js.map +1 -0
  11. package/json/dist/index.mjs +15 -0
  12. package/json/dist/index.mjs.map +1 -0
  13. package/package.json +13 -3
  14. package/react/dist/index.d.mts +24 -0
  15. package/react/dist/index.d.ts +24 -0
  16. package/react/dist/index.js +83 -0
  17. package/react/dist/index.js.map +1 -0
  18. package/react/dist/index.mjs +41 -0
  19. package/react/dist/index.mjs.map +1 -0
  20. package/react-devtools/dist/index.css +26 -0
  21. package/react-devtools/dist/index.css.map +1 -0
  22. package/react-devtools/dist/index.d.mts +15 -0
  23. package/react-devtools/dist/index.d.ts +15 -0
  24. package/react-devtools/dist/index.js +1596 -0
  25. package/react-devtools/dist/index.js.map +1 -0
  26. package/react-devtools/dist/index.mjs +1568 -0
  27. package/react-devtools/dist/index.mjs.map +1 -0
  28. package/realtime/dist/index.d.mts +27 -0
  29. package/realtime/dist/index.d.ts +27 -0
  30. package/realtime/dist/index.js +191 -0
  31. package/realtime/dist/index.js.map +1 -0
  32. package/realtime/dist/index.mjs +152 -0
  33. package/realtime/dist/index.mjs.map +1 -0
  34. package/realtime-react/dist/index.d.mts +45 -0
  35. package/realtime-react/dist/index.d.ts +45 -0
  36. package/realtime-react/dist/index.js +213 -0
  37. package/realtime-react/dist/index.js.map +1 -0
  38. package/realtime-react/dist/index.mjs +168 -0
  39. package/realtime-react/dist/index.mjs.map +1 -0
  40. package/realtime-testing/dist/index.d.mts +49 -0
  41. package/realtime-testing/dist/index.d.ts +49 -0
  42. package/realtime-testing/dist/index.js +153 -0
  43. package/realtime-testing/dist/index.js.map +1 -0
  44. package/realtime-testing/dist/index.mjs +117 -0
  45. package/realtime-testing/dist/index.mjs.map +1 -0
  46. package/realtime-testing/package.json +15 -0
  47. package/src/atom.ts +15 -15
  48. package/src/index.ts +59 -59
  49. package/src/internal/atom-internal.ts +36 -36
  50. package/src/internal/families-internal.ts +114 -114
  51. package/src/internal/get.ts +83 -83
  52. package/src/internal/is-default.ts +17 -17
  53. package/src/internal/meta/attach-meta.ts +7 -7
  54. package/src/internal/meta/meta-state.ts +115 -115
  55. package/src/internal/operation.ts +93 -93
  56. package/src/internal/selector/create-read-write-selector.ts +46 -46
  57. package/src/internal/selector/create-readonly-selector.ts +37 -37
  58. package/src/internal/selector/lookup-selector-sources.ts +9 -9
  59. package/src/internal/selector/register-selector.ts +44 -44
  60. package/src/internal/selector/trace-selector-atoms.ts +30 -30
  61. package/src/internal/selector/update-selector-atoms.ts +25 -25
  62. package/src/internal/selector-internal.ts +37 -37
  63. package/src/internal/set.ts +78 -78
  64. package/src/internal/store.ts +118 -118
  65. package/src/internal/subscribe-internal.ts +62 -62
  66. package/src/internal/time-travel-internal.ts +76 -76
  67. package/src/internal/timeline/add-atom-to-timeline.ts +158 -153
  68. package/src/internal/timeline-internal.ts +80 -80
  69. package/src/internal/transaction/abort-transaction.ts +8 -8
  70. package/src/internal/transaction/apply-transaction.ts +41 -41
  71. package/src/internal/transaction/build-transaction.ts +28 -28
  72. package/src/internal/transaction/index.ts +7 -7
  73. package/src/internal/transaction/redo-transaction.ts +13 -13
  74. package/src/internal/transaction/undo-transaction.ts +13 -13
  75. package/src/internal/transaction-internal.ts +48 -48
  76. package/src/json/select-json.ts +12 -12
  77. package/src/logger.ts +30 -30
  78. package/src/react/store-context.tsx +4 -4
  79. package/src/react/store-hooks.ts +18 -18
  80. package/src/react-devtools/AtomIODevtools.tsx +83 -82
  81. package/src/react-devtools/StateEditor.tsx +53 -53
  82. package/src/react-devtools/TokenList.tsx +47 -42
  83. package/src/react-explorer/AtomIOExplorer.tsx +197 -185
  84. package/src/react-explorer/explorer-effects.ts +11 -11
  85. package/src/react-explorer/explorer-states.ts +186 -193
  86. package/src/react-explorer/index.ts +11 -11
  87. package/src/react-explorer/space-states.ts +48 -50
  88. package/src/react-explorer/view-states.ts +25 -25
  89. package/src/realtime/hook-composition/expose-family.ts +81 -81
  90. package/src/realtime/hook-composition/expose-single.ts +26 -26
  91. package/src/realtime/hook-composition/expose-timeline.ts +60 -0
  92. package/src/realtime/hook-composition/index.ts +2 -2
  93. package/src/realtime/hook-composition/receive-state.ts +18 -18
  94. package/src/realtime/hook-composition/receive-transaction.ts +8 -8
  95. package/src/realtime-react/realtime-context.tsx +17 -17
  96. package/src/realtime-react/realtime-hooks.ts +17 -17
  97. package/src/realtime-react/realtime-state.ts +4 -4
  98. package/src/realtime-react/use-pull-family-member.ts +15 -15
  99. package/src/realtime-react/use-pull-family.ts +13 -13
  100. package/src/realtime-react/use-pull.ts +12 -12
  101. package/src/realtime-react/use-push.ts +15 -15
  102. package/src/realtime-react/use-server-action.ts +21 -21
  103. package/src/realtime-testing/index.ts +1 -0
  104. package/src/realtime-testing/setup-realtime-test.tsx +160 -0
  105. package/src/selector.ts +25 -25
  106. package/src/silo.ts +38 -38
  107. package/src/subscribe.ts +68 -68
  108. package/src/timeline.ts +13 -13
  109. package/src/transaction.ts +28 -28
  110. package/src/web-effects/storage.ts +17 -17
@@ -5,220 +5,213 @@ import type { Entries } from "~/packages/anvl/src/object"
5
5
 
6
6
  import { addToIndex, removeFromIndex } from "."
7
7
  import {
8
- makeSpaceLayoutNodeFamily,
9
- makeSpaceFamily,
10
- makeSpaceIndex,
11
- makeSpaceLayoutState,
8
+ makeSpaceLayoutNodeFamily,
9
+ makeSpaceFamily,
10
+ makeSpaceIndex,
11
+ makeSpaceLayoutState,
12
12
  } from "./space-states"
13
13
  import type { View } from "./view-states"
14
14
  import {
15
- makeViewFocusedFamily,
16
- makeViewFamily,
17
- makeViewIndex,
15
+ makeViewFocusedFamily,
16
+ makeViewFamily,
17
+ makeViewIndex,
18
18
  } from "./view-states"
19
19
  import type {
20
- AtomFamily,
21
- AtomToken,
22
- ReadonlySelectorFamily,
23
- SelectorFamily,
24
- Write,
20
+ AtomFamily,
21
+ AtomToken,
22
+ ReadonlySelectorFamily,
23
+ SelectorFamily,
24
+ Write,
25
25
  } from ".."
26
26
  import { selectorFamily, selector, transaction, atom } from ".."
27
27
  import { persistAtom } from "../web-effects"
28
28
 
29
29
  export const makeViewsPerSpaceState = (
30
- key: string
30
+ key: string,
31
31
  ): AtomToken<Join<null, `viewId`, `spaceId`>> =>
32
- atom<Join<null, `viewId`, `spaceId`>>({
33
- key: `${key}:views_per_space`,
34
- default: new Join({ relationType: `1:n` }),
35
- effects: [
36
- persistAtom<Join<null, `viewId`, `spaceId`>>(localStorage)({
37
- stringify: (index) => JSON.stringify(index.toJSON()),
38
- parse: (json) =>
39
- Join.fromJSON(JSON.parse(json), {
40
- from: `viewId`,
41
- to: `spaceId`,
42
- }),
43
- })(`${key}:views_per_space`),
44
- ],
45
- })
32
+ atom<Join<null, `viewId`, `spaceId`>>({
33
+ key: `${key}:views_per_space`,
34
+ default: new Join({ relationType: `1:n` }),
35
+ effects: [
36
+ persistAtom<Join<null, `viewId`, `spaceId`>>(localStorage)({
37
+ stringify: (index) => JSON.stringify(index.toJSON()),
38
+ parse: (json) =>
39
+ Join.fromJSON(JSON.parse(json), {
40
+ from: `viewId`,
41
+ to: `spaceId`,
42
+ }),
43
+ })(`${key}:views_per_space`),
44
+ ],
45
+ })
46
46
 
47
47
  export const makeSpaceViewsFamily = (
48
- key: string,
49
- viewsPerSpaceState: AtomToken<Join<null, `viewId`, `spaceId`>>
48
+ key: string,
49
+ viewsPerSpaceState: AtomToken<Join<null, `viewId`, `spaceId`>>,
50
50
  ): ReadonlySelectorFamily<string[], string> =>
51
- selectorFamily<string[], string>({
52
- key: `${key}:space_views`,
53
- get:
54
- (spaceId) =>
55
- ({ get }) => {
56
- const join = get(viewsPerSpaceState)
57
- const viewIds = join.getRelatedIds(spaceId)
58
- return viewIds
59
- },
60
- })
51
+ selectorFamily<string[], string>({
52
+ key: `${key}:space_views`,
53
+ get: (spaceId) => ({ get }) => {
54
+ const join = get(viewsPerSpaceState)
55
+ const viewIds = join.getRelatedIds(spaceId)
56
+ return viewIds
57
+ },
58
+ })
61
59
 
62
60
  export const makeSpaceFocusedViewFamily = (
63
- key: string,
64
- findSpaceViewsState: ReadonlySelectorFamily<string[], string>,
65
- findViewFocusedState: AtomFamily<number, string>
61
+ key: string,
62
+ findSpaceViewsState: ReadonlySelectorFamily<string[], string>,
63
+ findViewFocusedState: AtomFamily<number, string>,
66
64
  ): SelectorFamily<string | null, string> =>
67
- selectorFamily<string | null, string>({
68
- key: `${key}:space_focused_view`,
69
- get:
70
- (spaceKey) =>
71
- ({ get }) => {
72
- const views = get(findSpaceViewsState(spaceKey))
73
- const viewsLastFocused = views.map((viewKey): [string, number] => [
74
- viewKey,
75
- get(findViewFocusedState(viewKey)),
76
- ])
77
- const lastFocused = lastOf(viewsLastFocused.sort((a, b) => b[1] - a[1]))
78
- return lastFocused ? lastFocused[0] : null
79
- },
80
- set:
81
- (spaceKey) =>
82
- ({ get, set }, viewKey) => {
83
- if (viewKey === null) {
84
- return
85
- }
86
- const views = get(findSpaceViewsState(spaceKey))
87
- if (views.includes(viewKey)) {
88
- set(findViewFocusedState(viewKey), Date.now())
89
- } else {
90
- console.warn(`View ${viewKey} not found in space ${spaceKey}`)
91
- }
92
- },
93
- })
65
+ selectorFamily<string | null, string>({
66
+ key: `${key}:space_focused_view`,
67
+ get: (spaceKey) => ({ get }) => {
68
+ const views = get(findSpaceViewsState(spaceKey))
69
+ const viewsLastFocused = views.map((viewKey): [string, number] => [
70
+ viewKey,
71
+ get(findViewFocusedState(viewKey)),
72
+ ])
73
+ const lastFocused = lastOf(viewsLastFocused.sort((a, b) => b[1] - a[1]))
74
+ return lastFocused ? lastFocused[0] : null
75
+ },
76
+ set: (spaceKey) => ({ get, set }, viewKey) => {
77
+ if (viewKey === null) {
78
+ return
79
+ }
80
+ const views = get(findSpaceViewsState(spaceKey))
81
+ if (views.includes(viewKey)) {
82
+ set(findViewFocusedState(viewKey), Date.now())
83
+ } else {
84
+ console.warn(`View ${viewKey} not found in space ${spaceKey}`)
85
+ }
86
+ },
87
+ })
94
88
 
95
89
  type AddViewOptions = { spaceId?: string; path?: string }
96
90
  type SplitSpaceOptions = { parentId?: string }
97
91
 
98
92
  // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
99
93
  export const attachExplorerState = (key: string) => {
100
- const findSpaceState = makeSpaceFamily(key)
101
- const findViewState = makeViewFamily(key)
102
- const findViewFocusedState = makeViewFocusedFamily(key)
103
- const spaceIndexState = makeSpaceIndex(key)
104
- const spaceLayoutState = makeSpaceLayoutState(key)
105
- const viewIndexState = makeViewIndex(key)
106
- const viewsPerSpaceState = makeViewsPerSpaceState(key)
107
-
108
- const findSpaceLayoutNode = makeSpaceLayoutNodeFamily(key, spaceLayoutState)
109
- const findSpaceViewsState = makeSpaceViewsFamily(key, viewsPerSpaceState)
110
- const findSpaceFocusedViewState = makeSpaceFocusedViewFamily(
111
- key,
112
- findSpaceViewsState,
113
- findViewFocusedState
114
- )
115
-
116
- const allViewsState = selector<Entries<string, View>>({
117
- key: `${key}:all_views`,
118
- get: ({ get }) => {
119
- const viewIndex = get(viewIndexState)
120
- return [...viewIndex].map((id) => [id, get(findViewState(id))])
121
- },
122
- })
123
-
124
- const writeOperationAddSpace: Write<
125
- (options?: SplitSpaceOptions) => string
126
- > = (transactors, { parentId = `root` } = {}) => {
127
- const { set } = transactors
128
- const key = `s-${now()}`
129
- addToIndex(transactors, { indexAtom: spaceIndexState, id: key })
130
- set(spaceLayoutState, (current) =>
131
- current.set({ parent: `parent:${parentId}`, child: key }, { size: 1 })
132
- )
133
- set(findSpaceState(key), 1)
134
- return key
135
- }
136
-
137
- const writeOperationRemoveSpace: Write<(id: string) => void> = (
138
- transactors,
139
- id
140
- ) => {
141
- removeFromIndex(transactors, { indexAtom: spaceIndexState, id })
142
- transactors.set(findSpaceState(id), null)
143
- }
144
-
145
- const writeOperationAddView: Write<(options?: AddViewOptions) => void> = (
146
- transactors,
147
- { spaceId: maybeSpaceId, path } = {}
148
- ) => {
149
- const { get, set } = transactors
150
- const id = `v-${now()}`
151
-
152
- addToIndex(transactors, { indexAtom: viewIndexState, id })
153
- set(
154
- findViewState(id),
155
- (current): View => ({
156
- ...current,
157
- location: {
158
- ...current.location,
159
- pathname: path ?? `/`,
160
- },
161
- })
162
- )
163
- const spaceId =
164
- maybeSpaceId ??
165
- lastOf([...get(spaceIndexState)]) ??
166
- writeOperationAddSpace(transactors)
167
- set(findViewFocusedState(id), Date.now())
168
-
169
- set(viewsPerSpaceState, (current) => current.set({ spaceId, viewId: id }))
170
- set(findViewFocusedState(id), Date.now())
171
- }
172
-
173
- const writeOperationRemoveView: Write<(viewId: string) => void> = (
174
- transactors,
175
- viewId
176
- ) => {
177
- const { set } = transactors
178
- removeFromIndex(transactors, { indexAtom: viewIndexState, id: viewId })
179
- set(viewsPerSpaceState, (current) => current.remove({ viewId }))
180
- set(findViewState(viewId), null)
181
- }
182
-
183
- const addView = transaction<(options?: AddViewOptions) => void>({
184
- key: `${key}:add_view`,
185
- do: writeOperationAddView,
186
- })
187
-
188
- const removeView = transaction({
189
- key: `${key}:remove_view`,
190
- do: writeOperationRemoveView,
191
- })
192
-
193
- const addSpace = transaction({
194
- key: `${key}:add_space`,
195
- do: writeOperationAddSpace,
196
- })
197
-
198
- const removeSpace = transaction({
199
- key: `${key}:remove_space`,
200
- do: writeOperationRemoveSpace,
201
- })
202
-
203
- return {
204
- addSpace,
205
- addView,
206
- allViewsState,
207
- findSpaceLayoutNode,
208
- findSpaceFocusedViewState,
209
- findSpaceState,
210
- findSpaceViewsState,
211
- findViewState,
212
- findViewFocusedState,
213
- removeSpace,
214
- removeView,
215
- spaceIndexState,
216
- spaceLayoutState,
217
- viewIndexState,
218
- viewsPerSpaceState,
219
- writeOperationAddSpace,
220
- writeOperationAddView,
221
- writeOperationRemoveSpace,
222
- writeOperationRemoveView,
223
- }
94
+ const findSpaceState = makeSpaceFamily(key)
95
+ const findViewState = makeViewFamily(key)
96
+ const findViewFocusedState = makeViewFocusedFamily(key)
97
+ const spaceIndexState = makeSpaceIndex(key)
98
+ const spaceLayoutState = makeSpaceLayoutState(key)
99
+ const viewIndexState = makeViewIndex(key)
100
+ const viewsPerSpaceState = makeViewsPerSpaceState(key)
101
+
102
+ const findSpaceLayoutNode = makeSpaceLayoutNodeFamily(key, spaceLayoutState)
103
+ const findSpaceViewsState = makeSpaceViewsFamily(key, viewsPerSpaceState)
104
+ const findSpaceFocusedViewState = makeSpaceFocusedViewFamily(
105
+ key,
106
+ findSpaceViewsState,
107
+ findViewFocusedState,
108
+ )
109
+
110
+ const allViewsState = selector<Entries<string, View>>({
111
+ key: `${key}:all_views`,
112
+ get: ({ get }) => {
113
+ const viewIndex = get(viewIndexState)
114
+ return [...viewIndex].map((id) => [id, get(findViewState(id))])
115
+ },
116
+ })
117
+
118
+ const writeOperationAddSpace: Write<(options?: SplitSpaceOptions) => string> =
119
+ (transactors, { parentId = `root` } = {}) => {
120
+ const { set } = transactors
121
+ const key = `s-${now()}`
122
+ addToIndex(transactors, { indexAtom: spaceIndexState, id: key })
123
+ set(spaceLayoutState, (current) =>
124
+ current.set({ parent: `parent:${parentId}`, child: key }, { size: 1 }),
125
+ )
126
+ set(findSpaceState(key), 1)
127
+ return key
128
+ }
129
+
130
+ const writeOperationRemoveSpace: Write<(id: string) => void> = (
131
+ transactors,
132
+ id,
133
+ ) => {
134
+ removeFromIndex(transactors, { indexAtom: spaceIndexState, id })
135
+ transactors.set(findSpaceState(id), null)
136
+ }
137
+
138
+ const writeOperationAddView: Write<(options?: AddViewOptions) => void> = (
139
+ transactors,
140
+ { spaceId: maybeSpaceId, path } = {},
141
+ ) => {
142
+ const { get, set } = transactors
143
+ const id = `v-${now()}`
144
+
145
+ addToIndex(transactors, { indexAtom: viewIndexState, id })
146
+ set(
147
+ findViewState(id),
148
+ (current): View => ({
149
+ ...current,
150
+ location: {
151
+ ...current.location,
152
+ pathname: path ?? `/`,
153
+ },
154
+ }),
155
+ )
156
+ const spaceId =
157
+ maybeSpaceId ??
158
+ lastOf([...get(spaceIndexState)]) ??
159
+ writeOperationAddSpace(transactors)
160
+ set(findViewFocusedState(id), Date.now())
161
+
162
+ set(viewsPerSpaceState, (current) => current.set({ spaceId, viewId: id }))
163
+ set(findViewFocusedState(id), Date.now())
164
+ }
165
+
166
+ const writeOperationRemoveView: Write<(viewId: string) => void> = (
167
+ transactors,
168
+ viewId,
169
+ ) => {
170
+ const { set } = transactors
171
+ removeFromIndex(transactors, { indexAtom: viewIndexState, id: viewId })
172
+ set(viewsPerSpaceState, (current) => current.remove({ viewId }))
173
+ set(findViewState(viewId), null)
174
+ }
175
+
176
+ const addView = transaction<(options?: AddViewOptions) => void>({
177
+ key: `${key}:add_view`,
178
+ do: writeOperationAddView,
179
+ })
180
+
181
+ const removeView = transaction({
182
+ key: `${key}:remove_view`,
183
+ do: writeOperationRemoveView,
184
+ })
185
+
186
+ const addSpace = transaction({
187
+ key: `${key}:add_space`,
188
+ do: writeOperationAddSpace,
189
+ })
190
+
191
+ const removeSpace = transaction({
192
+ key: `${key}:remove_space`,
193
+ do: writeOperationRemoveSpace,
194
+ })
195
+
196
+ return {
197
+ addSpace,
198
+ addView,
199
+ allViewsState,
200
+ findSpaceLayoutNode,
201
+ findSpaceFocusedViewState,
202
+ findSpaceState,
203
+ findSpaceViewsState,
204
+ findViewState,
205
+ findViewFocusedState,
206
+ removeSpace,
207
+ removeView,
208
+ spaceIndexState,
209
+ spaceLayoutState,
210
+ viewIndexState,
211
+ viewsPerSpaceState,
212
+ writeOperationAddSpace,
213
+ writeOperationAddView,
214
+ writeOperationRemoveSpace,
215
+ writeOperationRemoveView,
216
+ }
224
217
  }
@@ -3,21 +3,21 @@ import type { AtomToken, Write } from "atom.io"
3
3
  export * from "./AtomIOExplorer"
4
4
 
5
5
  export type AtomicIndexOptions = {
6
- indexAtom: AtomToken<Set<string>>
7
- id: string
6
+ indexAtom: AtomToken<Set<string>>
7
+ id: string
8
8
  }
9
9
 
10
10
  export const addToIndex: Write<(options: AtomicIndexOptions) => void> = (
11
- { set },
12
- { indexAtom, id }
11
+ { set },
12
+ { indexAtom, id },
13
13
  ): void => set(indexAtom, (currentSet) => new Set(currentSet).add(id))
14
14
 
15
15
  export const removeFromIndex: Write<(options: AtomicIndexOptions) => void> = (
16
- { set },
17
- { indexAtom, id }
16
+ { set },
17
+ { indexAtom, id },
18
18
  ): void =>
19
- set(indexAtom, (currentSet) => {
20
- const newSet = new Set(currentSet)
21
- newSet.delete(id)
22
- return newSet
23
- })
19
+ set(indexAtom, (currentSet) => {
20
+ const newSet = new Set(currentSet)
21
+ newSet.delete(id)
22
+ return newSet
23
+ })
@@ -12,61 +12,59 @@ import { atom, atomFamily } from "../atom"
12
12
  import { lazyLocalStorageEffect, persistAtom } from "../web-effects"
13
13
 
14
14
  export const makeSpaceIndex = (key: string): AtomToken<Set<string>> =>
15
- atom<Set<string>>({
16
- key: `${key}:space_index`,
17
- default: new Set([`root`]),
18
- effects: [persistStringSetAtom(`${key}:space_index`)],
19
- })
15
+ atom<Set<string>>({
16
+ key: `${key}:space_index`,
17
+ default: new Set([`root`]),
18
+ effects: [persistStringSetAtom(`${key}:space_index`)],
19
+ })
20
20
 
21
21
  export const makeSpaceLayoutState = (
22
- key: string
22
+ key: string,
23
23
  ): AtomToken<Join<{ size: number }, `parent`, `child`>> =>
24
- atom({
25
- key: `${key}:space_layout`,
26
- default: new Join({ relationType: `1:n` }),
27
- effects: [
28
- persistAtom<Join<{ size: number }, `parent`, `child`>>(localStorage)({
29
- stringify: (join) => stringifyJson(join.toJSON()),
30
- parse: (string) => {
31
- try {
32
- const json = parseJson(string)
33
- const join = Join.fromJSON(json, {
34
- isContent: hasExactProperties({ size: isNumber }),
35
- from: `parent`,
36
- to: `child`,
37
- })
38
- return join
39
- } catch (thrown) {
40
- console.error(`Error parsing spaceLayoutState from localStorage`)
41
- return new Join({ relationType: `1:n` })
42
- }
43
- },
44
- })(`${key}:space_layout`),
45
- ],
46
- })
24
+ atom({
25
+ key: `${key}:space_layout`,
26
+ default: new Join({ relationType: `1:n` }),
27
+ effects: [
28
+ persistAtom<Join<{ size: number }, `parent`, `child`>>(localStorage)({
29
+ stringify: (join) => stringifyJson(join.toJSON()),
30
+ parse: (string) => {
31
+ try {
32
+ const json = parseJson(string)
33
+ const join = Join.fromJSON(json, {
34
+ isContent: hasExactProperties({ size: isNumber }),
35
+ from: `parent`,
36
+ to: `child`,
37
+ })
38
+ return join
39
+ } catch (thrown) {
40
+ console.error(`Error parsing spaceLayoutState from localStorage`)
41
+ return new Join({ relationType: `1:n` })
42
+ }
43
+ },
44
+ })(`${key}:space_layout`),
45
+ ],
46
+ })
47
47
 
48
48
  export const makeSpaceLayoutNodeFamily = (
49
- key: string,
50
- spaceLayoutState: AtomToken<Join<{ size: number }, `parent`, `child`>>
49
+ key: string,
50
+ spaceLayoutState: AtomToken<Join<{ size: number }, `parent`, `child`>>,
51
51
  ): ReadonlySelectorFamily<{ childSpaceIds: string[]; size: number }, string> =>
52
- selectorFamily<{ childSpaceIds: string[]; size: number }, string>({
53
- key: `${key}:explorer_space`,
54
- get:
55
- (me) =>
56
- ({ get }) => {
57
- const join = get(spaceLayoutState)
58
- const myFollowers = join.getRelatedIds(`parent:${me}`)
59
- const myLeader = join.getRelatedId(me)
60
- const { size } = myLeader
61
- ? join.getContent(myLeader, me) ?? { size: NaN }
62
- : { size: NaN }
63
- return { childSpaceIds: myFollowers, size }
64
- },
65
- })
52
+ selectorFamily<{ childSpaceIds: string[]; size: number }, string>({
53
+ key: `${key}:explorer_space`,
54
+ get: (me) => ({ get }) => {
55
+ const join = get(spaceLayoutState)
56
+ const myFollowers = join.getRelatedIds(`parent:${me}`)
57
+ const myLeader = join.getRelatedId(me)
58
+ const { size } = myLeader
59
+ ? join.getContent(myLeader, me) ?? { size: NaN }
60
+ : { size: NaN }
61
+ return { childSpaceIds: myFollowers, size }
62
+ },
63
+ })
66
64
 
67
65
  export const makeSpaceFamily = (key: string): AtomFamily<number, string> =>
68
- atomFamily<number, string>({
69
- key: `${key}:space`,
70
- default: 1,
71
- effects: (subKey) => [lazyLocalStorageEffect(`${key}:${subKey}`)],
72
- })
66
+ atomFamily<number, string>({
67
+ key: `${key}:space`,
68
+ default: 1,
69
+ effects: (subKey) => [lazyLocalStorageEffect(`${key}:${subKey}`)],
70
+ })
@@ -9,35 +9,35 @@ import { atom, atomFamily } from "../atom"
9
9
  import { lazyLocalStorageEffect } from "../web-effects"
10
10
 
11
11
  export type View = {
12
- title: string
13
- location: Omit<Location, `state`>
12
+ title: string
13
+ location: Omit<Location, `state`>
14
14
  }
15
15
 
16
16
  export const makeViewFamily = (key: string): AtomFamily<View, string> =>
17
- atomFamily<View, string>({
18
- key: `${key}:view`,
19
- default: {
20
- title: ``,
21
- location: {
22
- pathname: ``,
23
- search: ``,
24
- hash: ``,
25
- key: ``,
26
- },
27
- },
28
- effects: (subKey) => [lazyLocalStorageEffect(`${key}:${subKey}`)],
29
- })
17
+ atomFamily<View, string>({
18
+ key: `${key}:view`,
19
+ default: {
20
+ title: ``,
21
+ location: {
22
+ pathname: ``,
23
+ search: ``,
24
+ hash: ``,
25
+ key: ``,
26
+ },
27
+ },
28
+ effects: (subKey) => [lazyLocalStorageEffect(`${key}:${subKey}`)],
29
+ })
30
30
 
31
31
  export const makeViewIndex = (key: string): AtomToken<Set<string>> =>
32
- atom<Set<string>>({
33
- key: `${key}:view_index`,
34
- default: new Set(),
35
- effects: [persistStringSetAtom(`${key}:view_index`)],
36
- })
32
+ atom<Set<string>>({
33
+ key: `${key}:view_index`,
34
+ default: new Set(),
35
+ effects: [persistStringSetAtom(`${key}:view_index`)],
36
+ })
37
37
 
38
38
  export const makeViewFocusedFamily = (key: string): AtomFamily<number, string> =>
39
- atomFamily<number, string>({
40
- key: `${key}:view_focused`,
41
- default: 0,
42
- effects: (subKey) => [lazyLocalStorageEffect(`${key}:${subKey}`)],
43
- })
39
+ atomFamily<number, string>({
40
+ key: `${key}:view_focused`,
41
+ default: 0,
42
+ effects: (subKey) => [lazyLocalStorageEffect(`${key}:${subKey}`)],
43
+ })