@thefoxieflow/signalctx 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -128,7 +128,7 @@ Scoped update:
128
128
 
129
129
  ```ts
130
130
  // book must be object for selector
131
- const setBook = useSetSignal(store, s => s.book)
131
+ const setBook = useSet(store, s => s.book)
132
132
 
133
133
 
134
134
  // put: update an object
@@ -219,7 +219,7 @@ function Book() {
219
219
 
220
220
  ```tsx
221
221
  function Increment() {
222
- const set = useStore.useSetter()
222
+ const set = useStore.useSet()
223
223
 
224
224
  return (
225
225
  <button onClick={() =>
@@ -308,7 +308,7 @@ function AppB(){
308
308
  const storeABook = useStore(s => s.book,{ storeName :"storeA" })
309
309
 
310
310
  // same apply to setter
311
- const setBookStoreA = useStore.useSetter((s)=>s.book, {storeName : "storeA"})
311
+ const setBookStoreA = useStore.useSet((s)=>s.book, {storeName : "storeA"})
312
312
 
313
313
  const handleClick = (text)=>{
314
314
  setCountStoreA((s) => {
@@ -327,7 +327,7 @@ Each store is independent.
327
327
 
328
328
  ## 🌐 Server-Side Rendering (SSR)
329
329
 
330
- `signalctx` is SSR-safe.
330
+ `Signal Ctx` is SSR-safe.
331
331
 
332
332
  * Uses `useSyncExternalStore`
333
333
  * Identical snapshot logic on server & client
package/dist/index.d.mts CHANGED
@@ -1,49 +1,36 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import { PropsWithChildren } from 'react';
3
3
 
4
- type SetStateAction<T> = T | ((prev: T) => T);
4
+ type SetAction<T> = T | ((prev: T) => void);
5
5
  type Subscriber = () => void;
6
- /** for controlling store internal state without notifying subscribers
7
- * @function calling the store internal state reference
8
- * @method on subscribe to state changes
9
- * @method set update the state without notifying subscribers
10
- * @method reset reset the state to initial value without notifying subscribers
11
- * @method notify manually notify all subscribers
12
- */
13
- type InnerStore<T> = {
6
+ type Signal<T> = {
14
7
  (): T;
15
8
  on: (sub: Subscriber) => () => void;
16
9
  notify: () => void;
17
10
  reset: () => void;
18
- set: (action: SetStateAction<T>) => void;
11
+ set: (action: SetAction<T>) => void;
19
12
  };
20
- /**
21
- * @function calling the store returns a copy of the internal state
22
- * @method on subscribe to state changes
23
- * @method set update the state with notifying subscribers
24
- * @method reset reset the state to initial value with notifying subscribers
25
- * @property $ access to non-notifying methods
26
- */
27
13
  type Store<T> = {
28
14
  (): T;
29
15
  on: (sub: Subscriber) => () => void;
30
16
  reset: () => void;
31
- set: (action: SetStateAction<T>) => void;
32
- $: InnerStore<T>;
17
+ set: (action: SetAction<T>) => void;
18
+ $: Signal<T>;
33
19
  };
34
- declare const useValue: <T extends object, Dest = T>(store: Store<T>, selector?: (state: T) => Dest) => Dest;
35
- declare const useSet: <T extends object = any, Dest extends object = T>(store: Store<T>, selector?: (state: T) => Dest) => (action: SetStateAction<Dest>) => Dest;
36
20
  type StoreOption = {
37
21
  storeName?: string;
38
22
  };
23
+ declare const newStore: <T extends Record<string, any>>(init: () => T) => Store<T>;
24
+ declare const useValue: <T extends object, Dest = T>(store: Store<T>, selector?: (state: T) => Dest) => Dest;
25
+ declare const useSet: <T extends object = any, Dest extends object = T>(store: Store<T>, selector?: (state: T) => Dest) => (action: SetAction<Dest>) => void;
39
26
  declare function createCtx<T extends object>(init: () => T): {
40
27
  <Dest = any>(selector: (state: T) => Dest, opt?: StoreOption): Dest;
41
- provide: (opt?: {
28
+ Provider: ({ children, value, storeName, }: PropsWithChildren<{
42
29
  value?: T;
43
30
  storeName?: string;
44
- }) => ({ children }: PropsWithChildren) => react_jsx_runtime.JSX.Element;
45
- useSet: <Dest extends object = T>(selector?: (state: T) => Dest, opt?: StoreOption) => (action: SetStateAction<Dest>) => Dest;
31
+ }>) => react_jsx_runtime.JSX.Element;
32
+ useSet: <Dest extends object = T>(selector?: (state: T) => Dest, opt?: StoreOption) => (action: SetAction<Dest>) => void;
46
33
  useStore: (opt?: StoreOption) => Store<T>;
47
34
  };
48
35
 
49
- export { type InnerStore, type SetStateAction, type Store, type Subscriber, createCtx, useSet, useValue };
36
+ export { type SetAction, type Signal, type Store, type Subscriber, createCtx, newStore, useSet, useValue };
package/dist/index.d.ts CHANGED
@@ -1,49 +1,36 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import { PropsWithChildren } from 'react';
3
3
 
4
- type SetStateAction<T> = T | ((prev: T) => T);
4
+ type SetAction<T> = T | ((prev: T) => void);
5
5
  type Subscriber = () => void;
6
- /** for controlling store internal state without notifying subscribers
7
- * @function calling the store internal state reference
8
- * @method on subscribe to state changes
9
- * @method set update the state without notifying subscribers
10
- * @method reset reset the state to initial value without notifying subscribers
11
- * @method notify manually notify all subscribers
12
- */
13
- type InnerStore<T> = {
6
+ type Signal<T> = {
14
7
  (): T;
15
8
  on: (sub: Subscriber) => () => void;
16
9
  notify: () => void;
17
10
  reset: () => void;
18
- set: (action: SetStateAction<T>) => void;
11
+ set: (action: SetAction<T>) => void;
19
12
  };
20
- /**
21
- * @function calling the store returns a copy of the internal state
22
- * @method on subscribe to state changes
23
- * @method set update the state with notifying subscribers
24
- * @method reset reset the state to initial value with notifying subscribers
25
- * @property $ access to non-notifying methods
26
- */
27
13
  type Store<T> = {
28
14
  (): T;
29
15
  on: (sub: Subscriber) => () => void;
30
16
  reset: () => void;
31
- set: (action: SetStateAction<T>) => void;
32
- $: InnerStore<T>;
17
+ set: (action: SetAction<T>) => void;
18
+ $: Signal<T>;
33
19
  };
34
- declare const useValue: <T extends object, Dest = T>(store: Store<T>, selector?: (state: T) => Dest) => Dest;
35
- declare const useSet: <T extends object = any, Dest extends object = T>(store: Store<T>, selector?: (state: T) => Dest) => (action: SetStateAction<Dest>) => Dest;
36
20
  type StoreOption = {
37
21
  storeName?: string;
38
22
  };
23
+ declare const newStore: <T extends Record<string, any>>(init: () => T) => Store<T>;
24
+ declare const useValue: <T extends object, Dest = T>(store: Store<T>, selector?: (state: T) => Dest) => Dest;
25
+ declare const useSet: <T extends object = any, Dest extends object = T>(store: Store<T>, selector?: (state: T) => Dest) => (action: SetAction<Dest>) => void;
39
26
  declare function createCtx<T extends object>(init: () => T): {
40
27
  <Dest = any>(selector: (state: T) => Dest, opt?: StoreOption): Dest;
41
- provide: (opt?: {
28
+ Provider: ({ children, value, storeName, }: PropsWithChildren<{
42
29
  value?: T;
43
30
  storeName?: string;
44
- }) => ({ children }: PropsWithChildren) => react_jsx_runtime.JSX.Element;
45
- useSet: <Dest extends object = T>(selector?: (state: T) => Dest, opt?: StoreOption) => (action: SetStateAction<Dest>) => Dest;
31
+ }>) => react_jsx_runtime.JSX.Element;
32
+ useSet: <Dest extends object = T>(selector?: (state: T) => Dest, opt?: StoreOption) => (action: SetAction<Dest>) => void;
46
33
  useStore: (opt?: StoreOption) => Store<T>;
47
34
  };
48
35
 
49
- export { type InnerStore, type SetStateAction, type Store, type Subscriber, createCtx, useSet, useValue };
36
+ export { type SetAction, type Signal, type Store, type Subscriber, createCtx, newStore, useSet, useValue };
package/dist/index.js CHANGED
@@ -21,18 +21,19 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
21
21
  var index_exports = {};
22
22
  __export(index_exports, {
23
23
  createCtx: () => createCtx,
24
+ newStore: () => newStore,
24
25
  useSet: () => useSet,
25
26
  useValue: () => useValue
26
27
  });
27
28
  module.exports = __toCommonJS(index_exports);
28
29
  var import_react = require("react");
29
30
  var import_jsx_runtime = require("react/jsx-runtime");
30
- var createInnerStore = (init) => {
31
+ var newSignal = (init) => {
31
32
  let ref;
32
33
  const subs = /* @__PURE__ */ new Set();
33
34
  const store = () => ref || (ref = init());
34
35
  store.set = (action) => {
35
- apply(store(), action);
36
+ act(store(), action);
36
37
  };
37
38
  store.reset = () => {
38
39
  ref = init();
@@ -46,23 +47,23 @@ var createInnerStore = (init) => {
46
47
  };
47
48
  return store;
48
49
  };
49
- var isFunction = (val) => typeof val === "function";
50
- var setTargetValue = (target, newVal) => {
51
- if (Object.is(target, newVal)) return target;
50
+ var replaceIfDiff = (target, newVal) => {
51
+ if (Object.is(target, newVal)) return;
52
52
  Object.keys(target).forEach((k) => delete target[k]);
53
53
  Object.keys(newVal).forEach((k) => target[k] = newVal[k]);
54
- return target;
55
54
  };
56
- var apply = (target, action) => {
57
- const val = isFunction(action) ? action(target) : action;
58
- return setTargetValue(target, val);
55
+ var act = (target, action) => {
56
+ if (typeof action === "function") {
57
+ action(target);
58
+ } else {
59
+ replaceIfDiff(target, action);
60
+ }
59
61
  };
60
- function createStore(init) {
61
- const $ = createInnerStore(init);
62
- const store = () => {
63
- const ref = $();
64
- return { ...ref };
65
- };
62
+ var newStore = (init) => {
63
+ const $ = newSignal(init);
64
+ const store = () => $();
65
+ store.$ = $;
66
+ store.on = $.on;
66
67
  store.reset = () => {
67
68
  $.reset();
68
69
  $.notify();
@@ -71,29 +72,29 @@ function createStore(init) {
71
72
  $.set(action);
72
73
  $.notify();
73
74
  };
74
- store.on = $.on;
75
- store.$ = $;
76
75
  return store;
77
- }
76
+ };
78
77
  var useValue = (store, selector) => {
79
78
  const get = () => selector ? selector(store()) : store();
80
79
  return (0, import_react.useSyncExternalStore)(store.on, get, get);
81
80
  };
82
81
  var useSet = (store, selector) => {
83
82
  const setter = (action) => {
84
- const current = store();
85
- const target = selector ? selector(current) : current;
86
- apply(target, action);
87
- store.set(current);
88
- return target;
83
+ const ref = store.$();
84
+ const targetRef = selector ? selector(ref) : ref;
85
+ act(targetRef, action);
86
+ store.$.notify();
89
87
  };
90
88
  return setter;
91
89
  };
92
90
  function createCtx(init) {
93
- const ctx = (0, import_react.createContext)(createStore(init));
91
+ const ctx = (0, import_react.createContext)(null);
94
92
  const stores = /* @__PURE__ */ new Map();
95
- const initStore = (name, init2) => {
96
- if (!stores.has(name)) stores.set(name, createStore(init2));
93
+ const initStore = (init2, name) => {
94
+ if (!name) return newStore(init2);
95
+ if (!stores.has(name)) {
96
+ stores.set(name, newStore(init2));
97
+ }
97
98
  return stores.get(name);
98
99
  };
99
100
  const useStore = (opt) => {
@@ -102,19 +103,29 @@ function createCtx(init) {
102
103
  if (!store) throw new Error("useCtx must be used within a Provider");
103
104
  return store;
104
105
  };
105
- const provide = (opt = {}) => {
106
- const storeInit = opt.value ? () => opt.value : init;
107
- const storeName = opt.storeName || "ctx__store";
108
- const Provider = ({ children }) => {
109
- const store = initStore(storeName, storeInit);
110
- (0, import_react.useEffect)(() => () => {
111
- stores.delete(storeName);
112
- }, []);
113
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ctx.Provider, { value: store, children });
114
- };
115
- return Provider;
106
+ const Provider = ({
107
+ children,
108
+ value,
109
+ storeName
110
+ }) => {
111
+ const [store, name] = (0, import_react.useMemo)(() => {
112
+ const storeInit = value ? () => value : init;
113
+ const store2 = initStore(storeInit, storeName);
114
+ return [store2, storeName];
115
+ }, [value, storeName]);
116
+ (0, import_react.useEffect)(
117
+ () => () => {
118
+ if (name) stores.delete(name);
119
+ },
120
+ [store, name]
121
+ );
122
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(ctx.Provider, { value: store, children: [
123
+ " ",
124
+ children,
125
+ " "
126
+ ] });
116
127
  };
117
- const use = (selector, opt) => {
128
+ const useSelect = (selector, opt) => {
118
129
  const store = useStore(opt);
119
130
  return useValue(store, selector);
120
131
  };
@@ -122,14 +133,15 @@ function createCtx(init) {
122
133
  const store = useStore(opt);
123
134
  return useSet(store, selector);
124
135
  };
125
- use.provide = provide;
126
- use.useSet = useSetter;
127
- use.useStore = useStore;
128
- return use;
136
+ useSelect.Provider = Provider;
137
+ useSelect.useSet = useSetter;
138
+ useSelect.useStore = useStore;
139
+ return useSelect;
129
140
  }
130
141
  // Annotate the CommonJS export names for ESM import in node:
131
142
  0 && (module.exports = {
132
143
  createCtx,
144
+ newStore,
133
145
  useSet,
134
146
  useValue
135
147
  });
package/dist/index.mjs CHANGED
@@ -3,15 +3,16 @@ import {
3
3
  createContext,
4
4
  useContext,
5
5
  useEffect,
6
+ useMemo,
6
7
  useSyncExternalStore
7
8
  } from "react";
8
- import { jsx } from "react/jsx-runtime";
9
- var createInnerStore = (init) => {
9
+ import { jsxs } from "react/jsx-runtime";
10
+ var newSignal = (init) => {
10
11
  let ref;
11
12
  const subs = /* @__PURE__ */ new Set();
12
13
  const store = () => ref || (ref = init());
13
14
  store.set = (action) => {
14
- apply(store(), action);
15
+ act(store(), action);
15
16
  };
16
17
  store.reset = () => {
17
18
  ref = init();
@@ -25,23 +26,23 @@ var createInnerStore = (init) => {
25
26
  };
26
27
  return store;
27
28
  };
28
- var isFunction = (val) => typeof val === "function";
29
- var setTargetValue = (target, newVal) => {
30
- if (Object.is(target, newVal)) return target;
29
+ var replaceIfDiff = (target, newVal) => {
30
+ if (Object.is(target, newVal)) return;
31
31
  Object.keys(target).forEach((k) => delete target[k]);
32
32
  Object.keys(newVal).forEach((k) => target[k] = newVal[k]);
33
- return target;
34
33
  };
35
- var apply = (target, action) => {
36
- const val = isFunction(action) ? action(target) : action;
37
- return setTargetValue(target, val);
34
+ var act = (target, action) => {
35
+ if (typeof action === "function") {
36
+ action(target);
37
+ } else {
38
+ replaceIfDiff(target, action);
39
+ }
38
40
  };
39
- function createStore(init) {
40
- const $ = createInnerStore(init);
41
- const store = () => {
42
- const ref = $();
43
- return { ...ref };
44
- };
41
+ var newStore = (init) => {
42
+ const $ = newSignal(init);
43
+ const store = () => $();
44
+ store.$ = $;
45
+ store.on = $.on;
45
46
  store.reset = () => {
46
47
  $.reset();
47
48
  $.notify();
@@ -50,29 +51,29 @@ function createStore(init) {
50
51
  $.set(action);
51
52
  $.notify();
52
53
  };
53
- store.on = $.on;
54
- store.$ = $;
55
54
  return store;
56
- }
55
+ };
57
56
  var useValue = (store, selector) => {
58
57
  const get = () => selector ? selector(store()) : store();
59
58
  return useSyncExternalStore(store.on, get, get);
60
59
  };
61
60
  var useSet = (store, selector) => {
62
61
  const setter = (action) => {
63
- const current = store();
64
- const target = selector ? selector(current) : current;
65
- apply(target, action);
66
- store.set(current);
67
- return target;
62
+ const ref = store.$();
63
+ const targetRef = selector ? selector(ref) : ref;
64
+ act(targetRef, action);
65
+ store.$.notify();
68
66
  };
69
67
  return setter;
70
68
  };
71
69
  function createCtx(init) {
72
- const ctx = createContext(createStore(init));
70
+ const ctx = createContext(null);
73
71
  const stores = /* @__PURE__ */ new Map();
74
- const initStore = (name, init2) => {
75
- if (!stores.has(name)) stores.set(name, createStore(init2));
72
+ const initStore = (init2, name) => {
73
+ if (!name) return newStore(init2);
74
+ if (!stores.has(name)) {
75
+ stores.set(name, newStore(init2));
76
+ }
76
77
  return stores.get(name);
77
78
  };
78
79
  const useStore = (opt) => {
@@ -81,19 +82,29 @@ function createCtx(init) {
81
82
  if (!store) throw new Error("useCtx must be used within a Provider");
82
83
  return store;
83
84
  };
84
- const provide = (opt = {}) => {
85
- const storeInit = opt.value ? () => opt.value : init;
86
- const storeName = opt.storeName || "ctx__store";
87
- const Provider = ({ children }) => {
88
- const store = initStore(storeName, storeInit);
89
- useEffect(() => () => {
90
- stores.delete(storeName);
91
- }, []);
92
- return /* @__PURE__ */ jsx(ctx.Provider, { value: store, children });
93
- };
94
- return Provider;
85
+ const Provider = ({
86
+ children,
87
+ value,
88
+ storeName
89
+ }) => {
90
+ const [store, name] = useMemo(() => {
91
+ const storeInit = value ? () => value : init;
92
+ const store2 = initStore(storeInit, storeName);
93
+ return [store2, storeName];
94
+ }, [value, storeName]);
95
+ useEffect(
96
+ () => () => {
97
+ if (name) stores.delete(name);
98
+ },
99
+ [store, name]
100
+ );
101
+ return /* @__PURE__ */ jsxs(ctx.Provider, { value: store, children: [
102
+ " ",
103
+ children,
104
+ " "
105
+ ] });
95
106
  };
96
- const use = (selector, opt) => {
107
+ const useSelect = (selector, opt) => {
97
108
  const store = useStore(opt);
98
109
  return useValue(store, selector);
99
110
  };
@@ -101,13 +112,14 @@ function createCtx(init) {
101
112
  const store = useStore(opt);
102
113
  return useSet(store, selector);
103
114
  };
104
- use.provide = provide;
105
- use.useSet = useSetter;
106
- use.useStore = useStore;
107
- return use;
115
+ useSelect.Provider = Provider;
116
+ useSelect.useSet = useSetter;
117
+ useSelect.useStore = useStore;
118
+ return useSelect;
108
119
  }
109
120
  export {
110
121
  createCtx,
122
+ newStore,
111
123
  useSet,
112
124
  useValue
113
125
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thefoxieflow/signalctx",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Lightweight signal-based React context store",
5
5
  "main": "dist/index.cjs",
6
6
  "module": "dist/index.js",