doxum 0.1.12 → 0.1.13

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 (64) hide show
  1. package/README.md +44 -39
  2. package/dist/advanced.cjs +116 -0
  3. package/dist/advanced.cjs.map +1 -0
  4. package/dist/advanced.d.cts +42 -0
  5. package/dist/advanced.d.ts +42 -0
  6. package/dist/advanced.js +115 -0
  7. package/dist/advanced.js.map +1 -0
  8. package/dist/{contract-CeAnEPBA.d.ts → contract-BT53Gg94.d.ts} +5 -4
  9. package/dist/{contract-DtGVSXSK.d.cts → contract-XmKnroJq.d.cts} +5 -4
  10. package/dist/definition-177L4Amk.cjs +898 -0
  11. package/dist/definition-177L4Amk.cjs.map +1 -0
  12. package/dist/definition-BlMeHwdz.d.ts +98 -0
  13. package/dist/definition-DXrKMVs7.js +785 -0
  14. package/dist/definition-DXrKMVs7.js.map +1 -0
  15. package/dist/definition-kxnWUvX9.d.cts +98 -0
  16. package/dist/{driver-xOIkwrB8.cjs → driver-BCyfqxsl.cjs} +1 -1
  17. package/dist/{driver-xOIkwrB8.cjs.map → driver-BCyfqxsl.cjs.map} +1 -1
  18. package/dist/{driver-BlR81Dqg.js → driver-CSnhMjbP.js} +1 -1
  19. package/dist/{driver-BlR81Dqg.js.map → driver-CSnhMjbP.js.map} +1 -1
  20. package/dist/index.cjs +31 -29
  21. package/dist/index.cjs.map +1 -1
  22. package/dist/index.d.cts +5 -4
  23. package/dist/index.d.ts +5 -4
  24. package/dist/index.js +7 -6
  25. package/dist/index.js.map +1 -1
  26. package/dist/{integration-CWjttg7H.js → integration-Bco8ZB16.js} +7 -3
  27. package/dist/integration-Bco8ZB16.js.map +1 -0
  28. package/dist/integration-CEUn96tx.cjs +52 -0
  29. package/dist/integration-CEUn96tx.cjs.map +1 -0
  30. package/dist/integration.cjs +7 -3
  31. package/dist/integration.d.cts +7 -3
  32. package/dist/integration.d.ts +7 -3
  33. package/dist/integration.js +3 -3
  34. package/dist/local-sync.cjs +1 -1
  35. package/dist/local-sync.d.cts +1 -1
  36. package/dist/local-sync.d.ts +1 -1
  37. package/dist/local-sync.js +1 -1
  38. package/dist/react.cjs +63 -36
  39. package/dist/react.cjs.map +1 -1
  40. package/dist/react.d.cts +8 -7
  41. package/dist/react.d.ts +8 -7
  42. package/dist/react.js +63 -35
  43. package/dist/react.js.map +1 -1
  44. package/dist/store-CDeqZEE3.d.cts +28 -0
  45. package/dist/{store-7XBEcR8s.js → store-CtgvCVFg.js} +585 -922
  46. package/dist/store-CtgvCVFg.js.map +1 -0
  47. package/dist/{store-DBv58dns.cjs → store-DcDpDgjk.cjs} +595 -992
  48. package/dist/store-DcDpDgjk.cjs.map +1 -0
  49. package/dist/store-P5dJ7TVe.d.ts +28 -0
  50. package/package.json +6 -1
  51. package/skills/doxum-runtime/SKILL.md +5 -7
  52. package/skills/doxum-runtime/references/guide.en.md +12 -16
  53. package/skills/doxum-runtime/references/guide.zh-CN.md +9 -14
  54. package/skills/doxum-runtime/references/patterns.en.md +12 -20
  55. package/skills/doxum-runtime/references/patterns.zh-CN.md +12 -18
  56. package/skills/doxum-runtime/references/projections.en.md +56 -199
  57. package/skills/doxum-runtime/references/projections.zh-CN.md +50 -180
  58. package/dist/integration-BShL68Nc.cjs +0 -30
  59. package/dist/integration-BShL68Nc.cjs.map +0 -1
  60. package/dist/integration-CWjttg7H.js.map +0 -1
  61. package/dist/store-2i8pYXqa.d.ts +0 -263
  62. package/dist/store-7XBEcR8s.js.map +0 -1
  63. package/dist/store-DBv58dns.cjs.map +0 -1
  64. package/dist/store-Ks80xWS_.d.cts +0 -263
package/dist/react.cjs CHANGED
@@ -1,48 +1,76 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_store = require("./store-DBv58dns.cjs");
3
- const require_integration = require("./integration-BShL68Nc.cjs");
2
+ const require_store = require("./store-DcDpDgjk.cjs");
3
+ const require_integration = require("./integration-CEUn96tx.cjs");
4
4
  let react = require("react");
5
5
  //#region react/src/hooks.ts
6
6
  const ProjectionContext = (0, react.createContext)(void 0);
7
7
  const ProjectionProvider = ProjectionContext.Provider;
