@jay-framework/runtime 0.10.0 → 0.11.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 +24 -1
- package/dist/index.js +30 -0
- package/package.json +4 -4
- package/readme.md +51 -1
package/dist/index.d.ts
CHANGED
|
@@ -44,6 +44,8 @@ interface JayEvent<EventType, ViewState> {
|
|
|
44
44
|
coordinate: Coordinate;
|
|
45
45
|
}
|
|
46
46
|
type JayEventHandler<EventType, ViewState, Returns> = (event: JayEvent<EventType, ViewState>) => Returns;
|
|
47
|
+
/** Event type for ViewState change notifications */
|
|
48
|
+
declare const VIEW_STATE_CHANGE_EVENT = "viewStateChange";
|
|
47
49
|
interface JayComponent<Props, ViewState, jayElement extends BaseJayElement<ViewState>> {
|
|
48
50
|
element: jayElement;
|
|
49
51
|
update: updateFunc<Props>;
|
|
@@ -51,6 +53,8 @@ interface JayComponent<Props, ViewState, jayElement extends BaseJayElement<ViewS
|
|
|
51
53
|
unmount: MountFunc;
|
|
52
54
|
addEventListener: (type: string, handler: JayEventHandler<any, ViewState, void>) => void;
|
|
53
55
|
removeEventListener: (type: string, handler: JayEventHandler<any, ViewState, void>) => void;
|
|
56
|
+
/** Current ViewState (read-only, available when using @jay-framework/component) */
|
|
57
|
+
readonly viewState?: ViewState;
|
|
54
58
|
}
|
|
55
59
|
type PropsFrom<Type> = Type extends JayComponent<infer Props, any, any> ? Props : null;
|
|
56
60
|
type ViewStateFrom<Type> = Type extends JayComponent<any, infer ViewState, any> ? ViewState : null;
|
|
@@ -467,6 +471,25 @@ declare function isForEach<ViewState, Item>(c: Conditional<ViewState> | When<Vie
|
|
|
467
471
|
declare function isWhen<ViewState, Item>(c: Conditional<ViewState> | When<ViewState, any> | ForEach<ViewState, Item> | WithData<ViewState, any> | TextElement<ViewState> | BaseJayElement<ViewState>): c is When<ViewState, any>;
|
|
468
472
|
declare function isWithData<ViewState, ChildViewState>(c: Conditional<ViewState> | When<ViewState, any> | ForEach<ViewState, any> | WithData<ViewState, ChildViewState> | TextElement<ViewState> | BaseJayElement<ViewState>): c is WithData<ViewState, ChildViewState>;
|
|
469
473
|
declare function forEach<T, Item>(getItems: (T: any) => Array<Item>, elemCreator: (Item: any) => BaseJayElement<Item>, matchBy: string): ForEach<T, Item>;
|
|
474
|
+
/**
|
|
475
|
+
* Runtime support for pre-rendered slow arrays (slowForEach in jay-html).
|
|
476
|
+
*
|
|
477
|
+
* This function is used when a forEach loop has been pre-rendered at slow phase.
|
|
478
|
+
* The array items are statically embedded in the jay-html, but we still need to:
|
|
479
|
+
* 1. Set up the correct data context for each item (so bindings work)
|
|
480
|
+
* 2. Enable fast/interactive updates within each item
|
|
481
|
+
* 3. Support event handling with the correct item coordinates
|
|
482
|
+
*
|
|
483
|
+
* The key insight is that slowForEachItem switches the data context to the
|
|
484
|
+
* specific array item, so child bindings like {price} work correctly
|
|
485
|
+
* (they resolve to item.price, not viewState.price).
|
|
486
|
+
*
|
|
487
|
+
* @param arrayName - The property name of the array in the parent ViewState
|
|
488
|
+
* @param index - The jayIndex value (position in the pre-rendered array)
|
|
489
|
+
* @param trackByValue - The jayTrackBy value (identity for reconciliation)
|
|
490
|
+
* @param elementCreator - Function that creates the pre-rendered element (called within item context)
|
|
491
|
+
*/
|
|
492
|
+
declare function slowForEachItem<ParentVS, ItemVS>(arrayName: keyof ParentVS, index: number, trackByValue: string, elementCreator: () => BaseJayElement<ItemVS>): BaseJayElement<ParentVS>;
|
|
470
493
|
interface ForEach<ViewState, Item> {
|
|
471
494
|
getItems: (T: any) => Array<Item>;
|
|
472
495
|
elemCreator: (Item: any, String: any) => BaseJayElement<Item>;
|
|
@@ -550,4 +573,4 @@ declare class ConstructContext<ViewState> {
|
|
|
550
573
|
static withRootContext<ViewState, Refs>(viewState: ViewState, refManager: ReferencesManager, elementConstructor: () => BaseJayElement<ViewState>): JayElement<ViewState, Refs>;
|
|
551
574
|
}
|
|
552
575
|
|
|
553
|
-
export { type Attribute, type Attributes, type BaseJayElement, BaseReferencesManager, type ComponentCollectionProxy, ComponentCollectionRefImpl, type ComponentProxy, ComponentRefImpl, ComponentRefsImpl, type Conditional, ConstructContext, type ContextMarker, type Coordinate, type DynamicAttributeOrProperty, EVENT_TRAP, type ElementFrom, type EventEmitter, type EventTypeFrom, type ExtractFastViewState, type ExtractInteractiveViewState, type ExtractRefs, type ExtractSlowViewState, type ExtractViewState, type ForEach, GetTrapProxy, type GlobalJayEvents, type HTMLElementCollectionProxy, type HTMLElementCollectionProxyTarget, type HTMLElementProxy, type HTMLElementProxyTarget, type HTMLNativeExec, type HeadLink, type JayComponent, type JayComponentConstructor, type JayContract, type JayElement, type JayEvent, type JayEventHandler, type JayEventHandlerWrapper, type JayLog, type JayNativeEventBuilder, type JayNativeFunction, LogType, type ManagedRefConstructor, ManagedRefType, type ManagedRefs, type MapEventEmitterViewState, type MountFunc, type OnlyEventEmitters, type PreRenderElement, type PrivateRef, type PrivateRefConstructor, PrivateRefs, type PropsFrom, ReferencesManager, type RenderElement, type RenderElementOptions, type TextElement, type ViewStateFrom, type When, WhenRole, type WithData, booleanAttribute, childComp, clearGlobalContextRegistry, conditional, createJayContext, currentConstructionContext, defaultEventWrapper, dynamicAttribute, dynamicElement, dynamicElementNS, dynamicProperty, dynamicText, element, findContext, forEach, injectHeadLinks, isCondition, isForEach, isWhen, isWithData, jayLog, mathMLDynamicElement, mathMLElement, mkUpdateCollection, noop, noopMount, noopUpdate, normalizeMount, normalizeUpdates, pending, registerGlobalContext, rejected, resolved, restoreContext, saveContext, svgDynamicElement, svgElement, type updateFunc, useContext, useGlobalContext, withContext, withData };
|
|
576
|
+
export { type Attribute, type Attributes, type BaseJayElement, BaseReferencesManager, type ComponentCollectionProxy, ComponentCollectionRefImpl, type ComponentProxy, ComponentRefImpl, ComponentRefsImpl, type Conditional, ConstructContext, type ContextMarker, type Coordinate, type DynamicAttributeOrProperty, EVENT_TRAP, type ElementFrom, type EventEmitter, type EventTypeFrom, type ExtractFastViewState, type ExtractInteractiveViewState, type ExtractRefs, type ExtractSlowViewState, type ExtractViewState, type ForEach, GetTrapProxy, type GlobalJayEvents, type HTMLElementCollectionProxy, type HTMLElementCollectionProxyTarget, type HTMLElementProxy, type HTMLElementProxyTarget, type HTMLNativeExec, type HeadLink, type JayComponent, type JayComponentConstructor, type JayContract, type JayElement, type JayEvent, type JayEventHandler, type JayEventHandlerWrapper, type JayLog, type JayNativeEventBuilder, type JayNativeFunction, LogType, type ManagedRefConstructor, ManagedRefType, type ManagedRefs, type MapEventEmitterViewState, type MountFunc, type OnlyEventEmitters, type PreRenderElement, type PrivateRef, type PrivateRefConstructor, PrivateRefs, type PropsFrom, ReferencesManager, type RenderElement, type RenderElementOptions, type TextElement, VIEW_STATE_CHANGE_EVENT, type ViewStateFrom, type When, WhenRole, type WithData, booleanAttribute, childComp, clearGlobalContextRegistry, conditional, createJayContext, currentConstructionContext, defaultEventWrapper, dynamicAttribute, dynamicElement, dynamicElementNS, dynamicProperty, dynamicText, element, findContext, forEach, injectHeadLinks, isCondition, isForEach, isWhen, isWithData, jayLog, mathMLDynamicElement, mathMLElement, mkUpdateCollection, noop, noopMount, noopUpdate, normalizeMount, normalizeUpdates, pending, registerGlobalContext, rejected, resolved, restoreContext, saveContext, slowForEachItem, svgDynamicElement, svgElement, type updateFunc, useContext, useGlobalContext, withContext, withData };
|
package/dist/index.js
CHANGED
|
@@ -84,6 +84,7 @@ const noop = () => {
|
|
|
84
84
|
};
|
|
85
85
|
const noopUpdate = noop;
|
|
86
86
|
const noopMount = noop;
|
|
87
|
+
const VIEW_STATE_CHANGE_EVENT = "viewStateChange";
|
|
87
88
|
var LogType = /* @__PURE__ */ ((LogType2) => {
|
|
88
89
|
LogType2[LogType2["ASYNC_ERROR"] = 0] = "ASYNC_ERROR";
|
|
89
90
|
LogType2[LogType2["CONTEXT_NOT_FOUND"] = 1] = "CONTEXT_NOT_FOUND";
|
|
@@ -367,6 +368,33 @@ function mkWhenPendingCondition(when2, group) {
|
|
|
367
368
|
function forEach(getItems, elemCreator, matchBy) {
|
|
368
369
|
return { getItems, elemCreator, trackBy: matchBy };
|
|
369
370
|
}
|
|
371
|
+
function slowForEachItem(arrayName, index, trackByValue, elementCreator) {
|
|
372
|
+
const parentContext = currentConstructionContext();
|
|
373
|
+
const savedContext = saveContext();
|
|
374
|
+
const parentData = parentContext.currData;
|
|
375
|
+
const array = parentData[arrayName];
|
|
376
|
+
const initialItem = array?.[index];
|
|
377
|
+
const childContext = parentContext.forItem(initialItem, trackByValue);
|
|
378
|
+
const element2 = withContext(CONSTRUCTION_CONTEXT_MARKER, childContext, elementCreator);
|
|
379
|
+
const originalUpdate = element2.update;
|
|
380
|
+
const update = (newParentData) => {
|
|
381
|
+
const newArray = newParentData[arrayName];
|
|
382
|
+
const newItem = newArray?.[index];
|
|
383
|
+
const updateChildContext = parentContext.forItem(newItem, trackByValue);
|
|
384
|
+
restoreContext(
|
|
385
|
+
savedContext,
|
|
386
|
+
() => withContext(CONSTRUCTION_CONTEXT_MARKER, updateChildContext, () => {
|
|
387
|
+
originalUpdate(newItem);
|
|
388
|
+
})
|
|
389
|
+
);
|
|
390
|
+
};
|
|
391
|
+
return {
|
|
392
|
+
dom: element2.dom,
|
|
393
|
+
update,
|
|
394
|
+
mount: element2.mount,
|
|
395
|
+
unmount: element2.unmount
|
|
396
|
+
};
|
|
397
|
+
}
|
|
370
398
|
function withData(accessor, elem) {
|
|
371
399
|
return { accessor, elem };
|
|
372
400
|
}
|
|
@@ -995,6 +1023,7 @@ export {
|
|
|
995
1023
|
ManagedRefType,
|
|
996
1024
|
PrivateRefs,
|
|
997
1025
|
ReferencesManager,
|
|
1026
|
+
VIEW_STATE_CHANGE_EVENT,
|
|
998
1027
|
WhenRole,
|
|
999
1028
|
booleanAttribute,
|
|
1000
1029
|
childComp,
|
|
@@ -1031,6 +1060,7 @@ export {
|
|
|
1031
1060
|
resolved,
|
|
1032
1061
|
restoreContext,
|
|
1033
1062
|
saveContext,
|
|
1063
|
+
slowForEachItem,
|
|
1034
1064
|
svgDynamicElement,
|
|
1035
1065
|
svgElement,
|
|
1036
1066
|
useContext,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jay-framework/runtime",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.11.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -23,11 +23,11 @@
|
|
|
23
23
|
"test:watch": "vitest"
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
|
-
"@jay-framework/list-compare": "^0.
|
|
27
|
-
"@jay-framework/reactive": "^0.
|
|
26
|
+
"@jay-framework/list-compare": "^0.11.0",
|
|
27
|
+
"@jay-framework/reactive": "^0.11.0"
|
|
28
28
|
},
|
|
29
29
|
"devDependencies": {
|
|
30
|
-
"@jay-framework/dev-environment": "^0.
|
|
30
|
+
"@jay-framework/dev-environment": "^0.11.0",
|
|
31
31
|
"@testing-library/jest-dom": "^6.2.0",
|
|
32
32
|
"@types/jsdom": "^21.1.6",
|
|
33
33
|
"@types/node": "^20.11.5",
|
package/readme.md
CHANGED
|
@@ -105,7 +105,57 @@ interface JayElement<ViewState, Refs> extends BaseJayElement<ViewState> {
|
|
|
105
105
|
These references can be used to set event listeners, interact with child elements or component APIs.
|
|
106
106
|
Read more about `refs` in [refs.md](./docs/refs.md).
|
|
107
107
|
|
|
108
|
-
##
|
|
108
|
+
## Slow Rendering Support
|
|
109
|
+
|
|
110
|
+
The runtime supports pre-rendered "slow" arrays via the `slowForEachItem` function. This is used when a `forEach` loop has been pre-rendered at build time (slow phase), but still needs fast/interactive updates at runtime.
|
|
111
|
+
|
|
112
|
+
### slowForEachItem
|
|
113
|
+
|
|
114
|
+
```typescript
|
|
115
|
+
function slowForEachItem<ParentVS, ItemVS>(
|
|
116
|
+
arrayName: keyof ParentVS,
|
|
117
|
+
index: number,
|
|
118
|
+
trackByValue: string,
|
|
119
|
+
elementCreator: () => BaseJayElement<ItemVS>,
|
|
120
|
+
): BaseJayElement<ParentVS>;
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
**Parameters:**
|
|
124
|
+
|
|
125
|
+
- `arrayName` - The property name of the array in the parent ViewState
|
|
126
|
+
- `index` - The position in the pre-rendered array (jayIndex)
|
|
127
|
+
- `trackByValue` - The track-by value for client reconciliation (jayTrackBy)
|
|
128
|
+
- `elementCreator` - Function that creates the element (called within item context)
|
|
129
|
+
|
|
130
|
+
**How it works:**
|
|
131
|
+
|
|
132
|
+
1. Sets the data context to `viewState[arrayName][index]`
|
|
133
|
+
2. Calls `elementCreator()` within that context so bindings are item-scoped
|
|
134
|
+
3. On update, retrieves the item from the new ViewState and updates with item context
|
|
135
|
+
|
|
136
|
+
**Example generated code:**
|
|
137
|
+
|
|
138
|
+
```typescript
|
|
139
|
+
slowForEachItem('products', 0, 'p1', () =>
|
|
140
|
+
e('li', {}, [
|
|
141
|
+
e('span', { class: 'name' }, ['Widget A']), // static (pre-rendered)
|
|
142
|
+
e('span', { class: 'price' }, [
|
|
143
|
+
dt((vs) => vs.price), // dynamic (fast phase) - item-scoped
|
|
144
|
+
]),
|
|
145
|
+
]),
|
|
146
|
+
);
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
This corresponds to pre-rendered jay-html:
|
|
150
|
+
|
|
151
|
+
```html
|
|
152
|
+
<li slowForEach="products" trackBy="id" jayIndex="0" jayTrackBy="p1">
|
|
153
|
+
<span class="name">Widget A</span>
|
|
154
|
+
<span class="price">{price}</span>
|
|
155
|
+
</li>
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
## Implementation Details
|
|
109
159
|
|
|
110
160
|
- See the [Generated JayElement](./docs/jay-element.md) for the details of the `jay-html` generated target.
|
|
111
161
|
- See the [Generated JayElement creation Functions](./docs/runtime.md) for the details of the jay element creation functions used by the `jay-html` generated target.
|