@jay-framework/component 0.10.0 → 0.12.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.
- package/dist/index.d.ts +26 -1
- package/dist/index.js +23 -4
- package/docs/register-reactive-global-context.md +128 -0
- package/package.json +5 -5
- package/readme.md +1 -0
package/dist/index.d.ts
CHANGED
|
@@ -41,6 +41,31 @@ declare const forTesting: {
|
|
|
41
41
|
|
|
42
42
|
declare const CONTEXT_REACTIVE_SYMBOL_CONTEXT: unique symbol;
|
|
43
43
|
declare function createReactiveContext<T extends object>(mkContext: () => T): T;
|
|
44
|
+
/**
|
|
45
|
+
* Creates a reactive context and registers it globally.
|
|
46
|
+
* Use this in `withClient` initialization to create reactive global contexts.
|
|
47
|
+
*
|
|
48
|
+
* @param marker - The context marker created with createJayContext()
|
|
49
|
+
* @param mkContext - Factory function that creates the context (can use createSignal, etc.)
|
|
50
|
+
* @returns The created context (for immediate use in init)
|
|
51
|
+
*
|
|
52
|
+
* @example
|
|
53
|
+
* ```typescript
|
|
54
|
+
* export const init = makeJayInit()
|
|
55
|
+
* .withClient(async () => {
|
|
56
|
+
* const ctx = registerReactiveGlobalContext(MY_CONTEXT, () => {
|
|
57
|
+
* const [count, setCount] = createSignal(0);
|
|
58
|
+
* return {
|
|
59
|
+
* count,
|
|
60
|
+
* increment: () => setCount(n => n + 1),
|
|
61
|
+
* async init() { await loadData(); },
|
|
62
|
+
* };
|
|
63
|
+
* });
|
|
64
|
+
* await ctx.init();
|
|
65
|
+
* });
|
|
66
|
+
* ```
|
|
67
|
+
*/
|
|
68
|
+
declare function registerReactiveGlobalContext<T extends object>(marker: ContextMarker<T>, mkContext: () => T): T;
|
|
44
69
|
|
|
45
70
|
type EffectCleanup = () => void;
|
|
46
71
|
declare function createEffect(effect: () => void | EffectCleanup): void;
|
|
@@ -66,4 +91,4 @@ interface ComponentContext extends HookContext {
|
|
|
66
91
|
declare const COMPONENT_CONTEXT: ContextMarker<ComponentContext>;
|
|
67
92
|
declare const CONTEXT_CREATION_CONTEXT: ContextMarker<HookContext>;
|
|
68
93
|
|
|
69
|
-
export { COMPONENT_CONTEXT, CONTEXT_CREATION_CONTEXT, CONTEXT_REACTIVE_SYMBOL_CONTEXT, type ComponentConstructor, type ComponentContext, type ConcreteJayComponent, type ContextMarkers, type EffectCleanup, type HookContext, type JayComponentCore, type JayTsxComponentConstructor, type JsxNode, type Patcher, type Props, type UpdatableProps, type ViewStateGetters, createDerivedArray, createEffect, createEvent, createMemo, createPatchableSignal, createReactiveContext, createSignal, forTesting, type hasProps, makeJayComponent, makeJayTsxComponent, makePropsProxy, materializeViewState, provideContext, provideReactiveContext, useReactive };
|
|
94
|
+
export { COMPONENT_CONTEXT, CONTEXT_CREATION_CONTEXT, CONTEXT_REACTIVE_SYMBOL_CONTEXT, type ComponentConstructor, type ComponentContext, type ConcreteJayComponent, type ContextMarkers, type EffectCleanup, type HookContext, type JayComponentCore, type JayTsxComponentConstructor, type JsxNode, type Patcher, type Props, type UpdatableProps, type ViewStateGetters, createDerivedArray, createEffect, createEvent, createMemo, createPatchableSignal, createReactiveContext, createSignal, forTesting, type hasProps, makeJayComponent, makeJayTsxComponent, makePropsProxy, materializeViewState, provideContext, provideReactiveContext, registerReactiveGlobalContext, useReactive };
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createJayContext, withContext, findContext, useContext } from "@jay-framework/runtime";
|
|
1
|
+
import { createJayContext, withContext, registerGlobalContext, findContext, useContext, VIEW_STATE_CHANGE_EVENT } from "@jay-framework/runtime";
|
|
2
2
|
import { mkReactive, GetterMark, SetterMark, MeasureOfChange } from "@jay-framework/reactive";
|
|
3
3
|
import { patch } from "@jay-framework/json-patch";
|
|
4
4
|
const COMPONENT_CONTEXT = createJayContext();
|
|
@@ -34,6 +34,11 @@ function createReactiveContext(mkContext) {
|
|
|
34
34
|
);
|
|
35
35
|
return newContextProxy(reactive, context);
|
|
36
36
|
}
|
|
37
|
+
function registerReactiveGlobalContext(marker, mkContext) {
|
|
38
|
+
const context = createReactiveContext(mkContext);
|
|
39
|
+
registerGlobalContext(marker, context);
|
|
40
|
+
return context;
|
|
41
|
+
}
|
|
37
42
|
function currentHookContext() {
|
|
38
43
|
return findContext((_) => _ === COMPONENT_CONTEXT || _ === CONTEXT_CREATION_CONTEXT);
|
|
39
44
|
}
|
|
@@ -221,9 +226,12 @@ function makeJayComponent(preRender, comp, ...contextMarkers) {
|
|
|
221
226
|
componentContext.provideContexts.forEach(
|
|
222
227
|
([marker, context]) => context[CONTEXT_REACTIVE_SYMBOL_CONTEXT] && reactive.enablePairing(context[CONTEXT_REACTIVE_SYMBOL_CONTEXT])
|
|
223
228
|
);
|
|
229
|
+
let currentViewState;
|
|
230
|
+
let viewStateChangeListener;
|
|
224
231
|
componentContext.reactive.createReaction(() => {
|
|
225
232
|
let viewStateValueOrGetters = renderViewState();
|
|
226
233
|
let viewState = materializeViewState(viewStateValueOrGetters);
|
|
234
|
+
currentViewState = viewState;
|
|
227
235
|
if (!element)
|
|
228
236
|
element = renderWithContexts(
|
|
229
237
|
componentContext.provideContexts,
|
|
@@ -232,19 +240,24 @@ function makeJayComponent(preRender, comp, ...contextMarkers) {
|
|
|
232
240
|
);
|
|
233
241
|
else
|
|
234
242
|
element.update(viewState);
|
|
243
|
+
viewStateChangeListener?.({ event: viewState, viewState, coordinate: [] });
|
|
235
244
|
});
|
|
236
245
|
const [mount, unmount] = mkMounts(componentContext, element);
|
|
237
246
|
let update = (updateProps) => {
|
|
238
247
|
propsProxy.update(updateProps);
|
|
239
248
|
};
|
|
240
|
-
let events = {
|
|
249
|
+
let events = {
|
|
250
|
+
[VIEW_STATE_CHANGE_EVENT]: (handler) => {
|
|
251
|
+
viewStateChangeListener = handler;
|
|
252
|
+
}
|
|
253
|
+
};
|
|
241
254
|
let component = {
|
|
242
255
|
element,
|
|
243
256
|
update,
|
|
244
257
|
mount,
|
|
245
258
|
unmount,
|
|
246
|
-
addEventListener: (eventType, handler) => events[eventType](handler),
|
|
247
|
-
removeEventListener: (eventType) => events[eventType](void 0)
|
|
259
|
+
addEventListener: (eventType, handler) => events[eventType]?.(handler),
|
|
260
|
+
removeEventListener: (eventType) => events[eventType]?.(void 0)
|
|
248
261
|
};
|
|
249
262
|
for (let key in api) {
|
|
250
263
|
if (typeof api[key] === "function") {
|
|
@@ -260,6 +273,11 @@ function makeJayComponent(preRender, comp, ...contextMarkers) {
|
|
|
260
273
|
component[key] = api[key];
|
|
261
274
|
}
|
|
262
275
|
}
|
|
276
|
+
Object.defineProperty(component, "viewState", {
|
|
277
|
+
get: () => currentViewState,
|
|
278
|
+
enumerable: false,
|
|
279
|
+
configurable: true
|
|
280
|
+
});
|
|
263
281
|
return componentInstance = component;
|
|
264
282
|
});
|
|
265
283
|
};
|
|
@@ -318,5 +336,6 @@ export {
|
|
|
318
336
|
materializeViewState,
|
|
319
337
|
provideContext,
|
|
320
338
|
provideReactiveContext,
|
|
339
|
+
registerReactiveGlobalContext,
|
|
321
340
|
useReactive
|
|
322
341
|
};
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
# registerReactiveGlobalContext
|
|
2
|
+
|
|
3
|
+
Creates a reactive context and registers it globally for use across the application.
|
|
4
|
+
|
|
5
|
+
Use this in `withClient` initialization (via `makeJayInit`) to create reactive global contexts
|
|
6
|
+
that are available to all components without needing a parent component to provide them.
|
|
7
|
+
|
|
8
|
+
```typescript
|
|
9
|
+
declare function registerReactiveGlobalContext<T extends object>(
|
|
10
|
+
marker: ContextMarker<T>,
|
|
11
|
+
mkContext: () => T,
|
|
12
|
+
): T;
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Parameters:
|
|
16
|
+
|
|
17
|
+
- `marker`: A unique symbol identifying the context, created using `createJayContext`.
|
|
18
|
+
- `mkContext`: A function that creates the initial context value.
|
|
19
|
+
The function may use any of the Jay Hooks (`createSignal`, `createEffect`, etc.) and should return an object which represents the context.
|
|
20
|
+
|
|
21
|
+
## Returns:
|
|
22
|
+
|
|
23
|
+
The created reactive context value, which can be used immediately in the init function.
|
|
24
|
+
|
|
25
|
+
## Behavior
|
|
26
|
+
|
|
27
|
+
- Creates a `Reactive` instance for signal tracking
|
|
28
|
+
- Sets up the context creation environment so `createSignal()` and other hooks work
|
|
29
|
+
- Returns a proxy that batches reactions for function calls (same as `provideReactiveContext`)
|
|
30
|
+
- Registers the context in the global registry so it's available via `useContext()`
|
|
31
|
+
|
|
32
|
+
## Examples:
|
|
33
|
+
|
|
34
|
+
### Basic Counter Context
|
|
35
|
+
|
|
36
|
+
```typescript
|
|
37
|
+
import { createJayContext } from '@jay-framework/runtime';
|
|
38
|
+
import { createSignal, registerReactiveGlobalContext } from '@jay-framework/component';
|
|
39
|
+
import { makeJayInit } from '@jay-framework/fullstack-component';
|
|
40
|
+
|
|
41
|
+
interface CounterContext {
|
|
42
|
+
count: () => number;
|
|
43
|
+
increment: () => void;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export const COUNTER_CTX = createJayContext<CounterContext>();
|
|
47
|
+
|
|
48
|
+
export const init = makeJayInit().withClient(() => {
|
|
49
|
+
registerReactiveGlobalContext(COUNTER_CTX, () => {
|
|
50
|
+
const [count, setCount] = createSignal(0);
|
|
51
|
+
return {
|
|
52
|
+
count,
|
|
53
|
+
increment: () => setCount((n) => n + 1),
|
|
54
|
+
};
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### Async Initialization Pattern
|
|
60
|
+
|
|
61
|
+
For contexts that need async initialization, expose an `init()` method:
|
|
62
|
+
|
|
63
|
+
```typescript
|
|
64
|
+
interface WixClientContext {
|
|
65
|
+
client: WixClient;
|
|
66
|
+
isReady: () => boolean;
|
|
67
|
+
init: () => Promise<void>;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export const WIX_CLIENT_CTX = createJayContext<WixClientContext>();
|
|
71
|
+
|
|
72
|
+
export const init = makeJayInit().withClient(async () => {
|
|
73
|
+
const ctx = registerReactiveGlobalContext(WIX_CLIENT_CTX, () => {
|
|
74
|
+
const [isReady, setIsReady] = createSignal(false);
|
|
75
|
+
|
|
76
|
+
return {
|
|
77
|
+
client: wixClient,
|
|
78
|
+
isReady,
|
|
79
|
+
async init() {
|
|
80
|
+
const tokens = await wixClient.auth.generateVisitorTokens();
|
|
81
|
+
wixClient.auth.setTokens(tokens);
|
|
82
|
+
setIsReady(true);
|
|
83
|
+
},
|
|
84
|
+
};
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
// Call init immediately
|
|
88
|
+
await ctx.init();
|
|
89
|
+
});
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### Using the Context in Components
|
|
93
|
+
|
|
94
|
+
```typescript
|
|
95
|
+
import { useContext } from '@jay-framework/runtime';
|
|
96
|
+
import { COUNTER_CTX } from '../lib/init';
|
|
97
|
+
|
|
98
|
+
function MyComponent(props, refs) {
|
|
99
|
+
// Access the global context
|
|
100
|
+
const counter = useContext(COUNTER_CTX);
|
|
101
|
+
|
|
102
|
+
refs.incrementButton.onclick(() => {
|
|
103
|
+
counter.increment();
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
return {
|
|
107
|
+
render: () => ({
|
|
108
|
+
count: counter.count(),
|
|
109
|
+
}),
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
## Comparison with provideReactiveContext
|
|
115
|
+
|
|
116
|
+
| Feature | `provideReactiveContext` | `registerReactiveGlobalContext` |
|
|
117
|
+
| ------------- | -------------------------------------------- | ------------------------------- |
|
|
118
|
+
| Scope | Component subtree | Entire application |
|
|
119
|
+
| When to use | Component provides context to children | App initialization |
|
|
120
|
+
| Where to call | Inside component constructor | Inside `withClient` |
|
|
121
|
+
| Override | Child components can provide different value | Cannot be overridden |
|
|
122
|
+
|
|
123
|
+
## Design Log
|
|
124
|
+
|
|
125
|
+
For additional information on the design decisions, read:
|
|
126
|
+
|
|
127
|
+
- [67 - registerReactiveGlobalContext.md](../../../../design-log/67%20-%20registerReactiveGlobalContext.md)
|
|
128
|
+
- [65 - makeJayInit builder pattern.md](../../../../design-log/65%20-%20makeJayInit%20builder%20pattern.md)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jay-framework/component",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.12.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -21,12 +21,12 @@
|
|
|
21
21
|
"test:watch": "vitest"
|
|
22
22
|
},
|
|
23
23
|
"dependencies": {
|
|
24
|
-
"@jay-framework/json-patch": "^0.
|
|
25
|
-
"@jay-framework/reactive": "^0.
|
|
26
|
-
"@jay-framework/runtime": "^0.
|
|
24
|
+
"@jay-framework/json-patch": "^0.12.0",
|
|
25
|
+
"@jay-framework/reactive": "^0.12.0",
|
|
26
|
+
"@jay-framework/runtime": "^0.12.0"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
|
-
"@jay-framework/dev-environment": "^0.
|
|
29
|
+
"@jay-framework/dev-environment": "^0.12.0",
|
|
30
30
|
"@testing-library/jest-dom": "^6.2.0",
|
|
31
31
|
"@types/node": "^20.11.5",
|
|
32
32
|
"rimraf": "^5.0.5",
|
package/readme.md
CHANGED
|
@@ -27,6 +27,7 @@ Hooks for providing context:
|
|
|
27
27
|
|
|
28
28
|
- [provideContext](./docs/provide-context.md)
|
|
29
29
|
- [provideReactiveContext](./docs/provide-reactive-context.md)
|
|
30
|
+
- [registerReactiveGlobalContext](./docs/register-reactive-global-context.md)
|
|
30
31
|
|
|
31
32
|
Hooks to get Component Reactive Instance:
|
|
32
33
|
|