@jay-framework/runtime 0.15.5 → 0.15.6
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 +33 -20
- package/dist/index.js +48 -26
- package/package.json +4 -4
package/dist/index.d.ts
CHANGED
|
@@ -576,13 +576,26 @@ declare class ConstructContext<ViewState> {
|
|
|
576
576
|
/** The accumulated trackBy values from ancestor forEach loops (for __headlessInstances key lookup) */
|
|
577
577
|
get dataIds(): Coordinate;
|
|
578
578
|
coordinate: (refName: string) => Coordinate;
|
|
579
|
+
/**
|
|
580
|
+
* Create a child context for a forEach/slowForEach item.
|
|
581
|
+
*
|
|
582
|
+
* With scoped coordinates (DL#126), coordinateBase is NOT accumulated —
|
|
583
|
+
* scoped coordinates are fully qualified within each scope. Only dataIds
|
|
584
|
+
* accumulates (for __headlessInstances key lookup).
|
|
585
|
+
*
|
|
586
|
+
* coordinateBase is still maintained for the non-hydration path where
|
|
587
|
+
* coordinate() is used for refs.
|
|
588
|
+
*/
|
|
579
589
|
forItem<ChildViewState>(childViewState: ChildViewState, id: string): ConstructContext<ChildViewState>;
|
|
580
590
|
/**
|
|
581
|
-
* Create a child context scoped to a
|
|
582
|
-
*
|
|
583
|
-
*
|
|
591
|
+
* Create a child context scoped to a DOM subtree (DL#126).
|
|
592
|
+
*
|
|
593
|
+
* Builds a LOCAL coordinate map from the scope root element's subtree.
|
|
594
|
+
* All coordinate lookups within this scope search the local map only.
|
|
595
|
+
* This ensures forEach items with shared scope IDs resolve correctly —
|
|
596
|
+
* each item builds its own local map from its own DOM branch.
|
|
584
597
|
*/
|
|
585
|
-
|
|
598
|
+
forScope(scopeRootElement: Element): ConstructContext<ViewState>;
|
|
586
599
|
forAsync<ChildViewState>(childViewState: ChildViewState): ConstructContext<ChildViewState>;
|
|
587
600
|
/** Whether this context is in hydration mode (adopting existing DOM). */
|
|
588
601
|
get isHydrating(): boolean;
|
|
@@ -590,11 +603,14 @@ declare class ConstructContext<ViewState> {
|
|
|
590
603
|
get rootElement(): Element | undefined;
|
|
591
604
|
/**
|
|
592
605
|
* Resolve an element by its coordinate key from the hydration map.
|
|
593
|
-
* The key is scoped by the current coordinateBase — e.g., inside a forEach
|
|
594
|
-
* item with trackBy "item-1", resolveCoordinate("addBtn") looks up "item-1/addBtn".
|
|
595
606
|
*
|
|
596
|
-
*
|
|
597
|
-
*
|
|
607
|
+
* With scoped coordinates (DL#126), the key is fully qualified within the
|
|
608
|
+
* scope (e.g., "S2/0"). No coordinateBase prefix is applied — coordinates
|
|
609
|
+
* are self-contained within their scope.
|
|
610
|
+
*
|
|
611
|
+
* When multiple elements share the same coordinate (e.g., forEach items
|
|
612
|
+
* sharing the same template scope IDs), each call returns the next element
|
|
613
|
+
* in document order.
|
|
598
614
|
*/
|
|
599
615
|
resolveCoordinate(key: string): Element | undefined;
|
|
600
616
|
/**
|
|
@@ -696,28 +712,25 @@ declare function hydrateConditional<ViewState>(condition: (vs: ViewState) => boo
|
|
|
696
712
|
*
|
|
697
713
|
* @param accessor - Function to get the array from the ViewState
|
|
698
714
|
* @param trackBy - Property name used for item identity (reconciliation key)
|
|
715
|
+
* @param itemCoordinate - Scoped coordinate of each forEach item root element (DL#126).
|
|
716
|
+
* All items share this coordinate; each resolveCoordinate call consumes the next one.
|
|
699
717
|
* @param adoptItem - Called per existing item during hydration (should use adoptText/adoptElement)
|
|
700
718
|
* @param createItem - Called per new item (regular element()/dynamicText() from generated-element.ts)
|
|
701
719
|
*/
|
|
702
|
-
declare function hydrateForEach<ViewState, Item>(accessor: (vs: ViewState) => Item[], trackBy: string, adoptItem: () => BaseJayElement<Item>[], createItem: (item: Item, id: string) => BaseJayElement<Item>): DynamicChild<ViewState>;
|
|
720
|
+
declare function hydrateForEach<ViewState, Item>(accessor: (vs: ViewState) => Item[], trackBy: string, itemCoordinate: string, adoptItem: () => BaseJayElement<Item>[], createItem: (item: Item, id: string) => BaseJayElement<Item>): DynamicChild<ViewState>;
|
|
703
721
|
/**
|
|
704
722
|
* Hydration-aware child component instantiation.
|
|
705
723
|
*
|
|
706
|
-
*
|
|
707
|
-
*
|
|
708
|
-
* This
|
|
709
|
-
*
|
|
710
|
-
* page's coordinate map.
|
|
711
|
-
*
|
|
712
|
-
* Used for headless component instances during hydration. The child
|
|
713
|
-
* component's preRender calls ConstructContext.withHydrationChildContext()
|
|
714
|
-
* which inherits the scoped coordinateBase.
|
|
724
|
+
* With scoped coordinates (DL#126), the child component creates a LOCAL
|
|
725
|
+
* coordinate map from its inline template root element's subtree.
|
|
726
|
+
* This ensures the child's adopt calls resolve against the correct DOM
|
|
727
|
+
* branch, not the global map.
|
|
715
728
|
*
|
|
716
729
|
* @param compCreator - Component factory (from makeHeadlessInstanceComponent)
|
|
717
730
|
* @param getProps - Extracts component props from parent ViewState
|
|
718
|
-
* @param
|
|
731
|
+
* @param scopeRootCoordinate - Coordinate of the inline template root element (e.g., "S2/0")
|
|
719
732
|
* @param ref - Optional ref for the component instance
|
|
720
733
|
*/
|
|
721
|
-
declare function childCompHydrate<ParentVS, Props, ChildT, ChildElement extends BaseJayElement<ChildT>, ChildComp extends JayComponent<Props, ChildT, ChildElement>>(compCreator: JayComponentConstructor<Props>, getProps: (t: ParentVS) => Props,
|
|
734
|
+
declare function childCompHydrate<ParentVS, Props, ChildT, ChildElement extends BaseJayElement<ChildT>, ChildComp extends JayComponent<Props, ChildT, ChildElement>>(compCreator: JayComponentConstructor<Props>, getProps: (t: ParentVS) => Props, scopeRootCoordinate?: string, ref?: PrivateRef<ParentVS, ChildComp>): BaseJayElement<ParentVS>;
|
|
722
735
|
|
|
723
736
|
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 ExtractProps, 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, STATIC, type TextElement, VIEW_STATE_CHANGE_EVENT, type ViewStateFrom, type When, WhenRole, type WithData, adoptDynamicElement, adoptElement, adoptText, booleanAttribute, childComp, childCompHydrate, clearGlobalContextRegistry, conditional, createJayContext, currentConstructionContext, defaultEventWrapper, dynamicAttribute, dynamicElement, dynamicElementNS, dynamicProperty, dynamicText, element, findContext, forEach, hydrateConditional, hydrateForEach, 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
|
@@ -196,6 +196,16 @@ class ConstructContext {
|
|
|
196
196
|
get dataIds() {
|
|
197
197
|
return this._dataIds;
|
|
198
198
|
}
|
|
199
|
+
/**
|
|
200
|
+
* Create a child context for a forEach/slowForEach item.
|
|
201
|
+
*
|
|
202
|
+
* With scoped coordinates (DL#126), coordinateBase is NOT accumulated —
|
|
203
|
+
* scoped coordinates are fully qualified within each scope. Only dataIds
|
|
204
|
+
* accumulates (for __headlessInstances key lookup).
|
|
205
|
+
*
|
|
206
|
+
* coordinateBase is still maintained for the non-hydration path where
|
|
207
|
+
* coordinate() is used for refs.
|
|
208
|
+
*/
|
|
199
209
|
forItem(childViewState, id) {
|
|
200
210
|
return new ConstructContext(
|
|
201
211
|
childViewState,
|
|
@@ -207,18 +217,21 @@ class ConstructContext {
|
|
|
207
217
|
);
|
|
208
218
|
}
|
|
209
219
|
/**
|
|
210
|
-
* Create a child context scoped to a
|
|
211
|
-
*
|
|
212
|
-
*
|
|
220
|
+
* Create a child context scoped to a DOM subtree (DL#126).
|
|
221
|
+
*
|
|
222
|
+
* Builds a LOCAL coordinate map from the scope root element's subtree.
|
|
223
|
+
* All coordinate lookups within this scope search the local map only.
|
|
224
|
+
* This ensures forEach items with shared scope IDs resolve correctly —
|
|
225
|
+
* each item builds its own local map from its own DOM branch.
|
|
213
226
|
*/
|
|
214
|
-
|
|
215
|
-
const
|
|
227
|
+
forScope(scopeRootElement) {
|
|
228
|
+
const localMap = buildCoordinateMap(scopeRootElement);
|
|
216
229
|
return new ConstructContext(
|
|
217
230
|
this.data,
|
|
218
231
|
false,
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
232
|
+
this.coordinateBase,
|
|
233
|
+
localMap,
|
|
234
|
+
scopeRootElement,
|
|
222
235
|
this._dataIds
|
|
223
236
|
);
|
|
224
237
|
}
|
|
@@ -242,18 +255,19 @@ class ConstructContext {
|
|
|
242
255
|
}
|
|
243
256
|
/**
|
|
244
257
|
* Resolve an element by its coordinate key from the hydration map.
|
|
245
|
-
* The key is scoped by the current coordinateBase — e.g., inside a forEach
|
|
246
|
-
* item with trackBy "item-1", resolveCoordinate("addBtn") looks up "item-1/addBtn".
|
|
247
258
|
*
|
|
248
|
-
*
|
|
249
|
-
*
|
|
259
|
+
* With scoped coordinates (DL#126), the key is fully qualified within the
|
|
260
|
+
* scope (e.g., "S2/0"). No coordinateBase prefix is applied — coordinates
|
|
261
|
+
* are self-contained within their scope.
|
|
262
|
+
*
|
|
263
|
+
* When multiple elements share the same coordinate (e.g., forEach items
|
|
264
|
+
* sharing the same template scope IDs), each call returns the next element
|
|
265
|
+
* in document order.
|
|
250
266
|
*/
|
|
251
267
|
resolveCoordinate(key) {
|
|
252
268
|
if (!this._coordinateMap)
|
|
253
269
|
return void 0;
|
|
254
|
-
const
|
|
255
|
-
const fullKey = base ? key ? base + "/" + key : base : key;
|
|
256
|
-
const elements = this._coordinateMap.get(fullKey);
|
|
270
|
+
const elements = this._coordinateMap.get(key);
|
|
257
271
|
if (!elements || elements.length === 0)
|
|
258
272
|
return void 0;
|
|
259
273
|
return elements.shift();
|
|
@@ -267,9 +281,7 @@ class ConstructContext {
|
|
|
267
281
|
peekCoordinate(key) {
|
|
268
282
|
if (!this._coordinateMap)
|
|
269
283
|
return void 0;
|
|
270
|
-
const
|
|
271
|
-
const fullKey = base ? key ? base + "/" + key : base : key;
|
|
272
|
-
const elements = this._coordinateMap.get(fullKey);
|
|
284
|
+
const elements = this._coordinateMap.get(key);
|
|
273
285
|
if (!elements || elements.length === 0)
|
|
274
286
|
return void 0;
|
|
275
287
|
return elements[0];
|
|
@@ -1256,11 +1268,19 @@ function adoptBase(coordinate, attributes, ref) {
|
|
|
1256
1268
|
if (typeof value === "object" && value !== null && "valueFunc" in value) {
|
|
1257
1269
|
const dynAttr = value;
|
|
1258
1270
|
let attrValue = dynAttr.valueFunc(context.currData);
|
|
1271
|
+
const isBooleanAttr = dynAttr.style === 3;
|
|
1259
1272
|
if (!(key === STYLE && element2 instanceof HTMLElement)) {
|
|
1260
1273
|
updates.push((newData) => {
|
|
1261
1274
|
const newAttrValue = dynAttr.valueFunc(newData);
|
|
1262
1275
|
if (newAttrValue !== attrValue) {
|
|
1263
|
-
|
|
1276
|
+
if (isBooleanAttr) {
|
|
1277
|
+
if (newAttrValue)
|
|
1278
|
+
element2.setAttribute(key, "");
|
|
1279
|
+
else
|
|
1280
|
+
element2.removeAttribute(key);
|
|
1281
|
+
} else {
|
|
1282
|
+
element2.setAttribute(key, newAttrValue);
|
|
1283
|
+
}
|
|
1264
1284
|
}
|
|
1265
1285
|
attrValue = newAttrValue;
|
|
1266
1286
|
});
|
|
@@ -1418,17 +1438,18 @@ function hydrateConditional(condition, adoptExisting, createFallback) {
|
|
|
1418
1438
|
};
|
|
1419
1439
|
return result;
|
|
1420
1440
|
}
|
|
1421
|
-
function hydrateForEach(accessor, trackBy, adoptItem, createItem) {
|
|
1441
|
+
function hydrateForEach(accessor, trackBy, itemCoordinate, adoptItem, createItem) {
|
|
1422
1442
|
const context = currentConstructionContext();
|
|
1423
1443
|
const savedContext = saveContext();
|
|
1424
1444
|
const parentContext = context;
|
|
1425
1445
|
const initialItems = accessor(context.currData) || [];
|
|
1426
1446
|
const adoptedItems = [];
|
|
1427
|
-
for (
|
|
1447
|
+
for (let i = 0; i < initialItems.length; i++) {
|
|
1448
|
+
const item = initialItems[i];
|
|
1428
1449
|
const id = String(item[trackBy]);
|
|
1429
|
-
const itemDom = context.
|
|
1430
|
-
const
|
|
1431
|
-
const adopted = withContext(CONSTRUCTION_CONTEXT_MARKER,
|
|
1450
|
+
const itemDom = context.resolveCoordinate(itemCoordinate);
|
|
1451
|
+
const scopedContext = itemDom ? context.forScope(itemDom).forItem(item, id) : context.forItem(item, id);
|
|
1452
|
+
const adopted = withContext(CONSTRUCTION_CONTEXT_MARKER, scopedContext, () => {
|
|
1432
1453
|
const elements = adoptItem();
|
|
1433
1454
|
const updates = [];
|
|
1434
1455
|
const mounts = [];
|
|
@@ -1519,9 +1540,10 @@ function hydrateForEach(accessor, trackBy, adoptItem, createItem) {
|
|
|
1519
1540
|
};
|
|
1520
1541
|
return result;
|
|
1521
1542
|
}
|
|
1522
|
-
function childCompHydrate(compCreator, getProps,
|
|
1543
|
+
function childCompHydrate(compCreator, getProps, scopeRootCoordinate, ref) {
|
|
1523
1544
|
const context = currentConstructionContext();
|
|
1524
|
-
const
|
|
1545
|
+
const scopeRoot = scopeRootCoordinate ? context.resolveCoordinate(scopeRootCoordinate) : void 0;
|
|
1546
|
+
const childContext = scopeRoot ? context.forScope(scopeRoot) : context;
|
|
1525
1547
|
return withContext(CONSTRUCTION_CONTEXT_MARKER, childContext, () => {
|
|
1526
1548
|
const childComp2 = compCreator(getProps(context.currData));
|
|
1527
1549
|
const updates = [(t) => childComp2.update(getProps(t))];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jay-framework/runtime",
|
|
3
|
-
"version": "0.15.
|
|
3
|
+
"version": "0.15.6",
|
|
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.15.
|
|
27
|
-
"@jay-framework/reactive": "^0.15.
|
|
26
|
+
"@jay-framework/list-compare": "^0.15.6",
|
|
27
|
+
"@jay-framework/reactive": "^0.15.6"
|
|
28
28
|
},
|
|
29
29
|
"devDependencies": {
|
|
30
|
-
"@jay-framework/dev-environment": "^0.15.
|
|
30
|
+
"@jay-framework/dev-environment": "^0.15.6",
|
|
31
31
|
"@testing-library/jest-dom": "^6.2.0",
|
|
32
32
|
"@types/jsdom": "^21.1.6",
|
|
33
33
|
"@types/node": "^20.11.5",
|