atom.io 0.13.0 → 0.14.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/dist/index.cjs +9 -74
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +4 -4
- package/dist/index.d.ts +4 -4
- package/dist/index.js +11 -74
- package/dist/index.js.map +1 -1
- package/dist/metafile-cjs.json +1 -1
- package/dist/metafile-esm.json +1 -1
- package/internal/dist/index.cjs +802 -730
- package/internal/dist/index.cjs.map +1 -1
- package/internal/dist/index.d.cts +9 -2
- package/internal/dist/index.d.ts +9 -2
- package/internal/dist/index.js +800 -731
- package/internal/dist/index.js.map +1 -1
- package/internal/dist/metafile-cjs.json +1 -1
- package/internal/dist/metafile-esm.json +1 -1
- package/internal/src/atom/create-atom.ts +3 -2
- package/internal/src/mutable/create-mutable-atom.ts +3 -2
- package/internal/src/mutable/tracker.ts +6 -4
- package/internal/src/selector/register-selector.ts +1 -1
- package/internal/src/selector/update-selector-atoms.ts +3 -3
- package/internal/src/subscribe/index.ts +3 -0
- package/internal/src/subscribe/recall-state.ts +0 -6
- package/internal/src/subscribe/subscribe-to-state.ts +47 -0
- package/internal/src/subscribe/subscribe-to-timeline.ts +28 -0
- package/internal/src/subscribe/subscribe-to-transaction.ts +33 -0
- package/package.json +8 -8
- package/react/dist/index.cjs +39 -1
- package/react/dist/index.cjs.map +1 -1
- package/react/dist/index.d.cts +9 -2
- package/react/dist/index.d.ts +9 -2
- package/react/dist/index.js +41 -4
- package/react/dist/index.js.map +1 -1
- package/react/dist/metafile-cjs.json +1 -1
- package/react/dist/metafile-esm.json +1 -1
- package/react/src/store-hooks.ts +52 -3
- package/react-devtools/dist/index.cjs.map +1 -1
- package/react-devtools/dist/index.js.map +1 -1
- package/react-devtools/dist/metafile-cjs.json +1 -1
- package/react-devtools/dist/metafile-esm.json +1 -1
- package/realtime-client/dist/index.cjs +8 -7
- package/realtime-client/dist/index.cjs.map +1 -1
- package/realtime-client/dist/index.d.cts +3 -2
- package/realtime-client/dist/index.d.ts +3 -2
- package/realtime-client/dist/index.js +3 -2
- package/realtime-client/dist/index.js.map +1 -1
- package/realtime-client/dist/metafile-cjs.json +1 -1
- package/realtime-client/dist/metafile-esm.json +1 -1
- package/realtime-client/src/use-push.ts +4 -4
- package/realtime-client/src/use-server-action.ts +4 -4
- package/realtime-server/dist/index.cjs +46 -25
- package/realtime-server/dist/index.cjs.map +1 -1
- package/realtime-server/dist/index.d.cts +5 -5
- package/realtime-server/dist/index.d.ts +5 -5
- package/realtime-server/dist/index.js +38 -17
- package/realtime-server/dist/index.js.map +1 -1
- package/realtime-server/dist/metafile-cjs.json +1 -1
- package/realtime-server/dist/metafile-esm.json +1 -1
- package/realtime-server/src/hook-composition/expose-family.ts +7 -3
- package/realtime-server/src/hook-composition/expose-mutable-family.ts +13 -5
- package/realtime-server/src/hook-composition/expose-mutable.ts +11 -3
- package/realtime-server/src/hook-composition/expose-single.ts +6 -2
- package/realtime-server/src/hook-composition/receive-transaction.ts +14 -5
- package/src/subscribe.ts +37 -91
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { ReadonlySelectorToken, StateToken, UpdateHandler } from "atom.io"
|
|
2
|
+
import type { Store } from "atom.io/internal"
|
|
3
|
+
import { subscribeToRootAtoms, withdraw } from "atom.io/internal"
|
|
4
|
+
|
|
5
|
+
export function subscribeToState<T>(
|
|
6
|
+
token: ReadonlySelectorToken<T> | StateToken<T>,
|
|
7
|
+
handleUpdate: UpdateHandler<T>,
|
|
8
|
+
key: string,
|
|
9
|
+
store: Store,
|
|
10
|
+
): () => void {
|
|
11
|
+
const state = withdraw<T>(token, store)
|
|
12
|
+
if (state === undefined) {
|
|
13
|
+
throw new Error(
|
|
14
|
+
`State "${token.key}" not found in this store. Did you forget to initialize with the "atom" or "selector" function?`,
|
|
15
|
+
)
|
|
16
|
+
}
|
|
17
|
+
const unsubFunction = state.subject.subscribe(key, handleUpdate)
|
|
18
|
+
store.logger.info(`👀`, state.type, state.key, `Adding subscription "${key}"`)
|
|
19
|
+
const dependencyUnsubFunctions =
|
|
20
|
+
state.type !== `atom` ? subscribeToRootAtoms(state, store) : null
|
|
21
|
+
|
|
22
|
+
const unsubscribe =
|
|
23
|
+
dependencyUnsubFunctions === null
|
|
24
|
+
? () => {
|
|
25
|
+
store.logger.info(
|
|
26
|
+
`🙈`,
|
|
27
|
+
state.type,
|
|
28
|
+
state.key,
|
|
29
|
+
`Removing subscription "${key}"`,
|
|
30
|
+
)
|
|
31
|
+
unsubFunction()
|
|
32
|
+
}
|
|
33
|
+
: () => {
|
|
34
|
+
store.logger.info(
|
|
35
|
+
`🙈`,
|
|
36
|
+
state.type,
|
|
37
|
+
state.key,
|
|
38
|
+
`Removing subscription "${key}"`,
|
|
39
|
+
)
|
|
40
|
+
unsubFunction()
|
|
41
|
+
for (const unsubFromDependency of dependencyUnsubFunctions) {
|
|
42
|
+
unsubFromDependency()
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return unsubscribe
|
|
47
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { TimelineToken, TimelineUpdate } from "atom.io"
|
|
2
|
+
import type { Store } from "atom.io/internal"
|
|
3
|
+
import { withdraw } from "atom.io/internal"
|
|
4
|
+
|
|
5
|
+
export const subscribeToTimeline = (
|
|
6
|
+
token: TimelineToken,
|
|
7
|
+
handleUpdate: (update: TimelineUpdate | `redo` | `undo`) => void,
|
|
8
|
+
key: string,
|
|
9
|
+
store: Store,
|
|
10
|
+
): (() => void) => {
|
|
11
|
+
const tl = withdraw(token, store)
|
|
12
|
+
if (tl === undefined) {
|
|
13
|
+
throw new Error(
|
|
14
|
+
`Cannot subscribe to timeline "${token.key}": timeline not found in store "${store.config.name}".`,
|
|
15
|
+
)
|
|
16
|
+
}
|
|
17
|
+
store.logger.info(`👀`, `timeline`, token.key, `Adding subscription "${key}"`)
|
|
18
|
+
const unsubscribe = tl.subject.subscribe(key, handleUpdate)
|
|
19
|
+
return () => {
|
|
20
|
+
store.logger.info(
|
|
21
|
+
`🙈`,
|
|
22
|
+
`timeline`,
|
|
23
|
+
token.key,
|
|
24
|
+
`Removing subscription "${key}" from timeline`,
|
|
25
|
+
)
|
|
26
|
+
unsubscribe()
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { TransactionToken, TransactionUpdateHandler, ƒn } from "atom.io"
|
|
2
|
+
import type { Store } from "atom.io/internal"
|
|
3
|
+
import { withdraw } from "atom.io/internal"
|
|
4
|
+
|
|
5
|
+
export const subscribeToTransaction = <ƒ extends ƒn>(
|
|
6
|
+
token: TransactionToken<ƒ>,
|
|
7
|
+
handleUpdate: TransactionUpdateHandler<ƒ>,
|
|
8
|
+
key: string,
|
|
9
|
+
store: Store,
|
|
10
|
+
): (() => void) => {
|
|
11
|
+
const tx = withdraw(token, store)
|
|
12
|
+
if (tx === undefined) {
|
|
13
|
+
throw new Error(
|
|
14
|
+
`Cannot subscribe to transaction "${token.key}": transaction not found in store "${store.config.name}".`,
|
|
15
|
+
)
|
|
16
|
+
}
|
|
17
|
+
store.logger.info(
|
|
18
|
+
`👀`,
|
|
19
|
+
`transaction`,
|
|
20
|
+
token.key,
|
|
21
|
+
`Adding subscription "${key}"`,
|
|
22
|
+
)
|
|
23
|
+
const unsubscribe = tx.subject.subscribe(key, handleUpdate)
|
|
24
|
+
return () => {
|
|
25
|
+
store.logger.info(
|
|
26
|
+
`🙈`,
|
|
27
|
+
`transaction`,
|
|
28
|
+
token.key,
|
|
29
|
+
`Removing subscription "${key}"`,
|
|
30
|
+
)
|
|
31
|
+
unsubscribe()
|
|
32
|
+
}
|
|
33
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "atom.io",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.14.0",
|
|
4
4
|
"description": "Composable and testable reactive data library.",
|
|
5
5
|
"homepage": "https://atom.io.fyi",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -54,17 +54,17 @@
|
|
|
54
54
|
"@types/npmlog": "7.0.0",
|
|
55
55
|
"@types/react": "18.2.42",
|
|
56
56
|
"@types/tmp": "0.2.6",
|
|
57
|
-
"@vitest/coverage-v8": "1.0.
|
|
57
|
+
"@vitest/coverage-v8": "1.0.2",
|
|
58
58
|
"concurrently": "8.2.2",
|
|
59
59
|
"drizzle-kit": "0.20.6",
|
|
60
60
|
"drizzle-orm": "0.29.1",
|
|
61
61
|
"eslint": "8.55.0",
|
|
62
|
-
"framer-motion": "10.16.
|
|
62
|
+
"framer-motion": "10.16.16",
|
|
63
63
|
"happy-dom": "12.10.3",
|
|
64
64
|
"http-proxy": "1.18.1",
|
|
65
65
|
"npmlog": "7.0.1",
|
|
66
66
|
"postgres": "3.4.3",
|
|
67
|
-
"preact": "10.19.
|
|
67
|
+
"preact": "10.19.3",
|
|
68
68
|
"react": "18.2.0",
|
|
69
69
|
"react-dom": "18.2.0",
|
|
70
70
|
"react-router-dom": "6.20.1",
|
|
@@ -72,10 +72,10 @@
|
|
|
72
72
|
"socket.io-client": "4.7.2",
|
|
73
73
|
"tmp": "0.2.1",
|
|
74
74
|
"tsup": "8.0.1",
|
|
75
|
-
"typescript": "5.3.
|
|
76
|
-
"vite": "5.0.
|
|
77
|
-
"vite-tsconfig-paths": "4.2.
|
|
78
|
-
"vitest": "1.0.
|
|
75
|
+
"typescript": "5.3.3",
|
|
76
|
+
"vite": "5.0.7",
|
|
77
|
+
"vite-tsconfig-paths": "4.2.2",
|
|
78
|
+
"vitest": "1.0.2"
|
|
79
79
|
},
|
|
80
80
|
"main": "dist/index.js",
|
|
81
81
|
"types": "dist/index.d.ts",
|
package/react/dist/index.cjs
CHANGED
|
@@ -40,7 +40,7 @@ function useO(token) {
|
|
|
40
40
|
const store = React2__namespace.useContext(StoreContext);
|
|
41
41
|
const id = React2__namespace.useId();
|
|
42
42
|
return React2__namespace.useSyncExternalStore(
|
|
43
|
-
(dispatch) =>
|
|
43
|
+
(dispatch) => internal.subscribeToState(token, dispatch, `use-o:${id}`, store),
|
|
44
44
|
() => atom_io.getState(token, store),
|
|
45
45
|
() => atom_io.getState(token, store)
|
|
46
46
|
);
|
|
@@ -49,11 +49,49 @@ function useJSON(token) {
|
|
|
49
49
|
const jsonToken = internal.getJsonToken(token);
|
|
50
50
|
return useO(jsonToken);
|
|
51
51
|
}
|
|
52
|
+
function useTL(token) {
|
|
53
|
+
const store = React2__namespace.useContext(StoreContext);
|
|
54
|
+
const id = React2__namespace.useId();
|
|
55
|
+
const timeline = internal.withdraw(token, store);
|
|
56
|
+
if (timeline === void 0) {
|
|
57
|
+
store.logger.error(
|
|
58
|
+
`\u274C`,
|
|
59
|
+
`timeline`,
|
|
60
|
+
token.key,
|
|
61
|
+
`Failed to use timeline because it does not exist`
|
|
62
|
+
);
|
|
63
|
+
return {
|
|
64
|
+
at: NaN,
|
|
65
|
+
length: NaN,
|
|
66
|
+
undo: () => {
|
|
67
|
+
},
|
|
68
|
+
redo: () => {
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
const meta = React2__namespace.useRef({
|
|
73
|
+
at: timeline.at,
|
|
74
|
+
length: timeline.history.length,
|
|
75
|
+
undo: () => atom_io.undo(token),
|
|
76
|
+
redo: () => atom_io.redo(token)
|
|
77
|
+
});
|
|
78
|
+
const retrieve = React2__namespace.useCallback(() => {
|
|
79
|
+
meta.current.at = timeline.at;
|
|
80
|
+
meta.current.length = timeline.history.length;
|
|
81
|
+
return meta.current;
|
|
82
|
+
}, [meta]);
|
|
83
|
+
return React2__namespace.useSyncExternalStore(
|
|
84
|
+
(dispatch) => internal.subscribeToTimeline(token, dispatch, `use-tl:${id}`, store),
|
|
85
|
+
retrieve,
|
|
86
|
+
retrieve
|
|
87
|
+
);
|
|
88
|
+
}
|
|
52
89
|
|
|
53
90
|
exports.StoreContext = StoreContext;
|
|
54
91
|
exports.StoreProvider = StoreProvider;
|
|
55
92
|
exports.useI = useI;
|
|
56
93
|
exports.useJSON = useJSON;
|
|
57
94
|
exports.useO = useO;
|
|
95
|
+
exports.useTL = useTL;
|
|
58
96
|
//# sourceMappingURL=out.js.map
|
|
59
97
|
//# sourceMappingURL=index.cjs.map
|
package/react/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/store-context.tsx","../src/store-hooks.ts"],"names":["React"],"mappings":";AACA,SAAS,gBAAgB;AACzB,YAAY,WAAW;AAQtB;AANM,IAAM,eAAqB,oBAAqB,SAAS,KAAK;AAE9D,IAAM,gBAGR,CAAC,EAAE,UAAU,QAAQ,SAAS,MAAM,MACxC,oBAAC,aAAa,UAAb,EAAsB,OAAO,OAAQ,UAAS;;;ACVhD,YAAYA,YAAW;AAEvB,SAAS,UAAU,UAAU,
|
|
1
|
+
{"version":3,"sources":["../src/store-context.tsx","../src/store-hooks.ts"],"names":["React"],"mappings":";AACA,SAAS,gBAAgB;AACzB,YAAY,WAAW;AAQtB;AANM,IAAM,eAAqB,oBAAqB,SAAS,KAAK;AAE9D,IAAM,gBAGR,CAAC,EAAE,UAAU,QAAQ,SAAS,MAAM,MACxC,oBAAC,aAAa,UAAb,EAAsB,OAAO,OAAQ,UAAS;;;ACVhD,YAAYA,YAAW;AAEvB,SAAS,UAAU,MAAM,UAAU,YAAY;AAQ/C;AAAA,EACC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACM;AAIA,SAAS,KACf,OACyD;AACzD,QAAM,QAAc,kBAAW,YAAY;AAC3C,QAAM,SAEI,cAAO,IAAI;AACrB,MAAI,OAAO,YAAY,MAAM;AAC5B,WAAO,UAAU,CAAC,SAAS,SAAS,OAAO,MAAM,KAAK;AAAA,EACvD;AACA,SAAO,OAAO;AACf;AAEO,SAAS,KAAQ,OAAoD;AAC3E,QAAM,QAAc,kBAAW,YAAY;AAC3C,QAAM,KAAW,aAAM;AACvB,SAAa;AAAA,IACZ,CAAC,aAAa,iBAAiB,OAAO,UAAU,SAAS,EAAE,IAAI,KAAK;AAAA,IACpE,MAAM,SAAS,OAAO,KAAK;AAAA,IAC3B,MAAM,SAAS,OAAO,KAAK;AAAA,EAC5B;AACD;AAEO,SAAS,QACf,OACe;AACf,QAAM,YAAY,aAAa,KAAK;AACpC,SAAO,KAAK,SAAS;AACtB;AASO,SAAS,MAAM,OAAoC;AACzD,QAAM,QAAc,kBAAW,YAAY;AAC3C,QAAM,KAAW,aAAM;AACvB,QAAM,WAAW,SAAS,OAAO,KAAK;AACtC,MAAI,aAAa,QAAW;AAC3B,UAAM,OAAO;AAAA,MACZ;AAAA,MACA;AAAA,MACA,MAAM;AAAA,MACN;AAAA,IACD;AACA,WAAO;AAAA,MACN,IAAI;AAAA,MACJ,QAAQ;AAAA,MACR,MAAM,MAAM;AAAA,MAAC;AAAA,MACb,MAAM,MAAM;AAAA,MAAC;AAAA,IACd;AAAA,EACD;AACA,QAAM,OAAa,cAAqB;AAAA,IACvC,IAAI,SAAS;AAAA,IACb,QAAQ,SAAS,QAAQ;AAAA,IACzB,MAAM,MAAM,KAAK,KAAK;AAAA,IACtB,MAAM,MAAM,KAAK,KAAK;AAAA,EACvB,CAAC;AACD,QAAM,WAAiB,mBAAY,MAAM;AACxC,SAAK,QAAQ,KAAK,SAAS;AAC3B,SAAK,QAAQ,SAAS,SAAS,QAAQ;AACvC,WAAO,KAAK;AAAA,EACb,GAAG,CAAC,IAAI,CAAC;AACT,SAAa;AAAA,IACZ,CAAC,aAAa,oBAAoB,OAAO,UAAU,UAAU,EAAE,IAAI,KAAK;AAAA,IACxE;AAAA,IACA;AAAA,EACD;AACD","sourcesContent":["import type { Store } from \"atom.io/internal\"\nimport { IMPLICIT } from \"atom.io/internal\"\nimport * as React from \"react\"\n\nexport const StoreContext = React.createContext<Store>(IMPLICIT.STORE)\n\nexport const StoreProvider: React.FC<{\n\tchildren: React.ReactNode\n\tstore?: Store\n}> = ({ children, store = IMPLICIT.STORE }) => (\n\t<StoreContext.Provider value={store}>{children}</StoreContext.Provider>\n)\n","import * as React from \"react\"\n\nimport { getState, redo, setState, undo } from \"atom.io\"\nimport type {\n\tMutableAtomToken,\n\tReadonlySelectorToken,\n\tStateToken,\n\tTimelineToken,\n} from \"atom.io\"\n\nimport {\n\tgetJsonToken,\n\tsubscribeToState,\n\tsubscribeToTimeline,\n\twithdraw,\n} from \"atom.io/internal\"\nimport type { Json } from \"atom.io/json\"\nimport { StoreContext } from \"./store-context\"\n\nexport function useI<T>(\n\ttoken: StateToken<T>,\n): <New extends T>(next: New | ((old: T) => New)) => void {\n\tconst store = React.useContext(StoreContext)\n\tconst setter: React.MutableRefObject<\n\t\t(<New extends T>(next: New | ((old: T) => New)) => void) | null\n\t> = React.useRef(null)\n\tif (setter.current === null) {\n\t\tsetter.current = (next) => setState(token, next, store)\n\t}\n\treturn setter.current\n}\n\nexport function useO<T>(token: ReadonlySelectorToken<T> | StateToken<T>): T {\n\tconst store = React.useContext(StoreContext)\n\tconst id = React.useId()\n\treturn React.useSyncExternalStore<T>(\n\t\t(dispatch) => subscribeToState(token, dispatch, `use-o:${id}`, store),\n\t\t() => getState(token, store),\n\t\t() => getState(token, store),\n\t)\n}\n\nexport function useJSON<Serializable extends Json.Serializable>(\n\ttoken: MutableAtomToken<any, Serializable>,\n): Serializable {\n\tconst jsonToken = getJsonToken(token)\n\treturn useO(jsonToken)\n}\n\nexport type TimelineMeta = {\n\tat: number\n\tlength: number\n\tundo: () => void\n\tredo: () => void\n}\n\nexport function useTL(token: TimelineToken): TimelineMeta {\n\tconst store = React.useContext(StoreContext)\n\tconst id = React.useId()\n\tconst timeline = withdraw(token, store)\n\tif (timeline === undefined) {\n\t\tstore.logger.error(\n\t\t\t`❌`,\n\t\t\t`timeline`,\n\t\t\ttoken.key,\n\t\t\t`Failed to use timeline because it does not exist`,\n\t\t)\n\t\treturn {\n\t\t\tat: NaN,\n\t\t\tlength: NaN,\n\t\t\tundo: () => {},\n\t\t\tredo: () => {},\n\t\t}\n\t}\n\tconst meta = React.useRef<TimelineMeta>({\n\t\tat: timeline.at,\n\t\tlength: timeline.history.length,\n\t\tundo: () => undo(token),\n\t\tredo: () => redo(token),\n\t})\n\tconst retrieve = React.useCallback(() => {\n\t\tmeta.current.at = timeline.at\n\t\tmeta.current.length = timeline.history.length\n\t\treturn meta.current\n\t}, [meta])\n\treturn React.useSyncExternalStore<TimelineMeta>(\n\t\t(dispatch) => subscribeToTimeline(token, dispatch, `use-tl:${id}`, store),\n\t\tretrieve,\n\t\tretrieve,\n\t)\n}\n"]}
|
package/react/dist/index.d.cts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Store } from 'atom.io/internal';
|
|
2
2
|
import * as React from 'react';
|
|
3
|
-
import { StateToken, ReadonlySelectorToken, MutableAtomToken } from 'atom.io';
|
|
3
|
+
import { StateToken, ReadonlySelectorToken, MutableAtomToken, TimelineToken } from 'atom.io';
|
|
4
4
|
import { Json } from 'atom.io/json';
|
|
5
5
|
|
|
6
6
|
declare const StoreContext: React.Context<Store>;
|
|
@@ -12,5 +12,12 @@ declare const StoreProvider: React.FC<{
|
|
|
12
12
|
declare function useI<T>(token: StateToken<T>): <New extends T>(next: New | ((old: T) => New)) => void;
|
|
13
13
|
declare function useO<T>(token: ReadonlySelectorToken<T> | StateToken<T>): T;
|
|
14
14
|
declare function useJSON<Serializable extends Json.Serializable>(token: MutableAtomToken<any, Serializable>): Serializable;
|
|
15
|
+
type TimelineMeta = {
|
|
16
|
+
at: number;
|
|
17
|
+
length: number;
|
|
18
|
+
undo: () => void;
|
|
19
|
+
redo: () => void;
|
|
20
|
+
};
|
|
21
|
+
declare function useTL(token: TimelineToken): TimelineMeta;
|
|
15
22
|
|
|
16
|
-
export { StoreContext, StoreProvider, useI, useJSON, useO };
|
|
23
|
+
export { StoreContext, StoreProvider, type TimelineMeta, useI, useJSON, useO, useTL };
|
package/react/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Store } from 'atom.io/internal';
|
|
2
2
|
import * as React from 'react';
|
|
3
|
-
import { StateToken, ReadonlySelectorToken, MutableAtomToken } from 'atom.io';
|
|
3
|
+
import { StateToken, ReadonlySelectorToken, MutableAtomToken, TimelineToken } from 'atom.io';
|
|
4
4
|
import { Json } from 'atom.io/json';
|
|
5
5
|
|
|
6
6
|
declare const StoreContext: React.Context<Store>;
|
|
@@ -12,5 +12,12 @@ declare const StoreProvider: React.FC<{
|
|
|
12
12
|
declare function useI<T>(token: StateToken<T>): <New extends T>(next: New | ((old: T) => New)) => void;
|
|
13
13
|
declare function useO<T>(token: ReadonlySelectorToken<T> | StateToken<T>): T;
|
|
14
14
|
declare function useJSON<Serializable extends Json.Serializable>(token: MutableAtomToken<any, Serializable>): Serializable;
|
|
15
|
+
type TimelineMeta = {
|
|
16
|
+
at: number;
|
|
17
|
+
length: number;
|
|
18
|
+
undo: () => void;
|
|
19
|
+
redo: () => void;
|
|
20
|
+
};
|
|
21
|
+
declare function useTL(token: TimelineToken): TimelineMeta;
|
|
15
22
|
|
|
16
|
-
export { StoreContext, StoreProvider, useI, useJSON, useO };
|
|
23
|
+
export { StoreContext, StoreProvider, type TimelineMeta, useI, useJSON, useO, useTL };
|
package/react/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { IMPLICIT, getJsonToken } from 'atom.io/internal';
|
|
1
|
+
import { IMPLICIT, subscribeToState, getJsonToken, withdraw, subscribeToTimeline } from 'atom.io/internal';
|
|
2
2
|
import * as React2 from 'react';
|
|
3
3
|
import { jsx } from 'react/jsx-runtime';
|
|
4
|
-
import { setState,
|
|
4
|
+
import { setState, getState, undo, redo } from 'atom.io';
|
|
5
5
|
|
|
6
6
|
// src/store-context.tsx
|
|
7
7
|
var StoreContext = React2.createContext(IMPLICIT.STORE);
|
|
@@ -18,7 +18,7 @@ function useO(token) {
|
|
|
18
18
|
const store = React2.useContext(StoreContext);
|
|
19
19
|
const id = React2.useId();
|
|
20
20
|
return React2.useSyncExternalStore(
|
|
21
|
-
(dispatch) =>
|
|
21
|
+
(dispatch) => subscribeToState(token, dispatch, `use-o:${id}`, store),
|
|
22
22
|
() => getState(token, store),
|
|
23
23
|
() => getState(token, store)
|
|
24
24
|
);
|
|
@@ -27,7 +27,44 @@ function useJSON(token) {
|
|
|
27
27
|
const jsonToken = getJsonToken(token);
|
|
28
28
|
return useO(jsonToken);
|
|
29
29
|
}
|
|
30
|
+
function useTL(token) {
|
|
31
|
+
const store = React2.useContext(StoreContext);
|
|
32
|
+
const id = React2.useId();
|
|
33
|
+
const timeline = withdraw(token, store);
|
|
34
|
+
if (timeline === void 0) {
|
|
35
|
+
store.logger.error(
|
|
36
|
+
`\u274C`,
|
|
37
|
+
`timeline`,
|
|
38
|
+
token.key,
|
|
39
|
+
`Failed to use timeline because it does not exist`
|
|
40
|
+
);
|
|
41
|
+
return {
|
|
42
|
+
at: NaN,
|
|
43
|
+
length: NaN,
|
|
44
|
+
undo: () => {
|
|
45
|
+
},
|
|
46
|
+
redo: () => {
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
const meta = React2.useRef({
|
|
51
|
+
at: timeline.at,
|
|
52
|
+
length: timeline.history.length,
|
|
53
|
+
undo: () => undo(token),
|
|
54
|
+
redo: () => redo(token)
|
|
55
|
+
});
|
|
56
|
+
const retrieve = React2.useCallback(() => {
|
|
57
|
+
meta.current.at = timeline.at;
|
|
58
|
+
meta.current.length = timeline.history.length;
|
|
59
|
+
return meta.current;
|
|
60
|
+
}, [meta]);
|
|
61
|
+
return React2.useSyncExternalStore(
|
|
62
|
+
(dispatch) => subscribeToTimeline(token, dispatch, `use-tl:${id}`, store),
|
|
63
|
+
retrieve,
|
|
64
|
+
retrieve
|
|
65
|
+
);
|
|
66
|
+
}
|
|
30
67
|
|
|
31
|
-
export { StoreContext, StoreProvider, useI, useJSON, useO };
|
|
68
|
+
export { StoreContext, StoreProvider, useI, useJSON, useO, useTL };
|
|
32
69
|
//# sourceMappingURL=out.js.map
|
|
33
70
|
//# sourceMappingURL=index.js.map
|
package/react/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/store-context.tsx","../src/store-hooks.ts"],"names":["React"],"mappings":";AACA,SAAS,gBAAgB;AACzB,YAAY,WAAW;AAQtB;AANM,IAAM,eAAqB,oBAAqB,SAAS,KAAK;AAE9D,IAAM,gBAGR,CAAC,EAAE,UAAU,QAAQ,SAAS,MAAM,MACxC,oBAAC,aAAa,UAAb,EAAsB,OAAO,OAAQ,UAAS;;;ACVhD,YAAYA,YAAW;AAEvB,SAAS,UAAU,UAAU,
|
|
1
|
+
{"version":3,"sources":["../src/store-context.tsx","../src/store-hooks.ts"],"names":["React"],"mappings":";AACA,SAAS,gBAAgB;AACzB,YAAY,WAAW;AAQtB;AANM,IAAM,eAAqB,oBAAqB,SAAS,KAAK;AAE9D,IAAM,gBAGR,CAAC,EAAE,UAAU,QAAQ,SAAS,MAAM,MACxC,oBAAC,aAAa,UAAb,EAAsB,OAAO,OAAQ,UAAS;;;ACVhD,YAAYA,YAAW;AAEvB,SAAS,UAAU,MAAM,UAAU,YAAY;AAQ/C;AAAA,EACC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACM;AAIA,SAAS,KACf,OACyD;AACzD,QAAM,QAAc,kBAAW,YAAY;AAC3C,QAAM,SAEI,cAAO,IAAI;AACrB,MAAI,OAAO,YAAY,MAAM;AAC5B,WAAO,UAAU,CAAC,SAAS,SAAS,OAAO,MAAM,KAAK;AAAA,EACvD;AACA,SAAO,OAAO;AACf;AAEO,SAAS,KAAQ,OAAoD;AAC3E,QAAM,QAAc,kBAAW,YAAY;AAC3C,QAAM,KAAW,aAAM;AACvB,SAAa;AAAA,IACZ,CAAC,aAAa,iBAAiB,OAAO,UAAU,SAAS,EAAE,IAAI,KAAK;AAAA,IACpE,MAAM,SAAS,OAAO,KAAK;AAAA,IAC3B,MAAM,SAAS,OAAO,KAAK;AAAA,EAC5B;AACD;AAEO,SAAS,QACf,OACe;AACf,QAAM,YAAY,aAAa,KAAK;AACpC,SAAO,KAAK,SAAS;AACtB;AASO,SAAS,MAAM,OAAoC;AACzD,QAAM,QAAc,kBAAW,YAAY;AAC3C,QAAM,KAAW,aAAM;AACvB,QAAM,WAAW,SAAS,OAAO,KAAK;AACtC,MAAI,aAAa,QAAW;AAC3B,UAAM,OAAO;AAAA,MACZ;AAAA,MACA;AAAA,MACA,MAAM;AAAA,MACN;AAAA,IACD;AACA,WAAO;AAAA,MACN,IAAI;AAAA,MACJ,QAAQ;AAAA,MACR,MAAM,MAAM;AAAA,MAAC;AAAA,MACb,MAAM,MAAM;AAAA,MAAC;AAAA,IACd;AAAA,EACD;AACA,QAAM,OAAa,cAAqB;AAAA,IACvC,IAAI,SAAS;AAAA,IACb,QAAQ,SAAS,QAAQ;AAAA,IACzB,MAAM,MAAM,KAAK,KAAK;AAAA,IACtB,MAAM,MAAM,KAAK,KAAK;AAAA,EACvB,CAAC;AACD,QAAM,WAAiB,mBAAY,MAAM;AACxC,SAAK,QAAQ,KAAK,SAAS;AAC3B,SAAK,QAAQ,SAAS,SAAS,QAAQ;AACvC,WAAO,KAAK;AAAA,EACb,GAAG,CAAC,IAAI,CAAC;AACT,SAAa;AAAA,IACZ,CAAC,aAAa,oBAAoB,OAAO,UAAU,UAAU,EAAE,IAAI,KAAK;AAAA,IACxE;AAAA,IACA;AAAA,EACD;AACD","sourcesContent":["import type { Store } from \"atom.io/internal\"\nimport { IMPLICIT } from \"atom.io/internal\"\nimport * as React from \"react\"\n\nexport const StoreContext = React.createContext<Store>(IMPLICIT.STORE)\n\nexport const StoreProvider: React.FC<{\n\tchildren: React.ReactNode\n\tstore?: Store\n}> = ({ children, store = IMPLICIT.STORE }) => (\n\t<StoreContext.Provider value={store}>{children}</StoreContext.Provider>\n)\n","import * as React from \"react\"\n\nimport { getState, redo, setState, undo } from \"atom.io\"\nimport type {\n\tMutableAtomToken,\n\tReadonlySelectorToken,\n\tStateToken,\n\tTimelineToken,\n} from \"atom.io\"\n\nimport {\n\tgetJsonToken,\n\tsubscribeToState,\n\tsubscribeToTimeline,\n\twithdraw,\n} from \"atom.io/internal\"\nimport type { Json } from \"atom.io/json\"\nimport { StoreContext } from \"./store-context\"\n\nexport function useI<T>(\n\ttoken: StateToken<T>,\n): <New extends T>(next: New | ((old: T) => New)) => void {\n\tconst store = React.useContext(StoreContext)\n\tconst setter: React.MutableRefObject<\n\t\t(<New extends T>(next: New | ((old: T) => New)) => void) | null\n\t> = React.useRef(null)\n\tif (setter.current === null) {\n\t\tsetter.current = (next) => setState(token, next, store)\n\t}\n\treturn setter.current\n}\n\nexport function useO<T>(token: ReadonlySelectorToken<T> | StateToken<T>): T {\n\tconst store = React.useContext(StoreContext)\n\tconst id = React.useId()\n\treturn React.useSyncExternalStore<T>(\n\t\t(dispatch) => subscribeToState(token, dispatch, `use-o:${id}`, store),\n\t\t() => getState(token, store),\n\t\t() => getState(token, store),\n\t)\n}\n\nexport function useJSON<Serializable extends Json.Serializable>(\n\ttoken: MutableAtomToken<any, Serializable>,\n): Serializable {\n\tconst jsonToken = getJsonToken(token)\n\treturn useO(jsonToken)\n}\n\nexport type TimelineMeta = {\n\tat: number\n\tlength: number\n\tundo: () => void\n\tredo: () => void\n}\n\nexport function useTL(token: TimelineToken): TimelineMeta {\n\tconst store = React.useContext(StoreContext)\n\tconst id = React.useId()\n\tconst timeline = withdraw(token, store)\n\tif (timeline === undefined) {\n\t\tstore.logger.error(\n\t\t\t`❌`,\n\t\t\t`timeline`,\n\t\t\ttoken.key,\n\t\t\t`Failed to use timeline because it does not exist`,\n\t\t)\n\t\treturn {\n\t\t\tat: NaN,\n\t\t\tlength: NaN,\n\t\t\tundo: () => {},\n\t\t\tredo: () => {},\n\t\t}\n\t}\n\tconst meta = React.useRef<TimelineMeta>({\n\t\tat: timeline.at,\n\t\tlength: timeline.history.length,\n\t\tundo: () => undo(token),\n\t\tredo: () => redo(token),\n\t})\n\tconst retrieve = React.useCallback(() => {\n\t\tmeta.current.at = timeline.at\n\t\tmeta.current.length = timeline.history.length\n\t\treturn meta.current\n\t}, [meta])\n\treturn React.useSyncExternalStore<TimelineMeta>(\n\t\t(dispatch) => subscribeToTimeline(token, dispatch, `use-tl:${id}`, store),\n\t\tretrieve,\n\t\tretrieve,\n\t)\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"inputs":{"src/store-context.tsx":{"bytes":399,"imports":[{"path":"atom.io/internal","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"react/jsx-runtime","kind":"import-statement","external":true}],"format":"esm"},"src/store-hooks.ts":{"bytes":
|
|
1
|
+
{"inputs":{"src/store-context.tsx":{"bytes":399,"imports":[{"path":"atom.io/internal","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"react/jsx-runtime","kind":"import-statement","external":true}],"format":"esm"},"src/store-hooks.ts":{"bytes":2285,"imports":[{"path":"react","kind":"import-statement","external":true},{"path":"atom.io","kind":"import-statement","external":true},{"path":"atom.io/internal","kind":"import-statement","external":true},{"path":"src/store-context.tsx","kind":"import-statement","original":"./store-context"}],"format":"esm"},"src/index.ts":{"bytes":62,"imports":[{"path":"src/store-context.tsx","kind":"import-statement","original":"./store-context"},{"path":"src/store-hooks.ts","kind":"import-statement","original":"./store-hooks"}],"format":"esm"}},"outputs":{"dist/index.cjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":4490},"dist/index.cjs":{"imports":[{"path":"atom.io/internal","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"react/jsx-runtime","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"atom.io","kind":"import-statement","external":true},{"path":"atom.io/internal","kind":"import-statement","external":true}],"exports":["StoreContext","StoreProvider","useI","useJSON","useO","useTL"],"entryPoint":"src/index.ts","inputs":{"src/store-context.tsx":{"bytesInOutput":308},"src/index.ts":{"bytesInOutput":0},"src/store-hooks.ts":{"bytesInOutput":1717}},"bytes":2153}}}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"inputs":{"src/store-context.tsx":{"bytes":399,"imports":[{"path":"atom.io/internal","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"react/jsx-runtime","kind":"import-statement","external":true}],"format":"esm"},"src/store-hooks.ts":{"bytes":
|
|
1
|
+
{"inputs":{"src/store-context.tsx":{"bytes":399,"imports":[{"path":"atom.io/internal","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"react/jsx-runtime","kind":"import-statement","external":true}],"format":"esm"},"src/store-hooks.ts":{"bytes":2285,"imports":[{"path":"react","kind":"import-statement","external":true},{"path":"atom.io","kind":"import-statement","external":true},{"path":"atom.io/internal","kind":"import-statement","external":true},{"path":"src/store-context.tsx","kind":"import-statement","original":"./store-context"}],"format":"esm"},"src/index.ts":{"bytes":62,"imports":[{"path":"src/store-context.tsx","kind":"import-statement","original":"./store-context"},{"path":"src/store-hooks.ts","kind":"import-statement","original":"./store-hooks"}],"format":"esm"}},"outputs":{"dist/index.js.map":{"imports":[],"exports":[],"inputs":{},"bytes":4490},"dist/index.js":{"imports":[{"path":"atom.io/internal","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"react/jsx-runtime","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"atom.io","kind":"import-statement","external":true},{"path":"atom.io/internal","kind":"import-statement","external":true}],"exports":["StoreContext","StoreProvider","useI","useJSON","useO","useTL"],"entryPoint":"src/index.ts","inputs":{"src/store-context.tsx":{"bytesInOutput":308},"src/index.ts":{"bytesInOutput":0},"src/store-hooks.ts":{"bytesInOutput":1717}},"bytes":2153}}}
|
package/react/src/store-hooks.ts
CHANGED
|
@@ -1,13 +1,19 @@
|
|
|
1
1
|
import * as React from "react"
|
|
2
2
|
|
|
3
|
-
import { getState, setState,
|
|
3
|
+
import { getState, redo, setState, undo } from "atom.io"
|
|
4
4
|
import type {
|
|
5
5
|
MutableAtomToken,
|
|
6
6
|
ReadonlySelectorToken,
|
|
7
7
|
StateToken,
|
|
8
|
+
TimelineToken,
|
|
8
9
|
} from "atom.io"
|
|
9
10
|
|
|
10
|
-
import {
|
|
11
|
+
import {
|
|
12
|
+
getJsonToken,
|
|
13
|
+
subscribeToState,
|
|
14
|
+
subscribeToTimeline,
|
|
15
|
+
withdraw,
|
|
16
|
+
} from "atom.io/internal"
|
|
11
17
|
import type { Json } from "atom.io/json"
|
|
12
18
|
import { StoreContext } from "./store-context"
|
|
13
19
|
|
|
@@ -28,7 +34,7 @@ export function useO<T>(token: ReadonlySelectorToken<T> | StateToken<T>): T {
|
|
|
28
34
|
const store = React.useContext(StoreContext)
|
|
29
35
|
const id = React.useId()
|
|
30
36
|
return React.useSyncExternalStore<T>(
|
|
31
|
-
(dispatch) =>
|
|
37
|
+
(dispatch) => subscribeToState(token, dispatch, `use-o:${id}`, store),
|
|
32
38
|
() => getState(token, store),
|
|
33
39
|
() => getState(token, store),
|
|
34
40
|
)
|
|
@@ -40,3 +46,46 @@ export function useJSON<Serializable extends Json.Serializable>(
|
|
|
40
46
|
const jsonToken = getJsonToken(token)
|
|
41
47
|
return useO(jsonToken)
|
|
42
48
|
}
|
|
49
|
+
|
|
50
|
+
export type TimelineMeta = {
|
|
51
|
+
at: number
|
|
52
|
+
length: number
|
|
53
|
+
undo: () => void
|
|
54
|
+
redo: () => void
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export function useTL(token: TimelineToken): TimelineMeta {
|
|
58
|
+
const store = React.useContext(StoreContext)
|
|
59
|
+
const id = React.useId()
|
|
60
|
+
const timeline = withdraw(token, store)
|
|
61
|
+
if (timeline === undefined) {
|
|
62
|
+
store.logger.error(
|
|
63
|
+
`❌`,
|
|
64
|
+
`timeline`,
|
|
65
|
+
token.key,
|
|
66
|
+
`Failed to use timeline because it does not exist`,
|
|
67
|
+
)
|
|
68
|
+
return {
|
|
69
|
+
at: NaN,
|
|
70
|
+
length: NaN,
|
|
71
|
+
undo: () => {},
|
|
72
|
+
redo: () => {},
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
const meta = React.useRef<TimelineMeta>({
|
|
76
|
+
at: timeline.at,
|
|
77
|
+
length: timeline.history.length,
|
|
78
|
+
undo: () => undo(token),
|
|
79
|
+
redo: () => redo(token),
|
|
80
|
+
})
|
|
81
|
+
const retrieve = React.useCallback(() => {
|
|
82
|
+
meta.current.at = timeline.at
|
|
83
|
+
meta.current.length = timeline.history.length
|
|
84
|
+
return meta.current
|
|
85
|
+
}, [meta])
|
|
86
|
+
return React.useSyncExternalStore<TimelineMeta>(
|
|
87
|
+
(dispatch) => subscribeToTimeline(token, dispatch, `use-tl:${id}`, store),
|
|
88
|
+
retrieve,
|
|
89
|
+
retrieve,
|
|
90
|
+
)
|
|
91
|
+
}
|