@pixotope/react-context-store 0.2.0 → 0.3.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.
@@ -1,6 +1,6 @@
1
1
 
2
- > @pixotope/react-context-store@0.2.0 build /home/circleci/project/packages/react-context-store
3
- > tsup src/index.ts --format cjs,esm --dts --sourcemap --external react --external use-sync-external-store
2
+ > @pixotope/react-context-store@0.3.0 build /home/circleci/project/packages/react-context-store
3
+ > tsup src/index.ts --format cjs,esm --dts --sourcemap --external react
4
4
 
5
5
  CLI Building entry: src/index.ts
6
6
  CLI Using tsconfig: tsconfig.json
@@ -8,13 +8,13 @@
8
8
  CLI Target: es6
9
9
  CJS Build start
10
10
  ESM Build start
11
- ESM dist/index.js 7.92 KB
12
- ESM dist/index.js.map 16.10 KB
13
- ESM ⚡️ Build success in 24ms
14
- CJS dist/index.cjs 8.55 KB
15
- CJS dist/index.cjs.map 16.23 KB
16
- CJS ⚡️ Build success in 24ms
11
+ ESM dist/index.js 7.88 KB
12
+ ESM dist/index.js.map 16.05 KB
13
+ ESM ⚡️ Build success in 32ms
14
+ CJS dist/index.cjs 8.49 KB
15
+ CJS dist/index.cjs.map 16.17 KB
16
+ CJS ⚡️ Build success in 33ms
17
17
  DTS Build start
18
- DTS ⚡️ Build success in 1731ms
18
+ DTS ⚡️ Build success in 2162ms
19
19
  DTS dist/index.d.cts 2.31 KB
20
20
  DTS dist/index.d.ts 2.31 KB
@@ -1,4 +1,4 @@
1
1
 
2
- > @pixotope/react-context-store@0.2.0 check-types /home/circleci/project/packages/react-context-store
2
+ > @pixotope/react-context-store@0.3.0 check-types /home/circleci/project/packages/react-context-store
3
3
  > tsc --noEmit
4
4
 
@@ -1,14 +1,14 @@
1
1
 
2
- > @pixotope/react-context-store@0.2.0 test /home/circleci/project/packages/react-context-store
2
+ > @pixotope/react-context-store@0.3.0 test /home/circleci/project/packages/react-context-store
3
3
  > vitest
4
4
 
5
5
 
6
6
   RUN  v3.2.4 /home/circleci/project/packages/react-context-store
7
7
 
8
- ✓ src/store.test.tsx (12 tests) 102ms
8
+ ✓ src/store.test.tsx (12 tests) 105ms
9
9
 
10
10
   Test Files  1 passed (1)
11
11
   Tests  12 passed (12)
12
-  Start at  17:28:09
13
-  Duration  3.39s (transform 157ms, setup 117ms, collect 365ms, tests 102ms, environment 887ms, prepare 711ms)
12
+  Start at  17:35:07
13
+  Duration  3.27s (transform 301ms, setup 181ms, collect 307ms, tests 105ms, environment 1.13s, prepare 616ms)
14
14
 
package/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # @pixotope/react-context-store
2
2
 
3
+ ## 0.3.0
4
+
5
+ ### Minor Changes
6
+
7
+ - eec8876: - remove `use-sync-external-store` and force peer react version to min 18
8
+
3
9
  ## 0.2.0
4
10
 
5
11
  ### Minor Changes
package/dist/index.cjs CHANGED
@@ -105,7 +105,6 @@ module.exports = __toCommonJS(index_exports);
105
105
  // src/store.tsx
106
106
  var import_react = __toESM(require("react"), 1);
107
107
  var import_comparison = __toESM(require_comparison(), 1);
108
- var import_shim = require("use-sync-external-store/shim");
109
108
  var LIB_NAME = "@pixotope/react-context-store";
110
109
  function isFunction(value) {
111
110
  return typeof value === "function";
@@ -184,7 +183,7 @@ function createContextStore(initialState, actions = {}, options = {}) {
184
183
  `[${LIB_NAME}] Store not found. Make sure the component is wrapped in a ${Provider} component.`
185
184
  );
186
185
  }
