index.ts 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. import type { StateModel, StateStore } from "@json-render/core";
  2. import { createStoreAdapter } from "@json-render/core/store-utils";
  3. import type { WritableAtom } from "jotai";
  4. import { createStore as createJotaiStore } from "jotai/vanilla";
  5. export type { StateStore } from "@json-render/core";
  6. type JotaiStore = ReturnType<typeof createJotaiStore>;
  7. /**
  8. * Options for {@link jotaiStateStore}.
  9. */
  10. export interface JotaiStateStoreOptions {
  11. /** A writable atom that holds the json-render state model. */
  12. atom: WritableAtom<StateModel, [StateModel], void>;
  13. /**
  14. * The Jotai store instance. Defaults to `createStore()` from `jotai/vanilla`.
  15. * Pass your own if you use a `<Provider store={...}>` in your React tree.
  16. */
  17. store?: JotaiStore;
  18. }
  19. /**
  20. * Create a {@link StateStore} backed by a Jotai atom.
  21. *
  22. * @example
  23. * ```ts
  24. * import { atom } from "jotai";
  25. * import { jotaiStateStore } from "@json-render/jotai";
  26. *
  27. * const uiAtom = atom<Record<string, unknown>>({ count: 0 });
  28. *
  29. * const store = jotaiStateStore({ atom: uiAtom });
  30. *
  31. * <StateProvider store={store}>...</StateProvider>
  32. * ```
  33. *
  34. * @example With a shared Jotai store:
  35. * ```ts
  36. * import { atom, createStore } from "jotai";
  37. *
  38. * const jStore = createStore();
  39. * const uiAtom = atom<Record<string, unknown>>({ count: 0 });
  40. *
  41. * const store = jotaiStateStore({ atom: uiAtom, store: jStore });
  42. *
  43. * // In React:
  44. * <JotaiProvider store={jStore}>
  45. * <StateProvider store={store}>...</StateProvider>
  46. * </JotaiProvider>
  47. * ```
  48. */
  49. export function jotaiStateStore(options: JotaiStateStoreOptions): StateStore {
  50. const stateAtom = options.atom;
  51. const jStore = options.store ?? createJotaiStore();
  52. return createStoreAdapter({
  53. getSnapshot: () => jStore.get(stateAtom),
  54. setSnapshot: (next) => jStore.set(stateAtom, next),
  55. subscribe: (listener) => jStore.sub(stateAtom, listener),
  56. });
  57. }