signalium 1.1.0 → 1.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.
@@ -1,12 +1,12 @@
1
1
 
2
- > signalium@1.1.0 build
2
+ > signalium@1.1.1 build
3
3
  > npm run build:esm && npm run build:cjs
4
4
 
5
5
 
6
- > signalium@1.1.0 build:esm
6
+ > signalium@1.1.1 build:esm
7
7
  > tsc
8
8
 
9
9
 
10
- > signalium@1.1.0 build:cjs
10
+ > signalium@1.1.1 build:cjs
11
11
  > tsc --module commonjs --outDir dist/cjs --moduleResolution node
12
12
 
package/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # signalium
2
2
 
3
+ ## 1.1.1
4
+
5
+ ### Patch Changes
6
+
7
+ - dd4a7f9: Fix root context inheritance
8
+
3
9
  ## 1.1.0
4
10
 
5
11
  ### Minor Changes
@@ -1,8 +1,7 @@
1
1
  import { ContextPair } from '../internals/contexts.js';
2
- export declare function ContextProvider<C extends unknown[]>({ children, contexts, inherit, root, }: {
2
+ export declare function ContextProvider<C extends unknown[]>({ children, contexts, inherit, }: {
3
3
  children: React.ReactNode;
4
- contexts: [...ContextPair<C>];
4
+ contexts?: [...ContextPair<C>] | [];
5
5
  inherit?: boolean;
6
- root?: boolean;
7
6
  }): import("react/jsx-runtime").JSX.Element;
8
7
  //# sourceMappingURL=provider.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../../../src/react/provider.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAe,WAAW,EAAe,MAAM,0BAA0B,CAAC;AAEjF,wBAAgB,eAAe,CAAC,CAAC,SAAS,OAAO,EAAE,EAAE,EACnD,QAAQ,EACR,QAAQ,EACR,OAAc,EACd,IAAY,GACb,EAAE;IACD,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,QAAQ,EAAE,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;IAC9B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB,2CAKA"}
1
+ {"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../../../src/react/provider.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAe,WAAW,EAA2B,MAAM,0BAA0B,CAAC;AAE7F,wBAAgB,eAAe,CAAC,CAAC,SAAS,OAAO,EAAE,EAAE,EACnD,QAAQ,EACR,QAAa,EACb,OAAc,GACf,EAAE;IACD,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,QAAQ,CAAC,EAAE,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC;IACpC,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,2CAKA"}
@@ -5,8 +5,8 @@ const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const react_1 = require("react");
6
6
  const context_js_1 = require("./context.js");
7
7
  const contexts_js_1 = require("../internals/contexts.js");
8
- function ContextProvider({ children, contexts, inherit = true, root = false, }) {
9
- const parentScope = (0, react_1.useContext)(context_js_1.ScopeContext);
8
+ function ContextProvider({ children, contexts = [], inherit = true, }) {
9
+ const parentScope = (0, react_1.useContext)(context_js_1.ScopeContext) ?? contexts_js_1.ROOT_SCOPE;
10
10
  const scope = new contexts_js_1.SignalScope(contexts, inherit ? parentScope : undefined);
11
11
  return (0, jsx_runtime_1.jsx)(context_js_1.ScopeContext.Provider, { value: scope, children: children });
12
12
  }
@@ -1 +1 @@
1
- {"version":3,"file":"provider.js","sourceRoot":"","sources":["../../../src/react/provider.tsx"],"names":[],"mappings":";;AAIA,0CAeC;;AAnBD,iCAAmC;AACnC,6CAA4C;AAC5C,0DAAiF;AAEjF,SAAgB,eAAe,CAAsB,EACnD,QAAQ,EACR,QAAQ,EACR,OAAO,GAAG,IAAI,EACd,IAAI,GAAG,KAAK,GAMb;IACC,MAAM,WAAW,GAAG,IAAA,kBAAU,EAAC,yBAAY,CAAC,CAAC;IAC7C,MAAM,KAAK,GAAG,IAAI,yBAAW,CAAC,QAA6C,EAAE,OAAO,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;IAEhH,OAAO,uBAAC,yBAAY,CAAC,QAAQ,IAAC,KAAK,EAAE,KAAK,YAAG,QAAQ,GAAyB,CAAC;AACjF,CAAC"}
1
+ {"version":3,"file":"provider.js","sourceRoot":"","sources":["../../../src/react/provider.tsx"],"names":[],"mappings":";;AAIA,0CAaC;;AAjBD,iCAAmC;AACnC,6CAA4C;AAC5C,0DAA6F;AAE7F,SAAgB,eAAe,CAAsB,EACnD,QAAQ,EACR,QAAQ,GAAG,EAAE,EACb,OAAO,GAAG,IAAI,GAKf;IACC,MAAM,WAAW,GAAG,IAAA,kBAAU,EAAC,yBAAY,CAAC,IAAI,wBAAU,CAAC;IAC3D,MAAM,KAAK,GAAG,IAAI,yBAAW,CAAC,QAA6C,EAAE,OAAO,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;IAEhH,OAAO,uBAAC,yBAAY,CAAC,QAAQ,IAAC,KAAK,EAAE,KAAK,YAAG,QAAQ,GAAyB,CAAC;AACjF,CAAC"}
@@ -1,8 +1,7 @@
1
1
  import { ContextPair } from '../internals/contexts.js';
2
- export declare function ContextProvider<C extends unknown[]>({ children, contexts, inherit, root, }: {
2
+ export declare function ContextProvider<C extends unknown[]>({ children, contexts, inherit, }: {
3
3
  children: React.ReactNode;
4
- contexts: [...ContextPair<C>];
4
+ contexts?: [...ContextPair<C>] | [];
5
5
  inherit?: boolean;
6
- root?: boolean;
7
6
  }): import("react/jsx-runtime").JSX.Element;
8
7
  //# sourceMappingURL=provider.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../../../src/react/provider.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAe,WAAW,EAAe,MAAM,0BAA0B,CAAC;AAEjF,wBAAgB,eAAe,CAAC,CAAC,SAAS,OAAO,EAAE,EAAE,EACnD,QAAQ,EACR,QAAQ,EACR,OAAc,EACd,IAAY,GACb,EAAE;IACD,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,QAAQ,EAAE,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;IAC9B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB,2CAKA"}
1
+ {"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../../../src/react/provider.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAe,WAAW,EAA2B,MAAM,0BAA0B,CAAC;AAE7F,wBAAgB,eAAe,CAAC,CAAC,SAAS,OAAO,EAAE,EAAE,EACnD,QAAQ,EACR,QAAa,EACb,OAAc,GACf,EAAE;IACD,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,QAAQ,CAAC,EAAE,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC;IACpC,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,2CAKA"}
@@ -1,9 +1,9 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { useContext } from 'react';
3
3
  import { ScopeContext } from './context.js';
4
- import { SignalScope } from '../internals/contexts.js';
5
- export function ContextProvider({ children, contexts, inherit = true, root = false, }) {
6
- const parentScope = useContext(ScopeContext);
4
+ import { ROOT_SCOPE, SignalScope } from '../internals/contexts.js';
5
+ export function ContextProvider({ children, contexts = [], inherit = true, }) {
6
+ const parentScope = useContext(ScopeContext) ?? ROOT_SCOPE;
7
7
  const scope = new SignalScope(contexts, inherit ? parentScope : undefined);
8
8
  return _jsx(ScopeContext.Provider, { value: scope, children: children });
9
9
  }
@@ -1 +1 @@
1
- {"version":3,"file":"provider.js","sourceRoot":"","sources":["../../../src/react/provider.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AACnC,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAA4B,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAEjF,MAAM,UAAU,eAAe,CAAsB,EACnD,QAAQ,EACR,QAAQ,EACR,OAAO,GAAG,IAAI,EACd,IAAI,GAAG,KAAK,GAMb;IACC,MAAM,WAAW,GAAG,UAAU,CAAC,YAAY,CAAC,CAAC;IAC7C,MAAM,KAAK,GAAG,IAAI,WAAW,CAAC,QAA6C,EAAE,OAAO,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;IAEhH,OAAO,KAAC,YAAY,CAAC,QAAQ,IAAC,KAAK,EAAE,KAAK,YAAG,QAAQ,GAAyB,CAAC;AACjF,CAAC"}
1
+ {"version":3,"file":"provider.js","sourceRoot":"","sources":["../../../src/react/provider.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AACnC,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAA4B,UAAU,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAE7F,MAAM,UAAU,eAAe,CAAsB,EACnD,QAAQ,EACR,QAAQ,GAAG,EAAE,EACb,OAAO,GAAG,IAAI,GAKf;IACC,MAAM,WAAW,GAAG,UAAU,CAAC,YAAY,CAAC,IAAI,UAAU,CAAC;IAC3D,MAAM,KAAK,GAAG,IAAI,WAAW,CAAC,QAA6C,EAAE,OAAO,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;IAEhH,OAAO,KAAC,YAAY,CAAC,QAAQ,IAAC,KAAK,EAAE,KAAK,YAAG,QAAQ,GAAyB,CAAC;AACjF,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "signalium",
3
- "version": "1.1.0",
3
+ "version": "1.1.1",
4
4
  "type": "module",
5
5
  "repository": "https://github.com/pzuraq/signalium",
6
6
  "description": "Chain-reactivity at critical mass",
@@ -65,6 +65,54 @@ describe('contexts', () => {
65
65
  expect(derived()).toBe('Hi, Everyone');
66
66
  });
67
67
 
68
+ test('withContexts inherits from root scope', () => {
69
+ const defaultValue1 = state('default1');
70
+ const defaultValue2 = state('default2');
71
+ const ctx1 = createContext(defaultValue1);
72
+ const ctx2 = createContext(defaultValue2);
73
+ const rootOverride1 = state('root1');
74
+ const rootOverride2 = state('root2');
75
+
76
+ // Set root contexts
77
+ setRootContexts([
78
+ [ctx1, rootOverride1],
79
+ [ctx2, rootOverride2],
80
+ ]);
81
+
82
+ // Create a reactive function that uses both contexts
83
+ const derived = reactive(() => `${useContext(ctx1).get()}-${useContext(ctx2).get()}`);
84
+
85
+ // Should inherit from root scope when no local overrides
86
+ const result1 = withContexts([], () => derived());
87
+ expect(result1).toBe('root1-root2');
88
+
89
+ // Should inherit from root scope for unoverridden contexts
90
+ const localOverride1 = state('local1');
91
+ const result2 = withContexts([[ctx1, localOverride1]], () => derived());
92
+ expect(result2).toBe('local1-root2');
93
+
94
+ // Should use local overrides when provided
95
+ const localOverride2 = state('local2');
96
+ const result3 = withContexts(
97
+ [
98
+ [ctx1, localOverride1],
99
+ [ctx2, localOverride2],
100
+ ],
101
+ () => derived(),
102
+ );
103
+ expect(result3).toBe('local1-local2');
104
+
105
+ // Changes to root contexts should be reflected in inherited contexts
106
+ rootOverride1.set('updated-root1');
107
+ rootOverride2.set('updated-root2');
108
+
109
+ const result4 = withContexts([], () => derived());
110
+ expect(result4).toBe('updated-root1-updated-root2');
111
+
112
+ const result5 = withContexts([[ctx1, localOverride1]], () => derived());
113
+ expect(result5).toBe('local1-updated-root2');
114
+ });
115
+
68
116
  test('async computed maintains context ownership across await boundaries', async () => {
69
117
  const ctx = createContext('default');
70
118
 
@@ -1,6 +1,6 @@
1
1
  import { describe, expect, test } from 'vitest';
2
2
  import { render } from 'vitest-browser-react';
3
- import { state, reactive, createContext, useContext } from 'signalium';
3
+ import { state, reactive, createContext, useContext, setRootContexts } from '../../index.js';
4
4
  import { ContextProvider, setupReact, useScope } from '../index.js';
5
5
  import React, { useState } from 'react';
6
6
 
@@ -49,6 +49,69 @@ describe('React > contexts', () => {
49
49
  await expect.element(getByText('Hey, World')).toBeInTheDocument();
50
50
  });
51
51
 
52
+ test('provider inherits from root scope', async () => {
53
+ const defaultValue1 = state('default1');
54
+ const defaultValue2 = state('default2');
55
+ const ctx1 = createContext(defaultValue1);
56
+ const ctx2 = createContext(defaultValue2);
57
+ const rootOverride1 = state('root1');
58
+ const rootOverride2 = state('root2');
59
+
60
+ // Set root contexts
61
+ setRootContexts([
62
+ [ctx1, rootOverride1],
63
+ [ctx2, rootOverride2],
64
+ ]);
65
+
66
+ // Component that uses both contexts
67
+ function Component({ testId }: { testId: string }): React.ReactNode {
68
+ const value1 = useContext(ctx1);
69
+ const value2 = useContext(ctx2);
70
+ const derived = reactive(() => `${value1.get()}-${value2.get()}`);
71
+ return <div data-testid={testId}>{derived()}</div>;
72
+ }
73
+ const localOverride1 = state('local1');
74
+ const localOverride2 = state('local2');
75
+
76
+ // Should inherit from root scope when no local overrides
77
+ const { getByTestId } = render(
78
+ <>
79
+ <ContextProvider contexts={[]}>
80
+ <Component testId="result" />
81
+ </ContextProvider>
82
+ <ContextProvider contexts={[[ctx1, localOverride1]]}>
83
+ <Component testId="result2" />
84
+ </ContextProvider>
85
+ <ContextProvider
86
+ contexts={[
87
+ [ctx1, localOverride1],
88
+ [ctx2, localOverride2],
89
+ ]}
90
+ >
91
+ <Component testId="result3" />
92
+ </ContextProvider>
93
+ </>,
94
+ );
95
+
96
+ await expect.element(getByTestId('result')).toHaveTextContent('root1-root2');
97
+
98
+ // Should inherit from root scope for unoverridden contexts
99
+ await expect.element(getByTestId('result2')).toHaveTextContent('local1-root2');
100
+
101
+ // Should use local overrides when provided
102
+ await expect.element(getByTestId('result3')).toHaveTextContent('local1-local2');
103
+
104
+ // Changes to root contexts should be reflected in inherited contexts
105
+ rootOverride1.set('updated-root1');
106
+ rootOverride2.set('updated-root2');
107
+
108
+ await expect.element(getByTestId('result')).toHaveTextContent('updated-root1-updated-root2');
109
+
110
+ // Local overrides should remain unaffected by root context changes
111
+ await expect.element(getByTestId('result2')).toHaveTextContent('local1-updated-root2');
112
+ await expect.element(getByTestId('result3')).toHaveTextContent('local1-local2');
113
+ });
114
+
52
115
  test('useContext works inside computed value passed via context provider', async () => {
53
116
  const value = state('Hello');
54
117
  const override = state('Hey');
@@ -1,19 +1,17 @@
1
1
  import { useContext } from 'react';
2
2
  import { ScopeContext } from './context.js';
3
- import { ContextImpl, ContextPair, SignalScope } from '../internals/contexts.js';
3
+ import { ContextImpl, ContextPair, ROOT_SCOPE, SignalScope } from '../internals/contexts.js';
4
4
 
5
5
  export function ContextProvider<C extends unknown[]>({
6
6
  children,
7
- contexts,
7
+ contexts = [],
8
8
  inherit = true,
9
- root = false,
10
9
  }: {
11
10
  children: React.ReactNode;
12
- contexts: [...ContextPair<C>];
11
+ contexts?: [...ContextPair<C>] | [];
13
12
  inherit?: boolean;
14
- root?: boolean;
15
13
  }) {
16
- const parentScope = useContext(ScopeContext);
14
+ const parentScope = useContext(ScopeContext) ?? ROOT_SCOPE;
17
15
  const scope = new SignalScope(contexts as [ContextImpl<unknown>, unknown][], inherit ? parentScope : undefined);
18
16
 
19
17
  return <ScopeContext.Provider value={scope}>{children}</ScopeContext.Provider>;