187
- const state = (0, import_shim.useSyncExternalStore)(
186
+ const state = (0, import_react.useSyncExternalStore)(
188
187
  store.subscribe,
189
188
  () => {
190
189
  const selectedState = selector(store.get());
@@ -1 +1 @@
1
- {"version":3,"sources":["../../utils/dist/comparison/index.js","../src/index.ts","../src/store.tsx"],"sourcesContent":["\"use strict\";\nvar __defProp = Object.defineProperty;\nvar __getOwnPropDesc = Object.getOwnPropertyDescriptor;\nvar __getOwnPropNames = Object.getOwnPropertyNames;\nvar __hasOwnProp = Object.prototype.hasOwnProperty;\nvar __export = (target, all) => {\n for (var name in all)\n __defProp(target, name, { get: all[name], enumerable: true });\n};\nvar __copyProps = (to, from, except, desc) => {\n if (from && typeof from === \"object\" || typeof from === \"function\") {\n for (let key of __getOwnPropNames(from))\n if (!__hasOwnProp.call(to, key) && key !== except)\n __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });\n }\n return to;\n};\nvar __toCommonJS = (mod) => __copyProps(__defProp({}, \"__esModule\", { value: true }), mod);\n\n// src/comparison/index.ts\nvar comparison_exports = {};\n__export(comparison_exports, {\n shallowEqual: () => shallowEqual\n});\nmodule.exports = __toCommonJS(comparison_exports);\n\n// src/comparison/shallowEqual.ts\nfunction shallowEqual(objA, objB) {\n if (Object.is(objA, objB)) {\n return true;\n }\n if (typeof objA !== \"object\" || objA === null || typeof objB !== \"object\" || objB === null) {\n return false;\n }\n if (objA instanceof Map && objB instanceof Map) {\n if (objA.size !== objB.size) return false;\n for (const [key, value] of objA) {\n if (!Object.is(value, objB.get(key))) {\n return false;\n }\n }\n return true;\n }\n if (objA instanceof Set && objB instanceof Set) {\n if (objA.size !== objB.size) return false;\n for (const value of objA) {\n if (!objB.has(value)) {\n return false;\n }\n }\n return true;\n }\n const keysA = Object.keys(objA);\n if (keysA.length !== Object.keys(objB).length) {\n return false;\n }\n for (let i = 0; i < keysA.length; i++) {\n if (!Object.prototype.hasOwnProperty.call(objB, keysA[i]) || !Object.is(objA[keysA[i]], objB[keysA[i]])) {\n return false;\n }\n }\n return true;\n}\n// Annotate the CommonJS export names for ESM import in node:\n0 && (module.exports = {\n shallowEqual\n});\n","export * from \"./store\";\n","import React, {\n createContext,\n useCallback,\n useContext,\n useMemo,\n useRef,\n} from \"react\";\nimport { shallowEqual } from \"@pixotope/utils/comparison\";\nimport { useSyncExternalStore } from \"use-sync-external-store/shim\";\n\nconst LIB_NAME = \"@pixotope/react-context-store\";\n\nexport type SelectorOptions<Selected> = (\n first: Selected,\n second: Selected\n) => boolean;\n\nexport type ContextOptions = {\n /**\n * If true, the store state will be preserved across mounts and un-mounts\n * of the Provider.\n * @default false\n */\n global?: boolean;\n /**\n * A function that will be used to compare the selected state.\n * @default shallowEqual\n */\n compare?: SelectorOptions<unknown>;\n};\n\nexport type SetterArgs<Store> = Store | ((prev: Store) => Store);\ntype ExtractActionKeys<T> = {\n [K in keyof T]: T[K] extends (\n stateProps: never,\n action: infer A\n ) => void | Promise<void>\n ? A extends ActionablePayload<infer Payload>\n ? Payload extends undefined\n ? () => void\n : (payload: Payload) => void\n : () => void\n : never;\n};\n\ntype Prettify<T> = {\n [K in keyof T]: T[K];\n} & {};\n\nexport type ActionablePayload<Payload = any> = {\n payload: Payload;\n};\n\ntype StateActionProps<Store> = {\n set: (value: SetterArgs<Store>) => void;\n get: () => Store;\n};\n\ntype Actions<Store> = {\n [key: string]: (\n stateProps: StateActionProps<Store>,\n action: ActionablePayload\n ) => void | Promise<void>;\n};\n\ntype UseStoreReturnType<Store, SelectorOutput> = {\n state: SelectorOutput;\n get: () => SelectorOutput;\n set: (value: SetterArgs<Store>) => void;\n selector: () => Store;\n};\n\ntype ContextReturnType<Store, A extends Actions<Store>> = {\n Provider: React.FC<React.PropsWithChildren>;\n useStore: <SelectorOutput = Store>(\n selector?: (store: Store) => SelectorOutput,\n options?: SelectorOptions<SelectorOutput>\n ) => UseStoreReturnType<Store, SelectorOutput>;\n useActions: () => Prettify<ExtractActionKeys<A>>;\n useSetStore: () => (value: SetterArgs<Store>) => void;\n subscribe: <SelectorOutput = Store>(\n selector: (store: Store) => SelectorOutput,\n callback: (state: SelectorOutput) => void,\n options?: SelectorOptions<SelectorOutput>\n ) => () => void;\n unsubscribe: (callback: () => void) => void;\n};\n\nfunction isFunction(value: any): value is (prev: any) => any {\n return typeof value === \"function\";\n}\n\nexport function createContextStore<Store, A extends Actions<Store> = {}>(\n ...args: Extract<A, { payload: A }> extends { payload: infer Payload }\n ? [initialState: Store, actions?: A, options?: ContextOptions]\n : [initialState: Store, options?: ContextOptions]\n): ContextReturnType<Store, A>;\nexport function createContextStore<Store, A extends Actions<Store> = {}>(\n initialState: Store,\n actions: A = {} as A,\n options: ContextOptions = {}\n) {\n let globalStore: Store | undefined = options.global\n ? initialState\n : undefined;\n\n function useStoreData({\n defaultSubscriber = [],\n }: {\n defaultSubscriber?: ((state: Store) => void)[];\n } = {}): {\n get: () => Store;\n set: (value: SetterArgs<Store>) => void;\n subscribe: (callback: (state: Store) => void) => () => void;\n } {\n const store = useRef<Store>(globalStore ?? initialState);\n\n const get = useCallback(() => store.current, []);\n\n const subscribers = useRef(\n new Set<(state: Store) => void>(defaultSubscriber)\n );\n\n const set = useCallback((value: SetterArgs<Store>) => {\n store.current = isFunction(value) ? value(store.current) : value;\n\n if (options.global) {\n globalStore = store.current;\n }\n\n subscribers.current.forEach((callback) => callback(store.current));\n }, []);\n\n const subscribe = useCallback((callback: (state: Store) => void) => {\n subscribers.current.add(callback);\n\n return () => subscribers.current.delete(callback);\n }, []);\n\n return {\n get,\n set,\n subscribe,\n };\n }\n\n type UseStoreDataReturnType = ReturnType<typeof useStoreData>;\n\n const StoreContext = createContext<UseStoreDataReturnType | null>(null);\n\n /**\n * This is the provider that will be used to wrap the react component tree\n * to provide the store to all the components in the tree.\n */\n function Provider({ children }: React.PropsWithChildren) {\n return (\n <StoreContext.Provider\n value={useStoreData({ defaultSubscriber: [observable.broadcast] })}\n >\n {children}\n </StoreContext.Provider>\n );\n }\n\n /**\n * This holds all the observables that are subscribed to the store\n * but not being actively used by any component. Helps to broadcast\n * store updates to all the observables that are interested in reacting\n * to state outside the react component tree.\n */\n const observers = new Set<(state: Store) => void>();\n\n function subscribeExternal<SelectorOutput = Store>(\n selector: (store: Store) => SelectorOutput = (store) =>\n store as unknown as SelectorOutput,\n callback: (state: SelectorOutput) => void,\n compare: SelectorOptions<SelectorOutput> = shallowEqual\n ): () => void {\n let lastSelectedState: SelectorOutput | undefined;\n\n const shouldSendUpdates = (newSelectedState: SelectorOutput) => {\n if (\n lastSelectedState === undefined ||\n !compare(lastSelectedState, newSelectedState)\n ) {\n lastSelectedState = newSelectedState;\n\n return true;\n }\n\n return false;\n };\n\n const selectedCb = (store: Store) => {\n const selected = selector(store);\n const shouldSend = shouldSendUpdates(selected);\n\n if (shouldSend) {\n callback(selector(store));\n }\n };\n observers.add(selectedCb);\n\n return () => observers.delete(selectedCb);\n }\n\n /**\n * A simple observable that proxy store updates to all the subscribers\n * that are interested in reacting to state outside the react component tree.\n */\n const observable = {\n subscribe: subscribeExternal,\n unsubscribe: (callback: (state: Store) => void) => {\n observers.delete(callback);\n },\n broadcast: (state: Store) => {\n observers.forEach((callback) => callback(state));\n },\n } as const;\n\n /**\n * This is the hook that will be used to access the store from any component\n * in the react component tree.\n * @param selector A function that will be used to select the part of the store\n * that is needed by the component.\n * @param options Options to customize the behavior of the hook.\n * @returns An object with the selected state, a function to update the store\n * and a function to get the entire store.\n * @example\n * ```tsx\n * const { get, set } = useStore(store => store.user);\n * const { get, set } = useStore(store => store.user, { deepEqual: false });\n * const { get, set } = useStore(store => store.user, {\n * compare: (first, second) => first.id === second.id\n * });\n * ```\n */\n function useStore<SelectorOutput = Store>(\n selector: (store: Store) => SelectorOutput = (store) =>\n store as unknown as SelectorOutput,\n compare: SelectorOptions<SelectorOutput> = options.compare ?? shallowEqual\n ): UseStoreReturnType<Store, SelectorOutput> {\n const store = useContext(StoreContext);\n const lastSelectedState = useRef<SelectorOutput | undefined>(undefined);\n\n if (!store) {\n throw new Error(\n `[${LIB_NAME}] Store not found. Make sure the component is wrapped in a ${Provider} component.`\n );\n }\n\n const state = useSyncExternalStore(\n store.subscribe,\n () => {\n const selectedState = selector(store.get());\n\n if (\n lastSelectedState.current === undefined ||\n !compare(lastSelectedState.current, selectedState)\n ) {\n lastSelectedState.current = selectedState;\n }\n\n return lastSelectedState.current;\n },\n () => selector(initialState)\n );\n\n return {\n state,\n get: () => state,\n set: store.set,\n selector: () => store.get(),\n };\n }\n\n function useActions() {\n const store = useContext(StoreContext);\n\n if (!store) {\n throw new Error(\n `[${LIB_NAME}] Store not found. Make sure the component is wrapped in a ${Provider} component.`\n );\n }\n\n const actionProxy = useMemo(\n () =>\n new Proxy(actions, {\n get: (target, prop) => {\n const action = target[prop as string];\n\n if (action) {\n return (args: Parameters<typeof action>[\"1\"]) => {\n action(\n {\n set: store.set,\n get: store.get,\n },\n {\n payload: args,\n }\n );\n };\n }\n },\n set: () => {\n throw new Error(`[${LIB_NAME}] Actions cannot be updated`);\n },\n }),\n []\n );\n\n return actionProxy as unknown as ExtractActionKeys<typeof actions>;\n }\n\n const useSetStore = () => useStore(() => false).set;\n\n return {\n Provider,\n useStore,\n useSetStore,\n useActions,\n subscribe: observable.subscribe,\n unsubscribe: observable.unsubscribe,\n };\n}\n"],"mappings":"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","names":["exports","module","__defProp","__getOwnPropDesc","__getOwnPropNames","__hasOwnProp","__export","__copyProps","__toCommonJS","shallowEqual","React"]}
1
+ {"version":3,"sources":["../../utils/dist/comparison/index.js","../src/index.ts","../src/store.tsx"],"sourcesContent":["\"use strict\";\nvar __defProp = Object.defineProperty;\nvar __getOwnPropDesc = Object.getOwnPropertyDescriptor;\nvar __getOwnPropNames = Object.getOwnPropertyNames;\nvar __hasOwnProp = Object.prototype.hasOwnProperty;\nvar __export = (target, all) => {\n for (var name in all)\n __defProp(target, name, { get: all[name], enumerable: true });\n};\nvar __copyProps = (to, from, except, desc) => {\n if (from && typeof from === \"object\" || typeof from === \"function\") {\n for (let key of __getOwnPropNames(from))\n if (!__hasOwnProp.call(to, key) && key !== except)\n __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });\n }\n return to;\n};\nvar __toCommonJS = (mod) => __copyProps(__defProp({}, \"__esModule\", { value: true }), mod);\n\n// src/comparison/index.ts\nvar comparison_exports = {};\n__export(comparison_exports, {\n shallowEqual: () => shallowEqual\n});\nmodule.exports = __toCommonJS(comparison_exports);\n\n// src/comparison/shallowEqual.ts\nfunction shallowEqual(objA, objB) {\n if (Object.is(objA, objB)) {\n return true;\n }\n if (typeof objA !== \"object\" || objA === null || typeof objB !== \"object\" || objB === null) {\n return false;\n }\n if (objA instanceof Map && objB instanceof Map) {\n if (objA.size !== objB.size) return false;\n for (const [key, value] of objA) {\n if (!Object.is(value, objB.get(key))) {\n return false;\n }\n }\n return true;\n }\n if (objA instanceof Set && objB instanceof Set) {\n if (objA.size !== objB.size) return false;\n for (const value of objA) {\n if (!objB.has(value)) {\n return false;\n }\n }\n return true;\n }\n const keysA = Object.keys(objA);\n if (keysA.length !== Object.keys(objB).length) {\n return false;\n }\n for (let i = 0; i < keysA.length; i++) {\n if (!Object.prototype.hasOwnProperty.call(objB, keysA[i]) || !Object.is(objA[keysA[i]], objB[keysA[i]])) {\n return false;\n }\n }\n return true;\n}\n// Annotate the CommonJS export names for ESM import in node:\n0 && (module.exports = {\n shallowEqual\n});\n","export * from \"./store\";\n","import React, {\n createContext,\n useCallback,\n useContext,\n useMemo,\n useRef,\n useSyncExternalStore,\n} from \"react\";\nimport { shallowEqual } from \"@pixotope/utils/comparison\";\n\nconst LIB_NAME = \"@pixotope/react-context-store\";\n\nexport type SelectorOptions<Selected> = (\n first: Selected,\n second: Selected\n) => boolean;\n\nexport type ContextOptions = {\n /**\n * If true, the store state will be preserved across mounts and un-mounts\n * of the Provider.\n * @default false\n */\n global?: boolean;\n /**\n * A function that will be used to compare the selected state.\n * @default shallowEqual\n */\n compare?: SelectorOptions<unknown>;\n};\n\nexport type SetterArgs<Store> = Store | ((prev: Store) => Store);\ntype ExtractActionKeys<T> = {\n [K in keyof T]: T[K] extends (\n stateProps: never,\n action: infer A\n ) => void | Promise<void>\n ? A extends ActionablePayload<infer Payload>\n ? Payload extends undefined\n ? () => void\n : (payload: Payload) => void\n : () => void\n : never;\n};\n\ntype Prettify<T> = {\n [K in keyof T]: T[K];\n} & {};\n\nexport type ActionablePayload<Payload = any> = {\n payload: Payload;\n};\n\ntype StateActionProps<Store> = {\n set: (value: SetterArgs<Store>) => void;\n get: () => Store;\n};\n\ntype Actions<Store> = {\n [key: string]: (\n stateProps: StateActionProps<Store>,\n action: ActionablePayload\n ) => void | Promise<void>;\n};\n\ntype UseStoreReturnType<Store, SelectorOutput> = {\n state: SelectorOutput;\n get: () => SelectorOutput;\n set: (value: SetterArgs<Store>) => void;\n selector: () => Store;\n};\n\ntype ContextReturnType<Store, A extends Actions<Store>> = {\n Provider: React.FC<React.PropsWithChildren>;\n useStore: <SelectorOutput = Store>(\n selector?: (store: Store) => SelectorOutput,\n options?: SelectorOptions<SelectorOutput>\n ) => UseStoreReturnType<Store, SelectorOutput>;\n useActions: () => Prettify<ExtractActionKeys<A>>;\n useSetStore: () => (value: SetterArgs<Store>) => void;\n subscribe: <SelectorOutput = Store>(\n selector: (store: Store) => SelectorOutput,\n callback: (state: SelectorOutput) => void,\n options?: SelectorOptions<SelectorOutput>\n ) => () => void;\n unsubscribe: (callback: () => void) => void;\n};\n\nfunction isFunction(value: any): value is (prev: any) => any {\n return typeof value === \"function\";\n}\n\nexport function createContextStore<Store, A extends Actions<Store> = {}>(\n ...args: Extract<A, { payload: A }> extends { payload: infer Payload }\n ? [initialState: Store, actions?: A, options?: ContextOptions]\n : [initialState: Store, options?: ContextOptions]\n): ContextReturnType<Store, A>;\nexport function createContextStore<Store, A extends Actions<Store> = {}>(\n initialState: Store,\n actions: A = {} as A,\n options: ContextOptions = {}\n) {\n let globalStore: Store | undefined = options.global\n ? initialState\n : undefined;\n\n function useStoreData({\n defaultSubscriber = [],\n }: {\n defaultSubscriber?: ((state: Store) => void)[];\n } = {}): {\n get: () => Store;\n set: (value: SetterArgs<Store>) => void;\n subscribe: (callback: (state: Store) => void) => () => void;\n } {\n const store = useRef<Store>(globalStore ?? initialState);\n\n const get = useCallback(() => store.current, []);\n\n const subscribers = useRef(\n new Set<(state: Store) => void>(defaultSubscriber)\n );\n\n const set = useCallback((value: SetterArgs<Store>) => {\n store.current = isFunction(value) ? value(store.current) : value;\n\n if (options.global) {\n globalStore = store.current;\n }\n\n subscribers.current.forEach((callback) => callback(store.current));\n }, []);\n\n const subscribe = useCallback((callback: (state: Store) => void) => {\n subscribers.current.add(callback);\n\n return () => subscribers.current.delete(callback);\n }, []);\n\n return {\n get,\n set,\n subscribe,\n };\n }\n\n type UseStoreDataReturnType = ReturnType<typeof useStoreData>;\n\n const StoreContext = createContext<UseStoreDataReturnType | null>(null);\n\n /**\n * This is the provider that will be used to wrap the react component tree\n * to provide the store to all the components in the tree.\n */\n function Provider({ children }: React.PropsWithChildren) {\n return (\n <StoreContext.Provider\n value={useStoreData({ defaultSubscriber: [observable.broadcast] })}\n >\n {children}\n </StoreContext.Provider>\n );\n }\n\n /**\n * This holds all the observables that are subscribed to the store\n * but not being actively used by any component. Helps to broadcast\n * store updates to all the observables that are interested in reacting\n * to state outside the react component tree.\n */\n const observers = new Set<(state: Store) => void>();\n\n function subscribeExternal<SelectorOutput = Store>(\n selector: (store: Store) => SelectorOutput = (store) =>\n store as unknown as SelectorOutput,\n callback: (state: SelectorOutput) => void,\n compare: SelectorOptions<SelectorOutput> = shallowEqual\n ): () => void {\n let lastSelectedState: SelectorOutput | undefined;\n\n const shouldSendUpdates = (newSelectedState: SelectorOutput) => {\n if (\n lastSelectedState === undefined ||\n !compare(lastSelectedState, newSelectedState)\n ) {\n lastSelectedState = newSelectedState;\n\n return true;\n }\n\n return false;\n };\n\n const selectedCb = (store: Store) => {\n const selected = selector(store);\n const shouldSend = shouldSendUpdates(selected);\n\n if (shouldSend) {\n callback(selector(store));\n }\n };\n observers.add(selectedCb);\n\n return () => observers.delete(selectedCb);\n }\n\n /**\n * A simple observable that proxy store updates to all the subscribers\n * that are interested in reacting to state outside the react component tree.\n */\n const observable = {\n subscribe: subscribeExternal,\n unsubscribe: (callback: (state: Store) => void) => {\n observers.delete(callback);\n },\n broadcast: (state: Store) => {\n observers.forEach((callback) => callback(state));\n },\n } as const;\n\n /**\n * This is the hook that will be used to access the store from any component\n * in the react component tree.\n * @param selector A function that will be used to select the part of the store\n * that is needed by the component.\n * @param options Options to customize the behavior of the hook.\n * @returns An object with the selected state, a function to update the store\n * and a function to get the entire store.\n * @example\n * ```tsx\n * const { get, set } = useStore(store => store.user);\n * const { get, set } = useStore(store => store.user, { deepEqual: false });\n * const { get, set } = useStore(store => store.user, {\n * compare: (first, second) => first.id === second.id\n * });\n * ```\n */\n function useStore<SelectorOutput = Store>(\n selector: (store: Store) => SelectorOutput = (store) =>\n store as unknown as SelectorOutput,\n compare: SelectorOptions<SelectorOutput> = options.compare ?? shallowEqual\n ): UseStoreReturnType<Store, SelectorOutput> {\n const store = useContext(StoreContext);\n const lastSelectedState = useRef<SelectorOutput | undefined>(undefined);\n\n if (!store) {\n throw new Error(\n `[${LIB_NAME}] Store not found. Make sure the component is wrapped in a ${Provider} component.`\n );\n }\n\n const state = useSyncExternalStore(\n store.subscribe,\n () => {\n const selectedState = selector(store.get());\n\n if (\n lastSelectedState.current === undefined ||\n !compare(lastSelectedState.current, selectedState)\n ) {\n lastSelectedState.current = selectedState;\n }\n\n return lastSelectedState.current;\n },\n () => selector(initialState)\n );\n\n return {\n state,\n get: () => state,\n set: store.set,\n selector: () => store.get(),\n };\n }\n\n function useActions() {\n const store = useContext(StoreContext);\n\n if (!store) {\n throw new Error(\n `[${LIB_NAME}] Store not found. Make sure the component is wrapped in a ${Provider} component.`\n );\n }\n\n const actionProxy = useMemo(\n () =>\n new Proxy(actions, {\n get: (target, prop) => {\n const action = target[prop as string];\n\n if (action) {\n return (args: Parameters<typeof action>[\"1\"]) => {\n action(\n {\n set: store.set,\n get: store.get,\n },\n {\n payload: args,\n }\n );\n };\n }\n },\n set: () => {\n throw new Error(`[${LIB_NAME}] Actions cannot be updated`);\n },\n }),\n []\n );\n\n return actionProxy as unknown as ExtractActionKeys<typeof actions>;\n }\n\n const useSetStore = () => useStore(() => false).set;\n\n return {\n Provider,\n useStore,\n useSetStore,\n useActions,\n subscribe: observable.subscribe,\n unsubscribe: observable.unsubscribe,\n };\n}\n"],"mappings":"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","names":["exports","module","__defProp","__getOwnPropDesc","__getOwnPropNames","__hasOwnProp","__export","__copyProps","__toCommonJS","shallowEqual","React"]}
package/dist/index.js CHANGED
@@ -96,9 +96,9 @@ import React, {
96
96
  useCallback,
97
97
  useContext,
98
98
  useMemo,
99
- useRef
99
+ useRef,
100
+ useSyncExternalStore
100
101
  } from "react";
101
- import { useSyncExternalStore } from "use-sync-external-store/shim";
102
102
  var LIB_NAME = "@pixotope/react-context-store";
103
103
  function isFunction(value) {
104
104
  return typeof value === "function";
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../../utils/dist/comparison/index.js","../src/store.tsx"],"sourcesContent":["\"use strict\";\nvar __defProp = Object.defineProperty;\nvar __getOwnPropDesc = Object.getOwnPropertyDescriptor;\nvar __getOwnPropNames = Object.getOwnPropertyNames;\nvar __hasOwnProp = Object.prototype.hasOwnProperty;\nvar __export = (target, all) => {\n for (var name in all)\n __defProp(target, name, { get: all[name], enumerable: true });\n};\nvar __copyProps = (to, from, except, desc) => {\n if (from && typeof from === \"object\" || typeof from === \"function\") {\n for (let key of __getOwnPropNames(from))\n if (!__hasOwnProp.call(to, key) && key !== except)\n __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });\n }\n return to;\n};\nvar __toCommonJS = (mod) => __copyProps(__defProp({}, \"__esModule\", { value: true }), mod);\n\n// src/comparison/index.ts\nvar comparison_exports = {};\n__export(comparison_exports, {\n shallowEqual: () => shallowEqual\n});\nmodule.exports = __toCommonJS(comparison_exports);\n\n// src/comparison/shallowEqual.ts\nfunction shallowEqual(objA, objB) {\n if (Object.is(objA, objB)) {\n return true;\n }\n if (typeof objA !== \"object\" || objA === null || typeof objB !== \"object\" || objB === null) {\n return false;\n }\n if (objA instanceof Map && objB instanceof Map) {\n if (objA.size !== objB.size) return false;\n for (const [key, value] of objA) {\n if (!Object.is(value, objB.get(key))) {\n return false;\n }\n }\n return true;\n }\n if (objA instanceof Set && objB instanceof Set) {\n if (objA.size !== objB.size) return false;\n for (const value of objA) {\n if (!objB.has(value)) {\n return false;\n }\n }\n return true;\n }\n const keysA = Object.keys(objA);\n if (keysA.length !== Object.keys(objB).length) {\n return false;\n }\n for (let i = 0; i < keysA.length; i++) {\n if (!Object.prototype.hasOwnProperty.call(objB, keysA[i]) || !Object.is(objA[keysA[i]], objB[keysA[i]])) {\n return false;\n }\n }\n return true;\n}\n// Annotate the CommonJS export names for ESM import in node:\n0 && (module.exports = {\n shallowEqual\n});\n","import React, {\n createContext,\n useCallback,\n useContext,\n useMemo,\n useRef,\n} from \"react\";\nimport { shallowEqual } from \"@pixotope/utils/comparison\";\nimport { useSyncExternalStore } from \"use-sync-external-store/shim\";\n\nconst LIB_NAME = \"@pixotope/react-context-store\";\n\nexport type SelectorOptions<Selected> = (\n first: Selected,\n second: Selected\n) => boolean;\n\nexport type ContextOptions = {\n /**\n * If true, the store state will be preserved across mounts and un-mounts\n * of the Provider.\n * @default false\n */\n global?: boolean;\n /**\n * A function that will be used to compare the selected state.\n * @default shallowEqual\n */\n compare?: SelectorOptions<unknown>;\n};\n\nexport type SetterArgs<Store> = Store | ((prev: Store) => Store);\ntype ExtractActionKeys<T> = {\n [K in keyof T]: T[K] extends (\n stateProps: never,\n action: infer A\n ) => void | Promise<void>\n ? A extends ActionablePayload<infer Payload>\n ? Payload extends undefined\n ? () => void\n : (payload: Payload) => void\n : () => void\n : never;\n};\n\ntype Prettify<T> = {\n [K in keyof T]: T[K];\n} & {};\n\nexport type ActionablePayload<Payload = any> = {\n payload: Payload;\n};\n\ntype StateActionProps<Store> = {\n set: (value: SetterArgs<Store>) => void;\n get: () => Store;\n};\n\ntype Actions<Store> = {\n [key: string]: (\n stateProps: StateActionProps<Store>,\n action: ActionablePayload\n ) => void | Promise<void>;\n};\n\ntype UseStoreReturnType<Store, SelectorOutput> = {\n state: SelectorOutput;\n get: () => SelectorOutput;\n set: (value: SetterArgs<Store>) => void;\n selector: () => Store;\n};\n\ntype ContextReturnType<Store, A extends Actions<Store>> = {\n Provider: React.FC<React.PropsWithChildren>;\n useStore: <SelectorOutput = Store>(\n selector?: (store: Store) => SelectorOutput,\n options?: SelectorOptions<SelectorOutput>\n ) => UseStoreReturnType<Store, SelectorOutput>;\n useActions: () => Prettify<ExtractActionKeys<A>>;\n useSetStore: () => (value: SetterArgs<Store>) => void;\n subscribe: <SelectorOutput = Store>(\n selector: (store: Store) => SelectorOutput,\n callback: (state: SelectorOutput) => void,\n options?: SelectorOptions<SelectorOutput>\n ) => () => void;\n unsubscribe: (callback: () => void) => void;\n};\n\nfunction isFunction(value: any): value is (prev: any) => any {\n return typeof value === \"function\";\n}\n\nexport function createContextStore<Store, A extends Actions<Store> = {}>(\n ...args: Extract<A, { payload: A }> extends { payload: infer Payload }\n ? [initialState: Store, actions?: A, options?: ContextOptions]\n : [initialState: Store, options?: ContextOptions]\n): ContextReturnType<Store, A>;\nexport function createContextStore<Store, A extends Actions<Store> = {}>(\n initialState: Store,\n actions: A = {} as A,\n options: ContextOptions = {}\n) {\n let globalStore: Store | undefined = options.global\n ? initialState\n : undefined;\n\n function useStoreData({\n defaultSubscriber = [],\n }: {\n defaultSubscriber?: ((state: Store) => void)[];\n } = {}): {\n get: () => Store;\n set: (value: SetterArgs<Store>) => void;\n subscribe: (callback: (state: Store) => void) => () => void;\n } {\n const store = useRef<Store>(globalStore ?? initialState);\n\n const get = useCallback(() => store.current, []);\n\n const subscribers = useRef(\n new Set<(state: Store) => void>(defaultSubscriber)\n );\n\n const set = useCallback((value: SetterArgs<Store>) => {\n store.current = isFunction(value) ? value(store.current) : value;\n\n if (options.global) {\n globalStore = store.current;\n }\n\n subscribers.current.forEach((callback) => callback(store.current));\n }, []);\n\n const subscribe = useCallback((callback: (state: Store) => void) => {\n subscribers.current.add(callback);\n\n return () => subscribers.current.delete(callback);\n }, []);\n\n return {\n get,\n set,\n subscribe,\n };\n }\n\n type UseStoreDataReturnType = ReturnType<typeof useStoreData>;\n\n const StoreContext = createContext<UseStoreDataReturnType | null>(null);\n\n /**\n * This is the provider that will be used to wrap the react component tree\n * to provide the store to all the components in the tree.\n */\n function Provider({ children }: React.PropsWithChildren) {\n return (\n <StoreContext.Provider\n value={useStoreData({ defaultSubscriber: [observable.broadcast] })}\n >\n {children}\n </StoreContext.Provider>\n );\n }\n\n /**\n * This holds all the observables that are subscribed to the store\n * but not being actively used by any component. Helps to broadcast\n * store updates to all the observables that are interested in reacting\n * to state outside the react component tree.\n */\n const observers = new Set<(state: Store) => void>();\n\n function subscribeExternal<SelectorOutput = Store>(\n selector: (store: Store) => SelectorOutput = (store) =>\n store as unknown as SelectorOutput,\n callback: (state: SelectorOutput) => void,\n compare: SelectorOptions<SelectorOutput> = shallowEqual\n ): () => void {\n let lastSelectedState: SelectorOutput | undefined;\n\n const shouldSendUpdates = (newSelectedState: SelectorOutput) => {\n if (\n lastSelectedState === undefined ||\n !compare(lastSelectedState, newSelectedState)\n ) {\n lastSelectedState = newSelectedState;\n\n return true;\n }\n\n return false;\n };\n\n const selectedCb = (store: Store) => {\n const selected = selector(store);\n const shouldSend = shouldSendUpdates(selected);\n\n if (shouldSend) {\n callback(selector(store));\n }\n };\n observers.add(selectedCb);\n\n return () => observers.delete(selectedCb);\n }\n\n /**\n * A simple observable that proxy store updates to all the subscribers\n * that are interested in reacting to state outside the react component tree.\n */\n const observable = {\n subscribe: subscribeExternal,\n unsubscribe: (callback: (state: Store) => void) => {\n observers.delete(callback);\n },\n broadcast: (state: Store) => {\n observers.forEach((callback) => callback(state));\n },\n } as const;\n\n /**\n * This is the hook that will be used to access the store from any component\n * in the react component tree.\n * @param selector A function that will be used to select the part of the store\n * that is needed by the component.\n * @param options Options to customize the behavior of the hook.\n * @returns An object with the selected state, a function to update the store\n * and a function to get the entire store.\n * @example\n * ```tsx\n * const { get, set } = useStore(store => store.user);\n * const { get, set } = useStore(store => store.user, { deepEqual: false });\n * const { get, set } = useStore(store => store.user, {\n * compare: (first, second) => first.id === second.id\n * });\n * ```\n */\n function useStore<SelectorOutput = Store>(\n selector: (store: Store) => SelectorOutput = (store) =>\n store as unknown as SelectorOutput,\n compare: SelectorOptions<SelectorOutput> = options.compare ?? shallowEqual\n ): UseStoreReturnType<Store, SelectorOutput> {\n const store = useContext(StoreContext);\n const lastSelectedState = useRef<SelectorOutput | undefined>(undefined);\n\n if (!store) {\n throw new Error(\n `[${LIB_NAME}] Store not found. Make sure the component is wrapped in a ${Provider} component.`\n );\n }\n\n const state = useSyncExternalStore(\n store.subscribe,\n () => {\n const selectedState = selector(store.get());\n\n if (\n lastSelectedState.current === undefined ||\n !compare(lastSelectedState.current, selectedState)\n ) {\n lastSelectedState.current = selectedState;\n }\n\n return lastSelectedState.current;\n },\n () => selector(initialState)\n );\n\n return {\n state,\n get: () => state,\n set: store.set,\n selector: () => store.get(),\n };\n }\n\n function useActions() {\n const store = useContext(StoreContext);\n\n if (!store) {\n throw new Error(\n `[${LIB_NAME}] Store not found. Make sure the component is wrapped in a ${Provider} component.`\n );\n }\n\n const actionProxy = useMemo(\n () =>\n new Proxy(actions, {\n get: (target, prop) => {\n const action = target[prop as string];\n\n if (action) {\n return (args: Parameters<typeof action>[\"1\"]) => {\n action(\n {\n set: store.set,\n get: store.get,\n },\n {\n payload: args,\n }\n );\n };\n }\n },\n set: () => {\n throw new Error(`[${LIB_NAME}] Actions cannot be updated`);\n },\n }),\n []\n );\n\n return actionProxy as unknown as ExtractActionKeys<typeof actions>;\n }\n\n const useSetStore = () => useStore(() => false).set;\n\n return {\n Provider,\n useStore,\n useSetStore,\n useActions,\n subscribe: observable.subscribe,\n unsubscribe: observable.unsubscribe,\n };\n}\n"],"mappings":"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","names":["__defProp","__getOwnPropDesc","__getOwnPropNames","__hasOwnProp","__copyProps","shallowEqual"]}
1
+ {"version":3,"sources":["../../utils/dist/comparison/index.js","../src/store.tsx"],"sourcesContent":["\"use strict\";\nvar __defProp = Object.defineProperty;\nvar __getOwnPropDesc = Object.getOwnPropertyDescriptor;\nvar __getOwnPropNames = Object.getOwnPropertyNames;\nvar __hasOwnProp = Object.prototype.hasOwnProperty;\nvar __export = (target, all) => {\n for (var name in all)\n __defProp(target, name, { get: all[name], enumerable: true });\n};\nvar __copyProps = (to, from, except, desc) => {\n if (from && typeof from === \"object\" || typeof from === \"function\") {\n for (let key of __getOwnPropNames(from))\n if (!__hasOwnProp.call(to, key) && key !== except)\n __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });\n }\n return to;\n};\nvar __toCommonJS = (mod) => __copyProps(__defProp({}, \"__esModule\", { value: true }), mod);\n\n// src/comparison/index.ts\nvar comparison_exports = {};\n__export(comparison_exports, {\n shallowEqual: () => shallowEqual\n});\nmodule.exports = __toCommonJS(comparison_exports);\n\n// src/comparison/shallowEqual.ts\nfunction shallowEqual(objA, objB) {\n if (Object.is(objA, objB)) {\n return true;\n }\n if (typeof objA !== \"object\" || objA === null || typeof objB !== \"object\" || objB === null) {\n return false;\n }\n if (objA instanceof Map && objB instanceof Map) {\n if (objA.size !== objB.size) return false;\n for (const [key, value] of objA) {\n if (!Object.is(value, objB.get(key))) {\n return false;\n }\n }\n return true;\n }\n if (objA instanceof Set && objB instanceof Set) {\n if (objA.size !== objB.size) return false;\n for (const value of objA) {\n if (!objB.has(value)) {\n return false;\n }\n }\n return true;\n }\n const keysA = Object.keys(objA);\n if (keysA.length !== Object.keys(objB).length) {\n return false;\n }\n for (let i = 0; i < keysA.length; i++) {\n if (!Object.prototype.hasOwnProperty.call(objB, keysA[i]) || !Object.is(objA[keysA[i]], objB[keysA[i]])) {\n return false;\n }\n }\n return true;\n}\n// Annotate the CommonJS export names for ESM import in node:\n0 && (module.exports = {\n shallowEqual\n});\n","import React, {\n createContext,\n useCallback,\n useContext,\n useMemo,\n useRef,\n useSyncExternalStore,\n} from \"react\";\nimport { shallowEqual } from \"@pixotope/utils/comparison\";\n\nconst LIB_NAME = \"@pixotope/react-context-store\";\n\nexport type SelectorOptions<Selected> = (\n first: Selected,\n second: Selected\n) => boolean;\n\nexport type ContextOptions = {\n /**\n * If true, the store state will be preserved across mounts and un-mounts\n * of the Provider.\n * @default false\n */\n global?: boolean;\n /**\n * A function that will be used to compare the selected state.\n * @default shallowEqual\n */\n compare?: SelectorOptions<unknown>;\n};\n\nexport type SetterArgs<Store> = Store | ((prev: Store) => Store);\ntype ExtractActionKeys<T> = {\n [K in keyof T]: T[K] extends (\n stateProps: never,\n action: infer A\n ) => void | Promise<void>\n ? A extends ActionablePayload<infer Payload>\n ? Payload extends undefined\n ? () => void\n : (payload: Payload) => void\n : () => void\n : never;\n};\n\ntype Prettify<T> = {\n [K in keyof T]: T[K];\n} & {};\n\nexport type ActionablePayload<Payload = any> = {\n payload: Payload;\n};\n\ntype StateActionProps<Store> = {\n set: (value: SetterArgs<Store>) => void;\n get: () => Store;\n};\n\ntype Actions<Store> = {\n [key: string]: (\n stateProps: StateActionProps<Store>,\n action: ActionablePayload\n ) => void | Promise<void>;\n};\n\ntype UseStoreReturnType<Store, SelectorOutput> = {\n state: SelectorOutput;\n get: () => SelectorOutput;\n set: (value: SetterArgs<Store>) => void;\n selector: () => Store;\n};\n\ntype ContextReturnType<Store, A extends Actions<Store>> = {\n Provider: React.FC<React.PropsWithChildren>;\n useStore: <SelectorOutput = Store>(\n selector?: (store: Store) => SelectorOutput,\n options?: SelectorOptions<SelectorOutput>\n ) => UseStoreReturnType<Store, SelectorOutput>;\n useActions: () => Prettify<ExtractActionKeys<A>>;\n useSetStore: () => (value: SetterArgs<Store>) => void;\n subscribe: <SelectorOutput = Store>(\n selector: (store: Store) => SelectorOutput,\n callback: (state: SelectorOutput) => void,\n options?: SelectorOptions<SelectorOutput>\n ) => () => void;\n unsubscribe: (callback: () => void) => void;\n};\n\nfunction isFunction(value: any): value is (prev: any) => any {\n return typeof value === \"function\";\n}\n\nexport function createContextStore<Store, A extends Actions<Store> = {}>(\n ...args: Extract<A, { payload: A }> extends { payload: infer Payload }\n ? [initialState: Store, actions?: A, options?: ContextOptions]\n : [initialState: Store, options?: ContextOptions]\n): ContextReturnType<Store, A>;\nexport function createContextStore<Store, A extends Actions<Store> = {}>(\n initialState: Store,\n actions: A = {} as A,\n options: ContextOptions = {}\n) {\n let globalStore: Store | undefined = options.global\n ? initialState\n : undefined;\n\n function useStoreData({\n defaultSubscriber = [],\n }: {\n defaultSubscriber?: ((state: Store) => void)[];\n } = {}): {\n get: () => Store;\n set: (value: SetterArgs<Store>) => void;\n subscribe: (callback: (state: Store) => void) => () => void;\n } {\n const store = useRef<Store>(globalStore ?? initialState);\n\n const get = useCallback(() => store.current, []);\n\n const subscribers = useRef(\n new Set<(state: Store) => void>(defaultSubscriber)\n );\n\n const set = useCallback((value: SetterArgs<Store>) => {\n store.current = isFunction(value) ? value(store.current) : value;\n\n if (options.global) {\n globalStore = store.current;\n }\n\n subscribers.current.forEach((callback) => callback(store.current));\n }, []);\n\n const subscribe = useCallback((callback: (state: Store) => void) => {\n subscribers.current.add(callback);\n\n return () => subscribers.current.delete(callback);\n }, []);\n\n return {\n get,\n set,\n subscribe,\n };\n }\n\n type UseStoreDataReturnType = ReturnType<typeof useStoreData>;\n\n const StoreContext = createContext<UseStoreDataReturnType | null>(null);\n\n /**\n * This is the provider that will be used to wrap the react component tree\n * to provide the store to all the components in the tree.\n */\n function Provider({ children }: React.PropsWithChildren) {\n return (\n <StoreContext.Provider\n value={useStoreData({ defaultSubscriber: [observable.broadcast] })}\n >\n {children}\n </StoreContext.Provider>\n );\n }\n\n /**\n * This holds all the observables that are subscribed to the store\n * but not being actively used by any component. Helps to broadcast\n * store updates to all the observables that are interested in reacting\n * to state outside the react component tree.\n */\n const observers = new Set<(state: Store) => void>();\n\n function subscribeExternal<SelectorOutput = Store>(\n selector: (store: Store) => SelectorOutput = (store) =>\n store as unknown as SelectorOutput,\n callback: (state: SelectorOutput) => void,\n compare: SelectorOptions<SelectorOutput> = shallowEqual\n ): () => void {\n let lastSelectedState: SelectorOutput | undefined;\n\n const shouldSendUpdates = (newSelectedState: SelectorOutput) => {\n if (\n lastSelectedState === undefined ||\n !compare(lastSelectedState, newSelectedState)\n ) {\n lastSelectedState = newSelectedState;\n\n return true;\n }\n\n return false;\n };\n\n const selectedCb = (store: Store) => {\n const selected = selector(store);\n const shouldSend = shouldSendUpdates(selected);\n\n if (shouldSend) {\n callback(selector(store));\n }\n };\n observers.add(selectedCb);\n\n return () => observers.delete(selectedCb);\n }\n\n /**\n * A simple observable that proxy store updates to all the subscribers\n * that are interested in reacting to state outside the react component tree.\n */\n const observable = {\n subscribe: subscribeExternal,\n unsubscribe: (callback: (state: Store) => void) => {\n observers.delete(callback);\n },\n broadcast: (state: Store) => {\n observers.forEach((callback) => callback(state));\n },\n } as const;\n\n /**\n * This is the hook that will be used to access the store from any component\n * in the react component tree.\n * @param selector A function that will be used to select the part of the store\n * that is needed by the component.\n * @param options Options to customize the behavior of the hook.\n * @returns An object with the selected state, a function to update the store\n * and a function to get the entire store.\n * @example\n * ```tsx\n * const { get, set } = useStore(store => store.user);\n * const { get, set } = useStore(store => store.user, { deepEqual: false });\n * const { get, set } = useStore(store => store.user, {\n * compare: (first, second) => first.id === second.id\n * });\n * ```\n */\n function useStore<SelectorOutput = Store>(\n selector: (store: Store) => SelectorOutput = (store) =>\n store as unknown as SelectorOutput,\n compare: SelectorOptions<SelectorOutput> = options.compare ?? shallowEqual\n ): UseStoreReturnType<Store, SelectorOutput> {\n const store = useContext(StoreContext);\n const lastSelectedState = useRef<SelectorOutput | undefined>(undefined);\n\n if (!store) {\n throw new Error(\n `[${LIB_NAME}] Store not found. Make sure the component is wrapped in a ${Provider} component.`\n );\n }\n\n const state = useSyncExternalStore(\n store.subscribe,\n () => {\n const selectedState = selector(store.get());\n\n if (\n lastSelectedState.current === undefined ||\n !compare(lastSelectedState.current, selectedState)\n ) {\n lastSelectedState.current = selectedState;\n }\n\n return lastSelectedState.current;\n },\n () => selector(initialState)\n );\n\n return {\n state,\n get: () => state,\n set: store.set,\n selector: () => store.get(),\n };\n }\n\n function useActions() {\n const store = useContext(StoreContext);\n\n if (!store) {\n throw new Error(\n `[${LIB_NAME}] Store not found. Make sure the component is wrapped in a ${Provider} component.`\n );\n }\n\n const actionProxy = useMemo(\n () =>\n new Proxy(actions, {\n get: (target, prop) => {\n const action = target[prop as string];\n\n if (action) {\n return (args: Parameters<typeof action>[\"1\"]) => {\n action(\n {\n set: store.set,\n get: store.get,\n },\n {\n payload: args,\n }\n );\n };\n }\n },\n set: () => {\n throw new Error(`[${LIB_NAME}] Actions cannot be updated`);\n },\n }),\n []\n );\n\n return actionProxy as unknown as ExtractActionKeys<typeof actions>;\n }\n\n const useSetStore = () => useStore(() => false).set;\n\n return {\n Provider,\n useStore,\n useSetStore,\n useActions,\n subscribe: observable.subscribe,\n unsubscribe: observable.unsubscribe,\n };\n}\n"],"mappings":"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","names":["__defProp","__getOwnPropDesc","__getOwnPropNames","__hasOwnProp","__copyProps","shallowEqual"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pixotope/react-context-store",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "",
5
5
  "private": false,
6
6
  "main": "dist/index.js",
@@ -19,15 +19,14 @@
19
19
  "react-dom": "^19.1.1",
20
20
  "tsup": "^8.5.0",
21
21
  "typescript": "^5.7.2",
22
- "use-sync-external-store": "^1.5.0",
23
22
  "vitest": "^3.2.4",
24
23
  "@pixotope/utils": "0.1.0"
25
24
  },
26
25
  "peerDependencies": {
27
- "react": ">=17.0.0"
26
+ "react": ">=18.0.0"
28
27
  },
29
28
  "scripts": {
30
- "build": "tsup src/index.ts --format cjs,esm --dts --sourcemap --external react --external use-sync-external-store",
29
+ "build": "tsup src/index.ts --format cjs,esm --dts --sourcemap --external react",
31
30
  "check-types": "tsc --noEmit",
32
31
  "test": "vitest"
33
32
  }
package/src/store.tsx CHANGED
@@ -4,9 +4,9 @@ import React, {
4
4
  useContext,
5
5
  useMemo,
6
6
  useRef,
7
+ useSyncExternalStore,
7
8
  } from "react";
8
9
  import { shallowEqual } from "@pixotope/utils/comparison";
9
- import { useSyncExternalStore } from "use-sync-external-store/shim";
10
10
 
11
11
  const LIB_NAME = "@pixotope/react-context-store";
12
12