8
- function useProjection(projection, store) {
9
- const context = (0, react.useContext)(ProjectionContext);
10
- const owner = store ?? context;
11
- if (!owner) throw new Error("ProjectionStore is required.");
12
- const read = (0, react.useCallback)(() => owner.get(projection), [owner, projection]);
13
- return (0, react.useSyncExternalStore)((0, react.useCallback)((listener) => owner.subscribe(projection, listener), [owner, projection]), read, read);
14
- }
15
- function useProjectionItem(projection, key, store) {
8
+ const sameProjectionSelection = (left, right) => {
9
+ if (left.all !== right.all || left.structure !== right.structure || left.keys.size !== right.keys.size) return false;
10
+ for (const key of left.keys) if (!right.keys.has(key)) return false;
11
+ return true;
12
+ };
13
+ function useProjection(projection, selectorOrRuntime, equalityOrRuntime, suppliedRuntime) {
16
14
  const context = (0, react.useContext)(ProjectionContext);
17
- const owner = store ?? context;
18
- if (!owner) throw new Error("ProjectionStore is required.");
19
- const item = (0, react.useMemo)(() => owner.item(projection, key), [
20
- key,
15
+ const selector = typeof selectorOrRuntime === "function" ? selectorOrRuntime : void 0;
16
+ const equality = typeof equalityOrRuntime === "function" ? equalityOrRuntime : Object.is;
17
+ const owner = (selector ? suppliedRuntime : void 0) ?? (selector ? equalityOrRuntime && typeof equalityOrRuntime !== "function" ? equalityOrRuntime : void 0 : void 0) ?? (selector ? context : typeof selectorOrRuntime === "object" ? selectorOrRuntime : context);
18
+ if (!owner) throw new Error("ProjectionRuntime is required.");
19
+ if (!selector) {
20
+ const read = (0, react.useCallback)(() => owner.get(projection), [owner, projection]);
21
+ return (0, react.useSyncExternalStore)((0, react.useCallback)((listener) => owner.subscribe(projection, listener), [owner, projection]), read, read);
22
+ }
23
+ const cache = (0, react.useRef)(void 0);
24
+ const read = (0, react.useCallback)(() => {
25
+ const selected = require_store.trackProjection(owner, projection, selector);
26
+ const previous = cache.current;
27
+ const value = previous && equality(previous.value, selected.value) ? previous.value : selected.value;
28
+ cache.current = {
29
+ value,
30
+ selection: selected.selection
31
+ };
32
+ return value;
33
+ }, [
34
+ equality,
21
35
  owner,
22
- projection
36
+ projection,
37
+ selector
23
38
  ]);
24
- const read = (0, react.useMemo)(() => {
25
- let previousRevision = -1;
26
- let snapshot;
27
- return () => {
28
- const value = item.current();
29
- const revision = item.revision();
30
- if (snapshot && revision === previousRevision) return snapshot;
31
- previousRevision = revision;
32
- snapshot = {
33
- value,
34
- revision
35
- };
36
- return snapshot;
39
+ return (0, react.useSyncExternalStore)((0, react.useCallback)((listener) => {
40
+ read();
41
+ let selection = cache.current?.selection ?? {
42
+ keys: /* @__PURE__ */ new Set(),
43
+ all: true,
44
+ structure: false
37
45
  };
38
- }, [item]);
39
- return (0, react.useSyncExternalStore)((0, react.useCallback)((listener) => item.subscribe(listener), [item]), read, read).value;
46
+ let unsubscribe = require_store.subscribeProjection(owner, projection, selection, onInvalidate);
47
+ const reinstall = (next) => {
48
+ if (sameProjectionSelection(selection, next)) return;
49
+ unsubscribe();
50
+ selection = next;
51
+ unsubscribe = require_store.subscribeProjection(owner, projection, selection, onInvalidate);
52
+ };
53
+ function onInvalidate() {
54
+ const previous = cache.current?.value;
55
+ const next = read();
56
+ const nextSelection = cache.current?.selection;
57
+ if (nextSelection) reinstall(nextSelection);
58
+ if (!Object.is(previous, next)) listener();
59
+ }
60
+ return () => unsubscribe();
61
+ }, [
62
+ owner,
63
+ projection,
64
+ read
65
+ ]), read, read);
40
66
  }
41
- function useSetProjection(projection, store) {
67
+ function useInput(input, runtime) {
42
68
  const context = (0, react.useContext)(ProjectionContext);
43
- const owner = store ?? context;
44
- if (!owner) throw new Error("ProjectionStore is required.");
45
- return (0, react.useCallback)((value) => owner.set(projection, value), [owner, projection]);
69
+ const owner = runtime ?? context;
70
+ if (!owner) throw new Error("ProjectionRuntime is required.");
71
+ const value = useProjection(input, owner);
72
+ const set = (0, react.useCallback)((next) => owner.set(input, next), [input, owner]);
73
+ return (0, react.useMemo)(() => [value, set], [set, value]);
46
74
  }
47
75
  const objectIs = (previous, next) => Object.is(previous, next);
48
76
  const sameTargets = (left, right) => {
@@ -145,9 +173,8 @@ exports.ProjectionContext = ProjectionContext;
145
173
  exports.ProjectionProvider = ProjectionProvider;
146
174
  exports.useDocumentSelector = useDocumentSelector;
147
175
  exports.useHistory = useHistory;
176
+ exports.useInput = useInput;
148
177
  exports.useProjection = useProjection;
149
- exports.useProjectionItem = useProjectionItem;
150
178
  exports.useReadable = useReadable;
151
- exports.useSetProjection = useSetProjection;
152
179
 
153
180
  //# sourceMappingURL=react.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"react.cjs","names":["sameTarget","track","subscribeDependencies"],"sources":["../react/src/hooks.ts"],"sourcesContent":["import type {\n DocumentReadable,\n ObjectNode,\n DocumentSelector,\n HistoryState,\n LocalHistory,\n OperationResult,\n Readable,\n ProjectionStore,\n CollectionProjection,\n ValueProjection,\n InputProjection,\n} from 'doxum';\nimport { track, subscribeDependencies, sameTarget, type ImpactTarget } from 'doxum/integration';\nimport {\n createContext,\n useCallback,\n useContext,\n useMemo,\n useRef,\n useSyncExternalStore,\n} from 'react';\n\nexport const ProjectionContext = createContext<ProjectionStore | undefined>(undefined);\nexport const ProjectionProvider = ProjectionContext.Provider;\n\nexport function useProjection<T>(projection: ValueProjection<T>, store?: ProjectionStore): T {\n const context = useContext(ProjectionContext);\n const owner = store ?? context;\n if (!owner) throw new Error('ProjectionStore is required.');\n const read = useCallback(() => owner.get(projection), [owner, projection]);\n const subscribe = useCallback(\n (listener: () => void) => owner.subscribe(projection, listener),\n [owner, projection]\n );\n return useSyncExternalStore(subscribe, read, read);\n}\n\ntype ProjectionItemSnapshot<T> = {\n readonly value: T | undefined;\n readonly revision: number;\n};\n\nexport function useProjectionItem<K extends string, V>(\n projection: CollectionProjection<K, V>,\n key: K,\n store?: ProjectionStore\n): V | undefined {\n const context = useContext(ProjectionContext);\n const owner = store ?? context;\n if (!owner) throw new Error('ProjectionStore is required.');\n const item = useMemo(() => owner.item(projection, key), [key, owner, projection]);\n const read = useMemo(() => {\n let previousRevision = -1;\n let snapshot: ProjectionItemSnapshot<V> | undefined;\n return (): ProjectionItemSnapshot<V> => {\n const value = item.current();\n const revision = item.revision();\n if (snapshot && revision === previousRevision) return snapshot;\n previousRevision = revision;\n snapshot = { value, revision };\n return snapshot;\n };\n }, [item]);\n const subscribe = useCallback((listener: () => void) => item.subscribe(listener), [item]);\n return useSyncExternalStore(subscribe, read, read).value;\n}\n\nexport function useSetProjection<T>(\n projection: InputProjection<T>,\n store?: ProjectionStore\n): (value: T) => void {\n const context = useContext(ProjectionContext);\n const owner = store ?? context;\n if (!owner) throw new Error('ProjectionStore is required.');\n return useCallback((value: T) => owner.set(projection, value), [owner, projection]);\n}\n\nexport type DocumentSelectorOptions<TResult> = {\n readonly isEqual?: (previous: TResult, next: TResult) => boolean;\n readonly server?: () => TResult;\n};\n\ntype SelectorCache<TSchema extends ObjectNode, TResult> = {\n readonly runtime: DocumentReadable<TSchema>;\n readonly value: TResult;\n readonly targets: readonly ImpactTarget<unknown>[];\n};\n\nconst objectIs = <T>(previous: T, next: T): boolean => Object.is(previous, next);\nconst sameTargets = (\n left: readonly ImpactTarget<unknown>[],\n right: readonly ImpactTarget<unknown>[]\n): boolean => {\n if (left.length !== right.length) return false;\n for (let index = 0; index < left.length; index += 1)\n if (!sameTarget(left[index], right[index])) return false;\n return true;\n};\n\nexport function useDocumentSelector<TSchema extends ObjectNode, TResult>(\n runtime: DocumentReadable<TSchema>,\n selector: DocumentSelector<TSchema, TResult>,\n options?: DocumentSelectorOptions<TResult>\n): TResult {\n const equality = options?.isEqual ?? objectIs;\n const cache = useRef<SelectorCache<TSchema, TResult> | undefined>(undefined);\n const serverCache = useRef<\n | {\n readonly runtime: DocumentReadable<TSchema>;\n readonly selector: DocumentSelector<TSchema, TResult>;\n readonly source: (() => TResult) | undefined;\n readonly value: TResult;\n }\n | undefined\n >(undefined);\n\n const read = useMemo(() => {\n // Each selector closure owns its revision cache, including inline selectors\n // that allocate arrays or objects. Equality only compares distinct snapshots.\n let snapshot: { readonly revision: number; readonly value: TResult } | undefined;\n return (): TResult => {\n const revision = runtime.revision();\n if (snapshot?.revision === revision) return snapshot.value;\n const selection = track(runtime, selector);\n const previous = cache.current;\n const value =\n previous && previous.runtime === runtime && equality(previous.value, selection.value)\n ? previous.value\n : selection.value;\n cache.current = { runtime, value, targets: selection.targets };\n snapshot = { revision, value };\n return value;\n };\n }, [equality, runtime, selector]);\n\n const subscribe = useCallback(\n (listener: () => void) => {\n read();\n let targets = cache.current?.targets ?? [];\n let unsubscribe: () => void = () => undefined;\n const install = () => {\n if (targets.length === 0) return () => undefined;\n return subscribeDependencies(runtime, targets, onCommit);\n };\n const onCommit = () => {\n const previous = cache.current;\n const next = read();\n const nextTargets = cache.current?.targets ?? [];\n if (!sameTargets(targets, nextTargets)) {\n unsubscribe();\n targets = nextTargets;\n unsubscribe = install();\n }\n if (previous && !Object.is(previous.value, next)) listener();\n };\n unsubscribe = install();\n return () => unsubscribe();\n },\n [read, runtime]\n );\n\n const server = options?.server;\n const readServer = useCallback((): TResult => {\n const previous = serverCache.current;\n if (\n previous &&\n previous.source === server &&\n previous.runtime === runtime &&\n previous.selector === selector\n )\n return previous.value;\n const value = server ? server() : read();\n serverCache.current = { runtime, selector, source: server, value };\n return value;\n }, [read, server, runtime, selector]);\n\n return useSyncExternalStore(subscribe, read, readServer);\n}\n\nexport function useReadable<T>(readable: Readable<T>): T {\n const subscribe = useCallback((listener: () => void) => readable.subscribe(listener), [readable]);\n const read = useCallback(() => readable.current(), [readable]);\n return useSyncExternalStore(subscribe, read, read);\n}\n\nexport function useHistory<TCommit>(history: LocalHistory<TCommit>): HistoryState & {\n undo(): OperationResult<TCommit>;\n redo(): OperationResult<TCommit>;\n} {\n const subscribe = useCallback((listener: () => void) => history.subscribe(listener), [history]);\n const read = useCallback(() => history.current(), [history]);\n const state = useSyncExternalStore(subscribe, read, read);\n const undo = useCallback(() => history.undo(), [history]);\n const redo = useCallback(() => history.redo(), [history]);\n\n return useMemo(() => ({ ...state, undo, redo }), [redo, state, undo]);\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"react.cjs","names":["trackProjection","subscribeProjection","sameTarget","track","subscribeDependencies"],"sources":["../react/src/hooks.ts"],"sourcesContent":["import type {\n DocumentReadable,\n ObjectNode,\n DocumentSelector,\n HistoryState,\n LocalHistory,\n OperationResult,\n Readable,\n ProjectionRuntime,\n Projection,\n Input,\n} from 'doxum';\nimport {\n track,\n subscribeDependencies,\n sameTarget,\n type ImpactTarget,\n trackProjection,\n subscribeProjection,\n type ProjectionSelection,\n} from 'doxum/integration';\nimport {\n createContext,\n useCallback,\n useContext,\n useMemo,\n useRef,\n useSyncExternalStore,\n} from 'react';\n\nexport const ProjectionContext = createContext<ProjectionRuntime | undefined>(undefined);\nexport const ProjectionProvider = ProjectionContext.Provider;\n\nconst sameProjectionSelection = (\n left: ProjectionSelection,\n right: ProjectionSelection\n): boolean => {\n if (\n left.all !== right.all ||\n left.structure !== right.structure ||\n left.keys.size !== right.keys.size\n )\n return false;\n for (const key of left.keys) if (!right.keys.has(key)) return false;\n return true;\n};\n\nexport function useProjection<T>(projection: Projection<T>, runtime?: ProjectionRuntime): T;\nexport function useProjection<T, R>(\n projection: Projection<T>,\n selector: (value: T) => R,\n runtime?: ProjectionRuntime\n): R;\nexport function useProjection<T, R>(\n projection: Projection<T>,\n selector: (value: T) => R,\n equality?: (previous: R, next: R) => boolean,\n runtime?: ProjectionRuntime\n): R;\nexport function useProjection<T, R>(\n projection: Projection<T>,\n selectorOrRuntime?: ((value: T) => R) | ProjectionRuntime,\n equalityOrRuntime?: ((previous: R, next: R) => boolean) | ProjectionRuntime,\n suppliedRuntime?: ProjectionRuntime\n): T | R {\n const context = useContext(ProjectionContext);\n const selector = typeof selectorOrRuntime === 'function' ? selectorOrRuntime : undefined;\n const equality = typeof equalityOrRuntime === 'function' ? equalityOrRuntime : Object.is;\n const owner =\n (selector ? suppliedRuntime : undefined) ??\n (selector\n ? equalityOrRuntime && typeof equalityOrRuntime !== 'function'\n ? equalityOrRuntime\n : undefined\n : undefined) ??\n (selector ? context : typeof selectorOrRuntime === 'object' ? selectorOrRuntime : context);\n if (!owner) throw new Error('ProjectionRuntime is required.');\n if (!selector) {\n const read = useCallback(() => owner.get(projection), [owner, projection]);\n const subscribe = useCallback(\n (listener: () => void) => owner.subscribe(projection, listener),\n [owner, projection]\n );\n return useSyncExternalStore(subscribe, read, read) as T;\n }\n const cache = useRef<{ value: R; selection: ProjectionSelection } | undefined>(undefined);\n const read = useCallback(() => {\n const selected = trackProjection(owner, projection, selector);\n const previous = cache.current;\n const value =\n previous && equality(previous.value, selected.value) ? previous.value : selected.value;\n cache.current = { value, selection: selected.selection };\n return value;\n }, [equality, owner, projection, selector]);\n const subscribe = useCallback(\n (listener: () => void) => {\n read();\n let selection = cache.current?.selection ?? {\n keys: new Set<string>(),\n all: true,\n structure: false,\n };\n let unsubscribe = subscribeProjection(owner, projection, selection, onInvalidate);\n const reinstall = (next: ProjectionSelection) => {\n if (sameProjectionSelection(selection, next)) return;\n unsubscribe();\n selection = next;\n unsubscribe = subscribeProjection(owner, projection, selection, onInvalidate);\n };\n function onInvalidate() {\n const previous = cache.current?.value;\n const next = read();\n const nextSelection = cache.current?.selection;\n if (nextSelection) reinstall(nextSelection);\n if (!Object.is(previous, next)) listener();\n }\n return () => unsubscribe();\n },\n [owner, projection, read]\n );\n return useSyncExternalStore(subscribe, read, read);\n}\n\nexport function useInput<T>(\n input: Input<T>,\n runtime?: ProjectionRuntime\n): readonly [T, (value: T) => void] {\n const context = useContext(ProjectionContext);\n const owner = runtime ?? context;\n if (!owner) throw new Error('ProjectionRuntime is required.');\n const value = useProjection(input, owner);\n const set = useCallback((next: T) => owner.set(input, next), [input, owner]);\n return useMemo(() => [value, set] as const, [set, value]);\n}\n\nexport type DocumentSelectorOptions<TResult> = {\n readonly isEqual?: (previous: TResult, next: TResult) => boolean;\n readonly server?: () => TResult;\n};\n\ntype SelectorCache<TSchema extends ObjectNode, TResult> = {\n readonly runtime: DocumentReadable<TSchema>;\n readonly value: TResult;\n readonly targets: readonly ImpactTarget<unknown>[];\n};\n\nconst objectIs = <T>(previous: T, next: T): boolean => Object.is(previous, next);\nconst sameTargets = (\n left: readonly ImpactTarget<unknown>[],\n right: readonly ImpactTarget<unknown>[]\n): boolean => {\n if (left.length !== right.length) return false;\n for (let index = 0; index < left.length; index += 1)\n if (!sameTarget(left[index], right[index])) return false;\n return true;\n};\n\nexport function useDocumentSelector<TSchema extends ObjectNode, TResult>(\n runtime: DocumentReadable<TSchema>,\n selector: DocumentSelector<TSchema, TResult>,\n options?: DocumentSelectorOptions<TResult>\n): TResult {\n const equality = options?.isEqual ?? objectIs;\n const cache = useRef<SelectorCache<TSchema, TResult> | undefined>(undefined);\n const serverCache = useRef<\n | {\n readonly runtime: DocumentReadable<TSchema>;\n readonly selector: DocumentSelector<TSchema, TResult>;\n readonly source: (() => TResult) | undefined;\n readonly value: TResult;\n }\n | undefined\n >(undefined);\n\n const read = useMemo(() => {\n // Each selector closure owns its revision cache, including inline selectors\n // that allocate arrays or objects. Equality only compares distinct snapshots.\n let snapshot: { readonly revision: number; readonly value: TResult } | undefined;\n return (): TResult => {\n const revision = runtime.revision();\n if (snapshot?.revision === revision) return snapshot.value;\n const selection = track(runtime, selector);\n const previous = cache.current;\n const value =\n previous && previous.runtime === runtime && equality(previous.value, selection.value)\n ? previous.value\n : selection.value;\n cache.current = { runtime, value, targets: selection.targets };\n snapshot = { revision, value };\n return value;\n };\n }, [equality, runtime, selector]);\n\n const subscribe = useCallback(\n (listener: () => void) => {\n read();\n let targets = cache.current?.targets ?? [];\n let unsubscribe: () => void = () => undefined;\n const install = () => {\n if (targets.length === 0) return () => undefined;\n return subscribeDependencies(runtime, targets, onCommit);\n };\n const onCommit = () => {\n const previous = cache.current;\n const next = read();\n const nextTargets = cache.current?.targets ?? [];\n if (!sameTargets(targets, nextTargets)) {\n unsubscribe();\n targets = nextTargets;\n unsubscribe = install();\n }\n if (previous && !Object.is(previous.value, next)) listener();\n };\n unsubscribe = install();\n return () => unsubscribe();\n },\n [read, runtime]\n );\n\n const server = options?.server;\n const readServer = useCallback((): TResult => {\n const previous = serverCache.current;\n if (\n previous &&\n previous.source === server &&\n previous.runtime === runtime &&\n previous.selector === selector\n )\n return previous.value;\n const value = server ? server() : read();\n serverCache.current = { runtime, selector, source: server, value };\n return value;\n }, [read, server, runtime, selector]);\n\n return useSyncExternalStore(subscribe, read, readServer);\n}\n\nexport function useReadable<T>(readable: Readable<T>): T {\n const subscribe = useCallback((listener: () => void) => readable.subscribe(listener), [readable]);\n const read = useCallback(() => readable.current(), [readable]);\n return useSyncExternalStore(subscribe, read, read);\n}\n\nexport function useHistory<TCommit>(history: LocalHistory<TCommit>): HistoryState & {\n undo(): OperationResult<TCommit>;\n redo(): OperationResult<TCommit>;\n} {\n const subscribe = useCallback((listener: () => void) => history.subscribe(listener), [history]);\n const read = useCallback(() => history.current(), [history]);\n const state = useSyncExternalStore(subscribe, read, read);\n const undo = useCallback(() => history.undo(), [history]);\n const redo = useCallback(() => history.redo(), [history]);\n\n return useMemo(() => ({ ...state, undo, redo }), [redo, state, undo]);\n}\n"],"mappings":"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"}
package/dist/react.d.cts CHANGED
@@ -1,12 +1,13 @@
1
1
  import * as _$react from "react";
2
- import { CollectionProjection, DocumentReadable, DocumentSelector, HistoryState, InputProjection, LocalHistory, ObjectNode, OperationResult, ProjectionStore, Readable, ValueProjection } from "doxum";
2
+ import { DocumentReadable, DocumentSelector, HistoryState, Input, LocalHistory, ObjectNode, OperationResult, Projection, ProjectionRuntime, Readable } from "doxum";
3
3
 
4
4
  //#region react/src/hooks.d.ts
5
- declare const ProjectionContext: _$react.Context<ProjectionStore | undefined>;
6
- declare const ProjectionProvider: _$react.Provider<ProjectionStore | undefined>;
7
- declare function useProjection<T>(projection: ValueProjection<T>, store?: ProjectionStore): T;
8
- declare function useProjectionItem<K extends string, V>(projection: CollectionProjection<K, V>, key: K, store?: ProjectionStore): V | undefined;
9
- declare function useSetProjection<T>(projection: InputProjection<T>, store?: ProjectionStore): (value: T) => void;
5
+ declare const ProjectionContext: _$react.Context<ProjectionRuntime | undefined>;
6
+ declare const ProjectionProvider: _$react.Provider<ProjectionRuntime | undefined>;
7
+ declare function useProjection<T>(projection: Projection<T>, runtime?: ProjectionRuntime): T;
8
+ declare function useProjection<T, R>(projection: Projection<T>, selector: (value: T) => R, runtime?: ProjectionRuntime): R;
9
+ declare function useProjection<T, R>(projection: Projection<T>, selector: (value: T) => R, equality?: (previous: R, next: R) => boolean, runtime?: ProjectionRuntime): R;
10
+ declare function useInput<T>(input: Input<T>, runtime?: ProjectionRuntime): readonly [T, (value: T) => void];
10
11
  type DocumentSelectorOptions<TResult> = {
11
12
  readonly isEqual?: (previous: TResult, next: TResult) => boolean;
12
13
  readonly server?: () => TResult;
@@ -18,5 +19,5 @@ declare function useHistory<TCommit>(history: LocalHistory<TCommit>): HistorySta
18
19
  redo(): OperationResult<TCommit>;
19
20
  };
20
21
  //#endregion
21
- export { type DocumentSelectorOptions, ProjectionContext, ProjectionProvider, useDocumentSelector, useHistory, useProjection, useProjectionItem, useReadable, useSetProjection };
22
+ export { type DocumentSelectorOptions, ProjectionContext, ProjectionProvider, useDocumentSelector, useHistory, useInput, useProjection, useReadable };
22
23
  //# sourceMappingURL=react.d.cts.map
package/dist/react.d.ts CHANGED
@@ -1,12 +1,13 @@
1
1
  import * as _$react from "react";
2
- import { CollectionProjection, DocumentReadable, DocumentSelector, HistoryState, InputProjection, LocalHistory, ObjectNode, OperationResult, ProjectionStore, Readable, ValueProjection } from "doxum";
2
+ import { DocumentReadable, DocumentSelector, HistoryState, Input, LocalHistory, ObjectNode, OperationResult, Projection, ProjectionRuntime, Readable } from "doxum";
3
3
 
4
4
  //#region react/src/hooks.d.ts
5
- declare const ProjectionContext: _$react.Context<ProjectionStore | undefined>;
6
- declare const ProjectionProvider: _$react.Provider<ProjectionStore | undefined>;
7
- declare function useProjection<T>(projection: ValueProjection<T>, store?: ProjectionStore): T;
8
- declare function useProjectionItem<K extends string, V>(projection: CollectionProjection<K, V>, key: K, store?: ProjectionStore): V | undefined;
9
- declare function useSetProjection<T>(projection: InputProjection<T>, store?: ProjectionStore): (value: T) => void;
5
+ declare const ProjectionContext: _$react.Context<ProjectionRuntime | undefined>;
6
+ declare const ProjectionProvider: _$react.Provider<ProjectionRuntime | undefined>;
7
+ declare function useProjection<T>(projection: Projection<T>, runtime?: ProjectionRuntime): T;
8
+ declare function useProjection<T, R>(projection: Projection<T>, selector: (value: T) => R, runtime?: ProjectionRuntime): R;
9
+ declare function useProjection<T, R>(projection: Projection<T>, selector: (value: T) => R, equality?: (previous: R, next: R) => boolean, runtime?: ProjectionRuntime): R;
10
+ declare function useInput<T>(input: Input<T>, runtime?: ProjectionRuntime): readonly [T, (value: T) => void];
10
11
  type DocumentSelectorOptions<TResult> = {
11
12
  readonly isEqual?: (previous: TResult, next: TResult) => boolean;
12
13
  readonly server?: () => TResult;
@@ -18,5 +19,5 @@ declare function useHistory<TCommit>(history: LocalHistory<TCommit>): HistorySta
18
19
  redo(): OperationResult<TCommit>;
19
20
  };
20
21
  //#endregion
21
- export { type DocumentSelectorOptions, ProjectionContext, ProjectionProvider, useDocumentSelector, useHistory, useProjection, useProjectionItem, useReadable, useSetProjection };
22
+ export { type DocumentSelectorOptions, ProjectionContext, ProjectionProvider, useDocumentSelector, useHistory, useInput, useProjection, useReadable };
22
23
  //# sourceMappingURL=react.d.ts.map
package/dist/react.js CHANGED
@@ -1,47 +1,75 @@
1
- import { S as same, f as subscribeDependencies } from "./store-7XBEcR8s.js";
2
- import { t as track } from "./integration-CWjttg7H.js";
1
+ import { d as subscribeDependencies, n as subscribeProjection, r as trackProjection, x as same } from "./store-CtgvCVFg.js";
2
+ import { i as track } from "./integration-Bco8ZB16.js";
3
3
  import { createContext, useCallback, useContext, useMemo, useRef, useSyncExternalStore } from "react";
4
4
  //#region react/src/hooks.ts
5
5
  const ProjectionContext = createContext(void 0);
6
6
  const ProjectionProvider = ProjectionContext.Provider;
7
- function useProjection(projection, store) {
8
- const context = useContext(ProjectionContext);
9
- const owner = store ?? context;
10
- if (!owner) throw new Error("ProjectionStore is required.");
11
- const read = useCallback(() => owner.get(projection), [owner, projection]);
12
- return useSyncExternalStore(useCallback((listener) => owner.subscribe(projection, listener), [owner, projection]), read, read);
13
- }
14
- function useProjectionItem(projection, key, store) {
7
+ const sameProjectionSelection = (left, right) => {
8
+ if (left.all !== right.all || left.structure !== right.structure || left.keys.size !== right.keys.size) return false;
9
+ for (const key of left.keys) if (!right.keys.has(key)) return false;
10
+ return true;
11
+ };
12
+ function useProjection(projection, selectorOrRuntime, equalityOrRuntime, suppliedRuntime) {
15
13
  const context = useContext(ProjectionContext);
16
- const owner = store ?? context;
17
- if (!owner) throw new Error("ProjectionStore is required.");
18
- const item = useMemo(() => owner.item(projection, key), [
19
- key,
14
+ const selector = typeof selectorOrRuntime === "function" ? selectorOrRuntime : void 0;
15
+ const equality = typeof equalityOrRuntime === "function" ? equalityOrRuntime : Object.is;
16
+ const owner = (selector ? suppliedRuntime : void 0) ?? (selector ? equalityOrRuntime && typeof equalityOrRuntime !== "function" ? equalityOrRuntime : void 0 : void 0) ?? (selector ? context : typeof selectorOrRuntime === "object" ? selectorOrRuntime : context);
17
+ if (!owner) throw new Error("ProjectionRuntime is required.");
18
+ if (!selector) {
19
+ const read = useCallback(() => owner.get(projection), [owner, projection]);
20
+ return useSyncExternalStore(useCallback((listener) => owner.subscribe(projection, listener), [owner, projection]), read, read);
21
+ }
22
+ const cache = useRef(void 0);
23
+ const read = useCallback(() => {
24
+ const selected = trackProjection(owner, projection, selector);
25
+ const previous = cache.current;
26
+ const value = previous && equality(previous.value, selected.value) ? previous.value : selected.value;
27
+ cache.current = {
28
+ value,
29
+ selection: selected.selection
30
+ };
31
+ return value;
32
+ }, [
33
+ equality,
20
34
  owner,
21
- projection
35
+ projection,
36
+ selector
22
37
  ]);
23
- const read = useMemo(() => {
24
- let previousRevision = -1;
25
- let snapshot;
26
- return () => {
27
- const value = item.current();
28
- const revision = item.revision();
29
- if (snapshot && revision === previousRevision) return snapshot;
30
- previousRevision = revision;
31
- snapshot = {
32
- value,
33
- revision
34
- };
35
- return snapshot;
38
+ return useSyncExternalStore(useCallback((listener) => {
39
+ read();
40
+ let selection = cache.current?.selection ?? {
41
+ keys: /* @__PURE__ */ new Set(),
42
+ all: true,
43
+ structure: false
36
44
  };
37
- }, [item]);
38
- return useSyncExternalStore(useCallback((listener) => item.subscribe(listener), [item]), read, read).value;
45
+ let unsubscribe = subscribeProjection(owner, projection, selection, onInvalidate);
46
+ const reinstall = (next) => {
47
+ if (sameProjectionSelection(selection, next)) return;
48
+ unsubscribe();
49
+ selection = next;
50
+ unsubscribe = subscribeProjection(owner, projection, selection, onInvalidate);
51
+ };
52
+ function onInvalidate() {
53
+ const previous = cache.current?.value;
54
+ const next = read();
55
+ const nextSelection = cache.current?.selection;
56
+ if (nextSelection) reinstall(nextSelection);
57
+ if (!Object.is(previous, next)) listener();
58
+ }
59
+ return () => unsubscribe();
60
+ }, [
61
+ owner,
62
+ projection,
63
+ read
64
+ ]), read, read);
39
65
  }
40
- function useSetProjection(projection, store) {
66
+ function useInput(input, runtime) {
41
67
  const context = useContext(ProjectionContext);
42
- const owner = store ?? context;
43
- if (!owner) throw new Error("ProjectionStore is required.");
44
- return useCallback((value) => owner.set(projection, value), [owner, projection]);
68
+ const owner = runtime ?? context;
69
+ if (!owner) throw new Error("ProjectionRuntime is required.");
70
+ const value = useProjection(input, owner);
71
+ const set = useCallback((next) => owner.set(input, next), [input, owner]);
72
+ return useMemo(() => [value, set], [set, value]);
45
73
  }
46
74
  const objectIs = (previous, next) => Object.is(previous, next);
47
75
  const sameTargets = (left, right) => {
@@ -140,6 +168,6 @@ function useHistory(history) {
140
168
  ]);
141
169
  }
142
170
  //#endregion
143
- export { ProjectionContext, ProjectionProvider, useDocumentSelector, useHistory, useProjection, useProjectionItem, useReadable, useSetProjection };
171
+ export { ProjectionContext, ProjectionProvider, useDocumentSelector, useHistory, useInput, useProjection, useReadable };
144
172
 
145
173
  //# sourceMappingURL=react.js.map
package/dist/react.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"react.js","names":["sameTarget"],"sources":["../react/src/hooks.ts"],"sourcesContent":["import type {\n DocumentReadable,\n ObjectNode,\n DocumentSelector,\n HistoryState,\n LocalHistory,\n OperationResult,\n Readable,\n ProjectionStore,\n CollectionProjection,\n ValueProjection,\n InputProjection,\n} from 'doxum';\nimport { track, subscribeDependencies, sameTarget, type ImpactTarget } from 'doxum/integration';\nimport {\n createContext,\n useCallback,\n useContext,\n useMemo,\n useRef,\n useSyncExternalStore,\n} from 'react';\n\nexport const ProjectionContext = createContext<ProjectionStore | undefined>(undefined);\nexport const ProjectionProvider = ProjectionContext.Provider;\n\nexport function useProjection<T>(projection: ValueProjection<T>, store?: ProjectionStore): T {\n const context = useContext(ProjectionContext);\n const owner = store ?? context;\n if (!owner) throw new Error('ProjectionStore is required.');\n const read = useCallback(() => owner.get(projection), [owner, projection]);\n const subscribe = useCallback(\n (listener: () => void) => owner.subscribe(projection, listener),\n [owner, projection]\n );\n return useSyncExternalStore(subscribe, read, read);\n}\n\ntype ProjectionItemSnapshot<T> = {\n readonly value: T | undefined;\n readonly revision: number;\n};\n\nexport function useProjectionItem<K extends string, V>(\n projection: CollectionProjection<K, V>,\n key: K,\n store?: ProjectionStore\n): V | undefined {\n const context = useContext(ProjectionContext);\n const owner = store ?? context;\n if (!owner) throw new Error('ProjectionStore is required.');\n const item = useMemo(() => owner.item(projection, key), [key, owner, projection]);\n const read = useMemo(() => {\n let previousRevision = -1;\n let snapshot: ProjectionItemSnapshot<V> | undefined;\n return (): ProjectionItemSnapshot<V> => {\n const value = item.current();\n const revision = item.revision();\n if (snapshot && revision === previousRevision) return snapshot;\n previousRevision = revision;\n snapshot = { value, revision };\n return snapshot;\n };\n }, [item]);\n const subscribe = useCallback((listener: () => void) => item.subscribe(listener), [item]);\n return useSyncExternalStore(subscribe, read, read).value;\n}\n\nexport function useSetProjection<T>(\n projection: InputProjection<T>,\n store?: ProjectionStore\n): (value: T) => void {\n const context = useContext(ProjectionContext);\n const owner = store ?? context;\n if (!owner) throw new Error('ProjectionStore is required.');\n return useCallback((value: T) => owner.set(projection, value), [owner, projection]);\n}\n\nexport type DocumentSelectorOptions<TResult> = {\n readonly isEqual?: (previous: TResult, next: TResult) => boolean;\n readonly server?: () => TResult;\n};\n\ntype SelectorCache<TSchema extends ObjectNode, TResult> = {\n readonly runtime: DocumentReadable<TSchema>;\n readonly value: TResult;\n readonly targets: readonly ImpactTarget<unknown>[];\n};\n\nconst objectIs = <T>(previous: T, next: T): boolean => Object.is(previous, next);\nconst sameTargets = (\n left: readonly ImpactTarget<unknown>[],\n right: readonly ImpactTarget<unknown>[]\n): boolean => {\n if (left.length !== right.length) return false;\n for (let index = 0; index < left.length; index += 1)\n if (!sameTarget(left[index], right[index])) return false;\n return true;\n};\n\nexport function useDocumentSelector<TSchema extends ObjectNode, TResult>(\n runtime: DocumentReadable<TSchema>,\n selector: DocumentSelector<TSchema, TResult>,\n options?: DocumentSelectorOptions<TResult>\n): TResult {\n const equality = options?.isEqual ?? objectIs;\n const cache = useRef<SelectorCache<TSchema, TResult> | undefined>(undefined);\n const serverCache = useRef<\n | {\n readonly runtime: DocumentReadable<TSchema>;\n readonly selector: DocumentSelector<TSchema, TResult>;\n readonly source: (() => TResult) | undefined;\n readonly value: TResult;\n }\n | undefined\n >(undefined);\n\n const read = useMemo(() => {\n // Each selector closure owns its revision cache, including inline selectors\n // that allocate arrays or objects. Equality only compares distinct snapshots.\n let snapshot: { readonly revision: number; readonly value: TResult } | undefined;\n return (): TResult => {\n const revision = runtime.revision();\n if (snapshot?.revision === revision) return snapshot.value;\n const selection = track(runtime, selector);\n const previous = cache.current;\n const value =\n previous && previous.runtime === runtime && equality(previous.value, selection.value)\n ? previous.value\n : selection.value;\n cache.current = { runtime, value, targets: selection.targets };\n snapshot = { revision, value };\n return value;\n };\n }, [equality, runtime, selector]);\n\n const subscribe = useCallback(\n (listener: () => void) => {\n read();\n let targets = cache.current?.targets ?? [];\n let unsubscribe: () => void = () => undefined;\n const install = () => {\n if (targets.length === 0) return () => undefined;\n return subscribeDependencies(runtime, targets, onCommit);\n };\n const onCommit = () => {\n const previous = cache.current;\n const next = read();\n const nextTargets = cache.current?.targets ?? [];\n if (!sameTargets(targets, nextTargets)) {\n unsubscribe();\n targets = nextTargets;\n unsubscribe = install();\n }\n if (previous && !Object.is(previous.value, next)) listener();\n };\n unsubscribe = install();\n return () => unsubscribe();\n },\n [read, runtime]\n );\n\n const server = options?.server;\n const readServer = useCallback((): TResult => {\n const previous = serverCache.current;\n if (\n previous &&\n previous.source === server &&\n previous.runtime === runtime &&\n previous.selector === selector\n )\n return previous.value;\n const value = server ? server() : read();\n serverCache.current = { runtime, selector, source: server, value };\n return value;\n }, [read, server, runtime, selector]);\n\n return useSyncExternalStore(subscribe, read, readServer);\n}\n\nexport function useReadable<T>(readable: Readable<T>): T {\n const subscribe = useCallback((listener: () => void) => readable.subscribe(listener), [readable]);\n const read = useCallback(() => readable.current(), [readable]);\n return useSyncExternalStore(subscribe, read, read);\n}\n\nexport function useHistory<TCommit>(history: LocalHistory<TCommit>): HistoryState & {\n undo(): OperationResult<TCommit>;\n redo(): OperationResult<TCommit>;\n} {\n const subscribe = useCallback((listener: () => void) => history.subscribe(listener), [history]);\n const read = useCallback(() => history.current(), [history]);\n const state = useSyncExternalStore(subscribe, read, read);\n const undo = useCallback(() => history.undo(), [history]);\n const redo = useCallback(() => history.redo(), [history]);\n\n return useMemo(() => ({ ...state, undo, redo }), [redo, state, undo]);\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"react.js","names":["sameTarget"],"sources":["../react/src/hooks.ts"],"sourcesContent":["import type {\n DocumentReadable,\n ObjectNode,\n DocumentSelector,\n HistoryState,\n LocalHistory,\n OperationResult,\n Readable,\n ProjectionRuntime,\n Projection,\n Input,\n} from 'doxum';\nimport {\n track,\n subscribeDependencies,\n sameTarget,\n type ImpactTarget,\n trackProjection,\n subscribeProjection,\n type ProjectionSelection,\n} from 'doxum/integration';\nimport {\n createContext,\n useCallback,\n useContext,\n useMemo,\n useRef,\n useSyncExternalStore,\n} from 'react';\n\nexport const ProjectionContext = createContext<ProjectionRuntime | undefined>(undefined);\nexport const ProjectionProvider = ProjectionContext.Provider;\n\nconst sameProjectionSelection = (\n left: ProjectionSelection,\n right: ProjectionSelection\n): boolean => {\n if (\n left.all !== right.all ||\n left.structure !== right.structure ||\n left.keys.size !== right.keys.size\n )\n return false;\n for (const key of left.keys) if (!right.keys.has(key)) return false;\n return true;\n};\n\nexport function useProjection<T>(projection: Projection<T>, runtime?: ProjectionRuntime): T;\nexport function useProjection<T, R>(\n projection: Projection<T>,\n selector: (value: T) => R,\n runtime?: ProjectionRuntime\n): R;\nexport function useProjection<T, R>(\n projection: Projection<T>,\n selector: (value: T) => R,\n equality?: (previous: R, next: R) => boolean,\n runtime?: ProjectionRuntime\n): R;\nexport function useProjection<T, R>(\n projection: Projection<T>,\n selectorOrRuntime?: ((value: T) => R) | ProjectionRuntime,\n equalityOrRuntime?: ((previous: R, next: R) => boolean) | ProjectionRuntime,\n suppliedRuntime?: ProjectionRuntime\n): T | R {\n const context = useContext(ProjectionContext);\n const selector = typeof selectorOrRuntime === 'function' ? selectorOrRuntime : undefined;\n const equality = typeof equalityOrRuntime === 'function' ? equalityOrRuntime : Object.is;\n const owner =\n (selector ? suppliedRuntime : undefined) ??\n (selector\n ? equalityOrRuntime && typeof equalityOrRuntime !== 'function'\n ? equalityOrRuntime\n : undefined\n : undefined) ??\n (selector ? context : typeof selectorOrRuntime === 'object' ? selectorOrRuntime : context);\n if (!owner) throw new Error('ProjectionRuntime is required.');\n if (!selector) {\n const read = useCallback(() => owner.get(projection), [owner, projection]);\n const subscribe = useCallback(\n (listener: () => void) => owner.subscribe(projection, listener),\n [owner, projection]\n );\n return useSyncExternalStore(subscribe, read, read) as T;\n }\n const cache = useRef<{ value: R; selection: ProjectionSelection } | undefined>(undefined);\n const read = useCallback(() => {\n const selected = trackProjection(owner, projection, selector);\n const previous = cache.current;\n const value =\n previous && equality(previous.value, selected.value) ? previous.value : selected.value;\n cache.current = { value, selection: selected.selection };\n return value;\n }, [equality, owner, projection, selector]);\n const subscribe = useCallback(\n (listener: () => void) => {\n read();\n let selection = cache.current?.selection ?? {\n keys: new Set<string>(),\n all: true,\n structure: false,\n };\n let unsubscribe = subscribeProjection(owner, projection, selection, onInvalidate);\n const reinstall = (next: ProjectionSelection) => {\n if (sameProjectionSelection(selection, next)) return;\n unsubscribe();\n selection = next;\n unsubscribe = subscribeProjection(owner, projection, selection, onInvalidate);\n };\n function onInvalidate() {\n const previous = cache.current?.value;\n const next = read();\n const nextSelection = cache.current?.selection;\n if (nextSelection) reinstall(nextSelection);\n if (!Object.is(previous, next)) listener();\n }\n return () => unsubscribe();\n },\n [owner, projection, read]\n );\n return useSyncExternalStore(subscribe, read, read);\n}\n\nexport function useInput<T>(\n input: Input<T>,\n runtime?: ProjectionRuntime\n): readonly [T, (value: T) => void] {\n const context = useContext(ProjectionContext);\n const owner = runtime ?? context;\n if (!owner) throw new Error('ProjectionRuntime is required.');\n const value = useProjection(input, owner);\n const set = useCallback((next: T) => owner.set(input, next), [input, owner]);\n return useMemo(() => [value, set] as const, [set, value]);\n}\n\nexport type DocumentSelectorOptions<TResult> = {\n readonly isEqual?: (previous: TResult, next: TResult) => boolean;\n readonly server?: () => TResult;\n};\n\ntype SelectorCache<TSchema extends ObjectNode, TResult> = {\n readonly runtime: DocumentReadable<TSchema>;\n readonly value: TResult;\n readonly targets: readonly ImpactTarget<unknown>[];\n};\n\nconst objectIs = <T>(previous: T, next: T): boolean => Object.is(previous, next);\nconst sameTargets = (\n left: readonly ImpactTarget<unknown>[],\n right: readonly ImpactTarget<unknown>[]\n): boolean => {\n if (left.length !== right.length) return false;\n for (let index = 0; index < left.length; index += 1)\n if (!sameTarget(left[index], right[index])) return false;\n return true;\n};\n\nexport function useDocumentSelector<TSchema extends ObjectNode, TResult>(\n runtime: DocumentReadable<TSchema>,\n selector: DocumentSelector<TSchema, TResult>,\n options?: DocumentSelectorOptions<TResult>\n): TResult {\n const equality = options?.isEqual ?? objectIs;\n const cache = useRef<SelectorCache<TSchema, TResult> | undefined>(undefined);\n const serverCache = useRef<\n | {\n readonly runtime: DocumentReadable<TSchema>;\n readonly selector: DocumentSelector<TSchema, TResult>;\n readonly source: (() => TResult) | undefined;\n readonly value: TResult;\n }\n | undefined\n >(undefined);\n\n const read = useMemo(() => {\n // Each selector closure owns its revision cache, including inline selectors\n // that allocate arrays or objects. Equality only compares distinct snapshots.\n let snapshot: { readonly revision: number; readonly value: TResult } | undefined;\n return (): TResult => {\n const revision = runtime.revision();\n if (snapshot?.revision === revision) return snapshot.value;\n const selection = track(runtime, selector);\n const previous = cache.current;\n const value =\n previous && previous.runtime === runtime && equality(previous.value, selection.value)\n ? previous.value\n : selection.value;\n cache.current = { runtime, value, targets: selection.targets };\n snapshot = { revision, value };\n return value;\n };\n }, [equality, runtime, selector]);\n\n const subscribe = useCallback(\n (listener: () => void) => {\n read();\n let targets = cache.current?.targets ?? [];\n let unsubscribe: () => void = () => undefined;\n const install = () => {\n if (targets.length === 0) return () => undefined;\n return subscribeDependencies(runtime, targets, onCommit);\n };\n const onCommit = () => {\n const previous = cache.current;\n const next = read();\n const nextTargets = cache.current?.targets ?? [];\n if (!sameTargets(targets, nextTargets)) {\n unsubscribe();\n targets = nextTargets;\n unsubscribe = install();\n }\n if (previous && !Object.is(previous.value, next)) listener();\n };\n unsubscribe = install();\n return () => unsubscribe();\n },\n [read, runtime]\n );\n\n const server = options?.server;\n const readServer = useCallback((): TResult => {\n const previous = serverCache.current;\n if (\n previous &&\n previous.source === server &&\n previous.runtime === runtime &&\n previous.selector === selector\n )\n return previous.value;\n const value = server ? server() : read();\n serverCache.current = { runtime, selector, source: server, value };\n return value;\n }, [read, server, runtime, selector]);\n\n return useSyncExternalStore(subscribe, read, readServer);\n}\n\nexport function useReadable<T>(readable: Readable<T>): T {\n const subscribe = useCallback((listener: () => void) => readable.subscribe(listener), [readable]);\n const read = useCallback(() => readable.current(), [readable]);\n return useSyncExternalStore(subscribe, read, read);\n}\n\nexport function useHistory<TCommit>(history: LocalHistory<TCommit>): HistoryState & {\n undo(): OperationResult<TCommit>;\n redo(): OperationResult<TCommit>;\n} {\n const subscribe = useCallback((listener: () => void) => history.subscribe(listener), [history]);\n const read = useCallback(() => history.current(), [history]);\n const state = useSyncExternalStore(subscribe, read, read);\n const undo = useCallback(() => history.undo(), [history]);\n const redo = useCallback(() => history.redo(), [history]);\n\n return useMemo(() => ({ ...state, undo, redo }), [redo, state, undo]);\n}\n"],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ import { _ as Unsubscribe } from "./contract-XmKnroJq.cjs";
2
+ import { c as BatchOptions, m as ProjectionError, n as Projection, t as Input } from "./definition-kxnWUvX9.cjs";
3
+
4
+ //#region core/src/projection/store.d.ts
5
+ type ProjectionRuntime = {
6
+ get<T>(projection: Projection<T>): T;
7
+ subscribe<T>(projection: Projection<T>, listener: () => void): Unsubscribe;
8
+ set<T>(input: Input<T>, value: T): void;
9
+ batch<T>(run: () => T): T;
10
+ batch<T>(options: BatchOptions, run: () => T): T;
11
+ dispose(): void;
12
+ };
13
+ declare const createProjectionRuntime: (options?: {
14
+ readonly onError?: (error: ProjectionError) => void;
15
+ }) => ProjectionRuntime;
16
+ type ProjectionSelection = {
17
+ readonly keys: ReadonlySet<string>;
18
+ readonly all: boolean;
19
+ readonly structure: boolean;
20
+ };
21
+ declare const trackProjection: <T, R>(owner: ProjectionRuntime, projection: Projection<T>, selector: (value: T) => R) => {
22
+ readonly value: R;
23
+ readonly selection: ProjectionSelection;
24
+ };
25
+ declare const subscribeProjection: (owner: ProjectionRuntime, projection: Projection<unknown>, selection: ProjectionSelection, listener: () => void) => Unsubscribe;
26
+ //#endregion
27
+ export { trackProjection as a, subscribeProjection as i, ProjectionSelection as n, createProjectionRuntime as r, ProjectionRuntime as t };
28
+ //# sourceMappingURL=store-CDeqZEE3.d.cts.map