@jay-framework/compiler-jay-html 0.17.3 → 0.18.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.cts CHANGED
@@ -270,7 +270,7 @@ declare function assignCoordinatesToJayHtml(jayHtml: string, headlessContractNam
270
270
  /**
271
271
  * Assign `jay-coordinate-base` and `jay-scope` attributes to elements in the DOM tree.
272
272
  *
273
- * Must run after slow-render (which resolves slow conditions, unrolls slowForEach,
273
+ * Must run after slow-render (which resolves slow conditions
274
274
  * and wraps multi-child headless inline templates).
275
275
  *
276
276
  * Mutates the DOM in place. Returns the serialized DOM for debug output.
package/dist/index.js CHANGED
@@ -5891,18 +5891,6 @@ function walkChildren(parent, parentCoord, scopeId, options, counter) {
5891
5891
  continue;
5892
5892
  }
5893
5893
  }
5894
- const slowForEachAttr = element.getAttribute("slowForEach");
5895
- if (slowForEachAttr) {
5896
- const jayTrackBy = element.getAttribute("jayTrackBy");
5897
- if (jayTrackBy) {
5898
- const itemScopeId = nextScopeId(counter);
5899
- element.setAttribute(SCOPE_ATTR, itemScopeId);
5900
- const itemCoord = `${itemScopeId}/0`;
5901
- element.setAttribute(COORD_ATTR$1, itemCoord);
5902
- walkChildren(element, itemCoord, itemScopeId, options, counter);
5903
- continue;
5904
- }
5905
- }
5906
5894
  const coord = `${parentCoord}/${childCounter}`;
5907
5895
  element.setAttribute(COORD_ATTR$1, coord);
5908
5896
  childCounter++;
@@ -13446,27 +13434,6 @@ function isConditional(node2) {
13446
13434
  function isForEach(node2) {
13447
13435
  return node2.nodeType !== NodeType.TEXT_NODE && node2.hasAttribute("forEach");
13448
13436
  }
13449
- function isSlowForEach(node2) {
13450
- return node2.nodeType !== NodeType.TEXT_NODE && node2.hasAttribute("slowForEach");
13451
- }
13452
- function getSlowForEachInfo(node2) {
13453
- if (!isSlowForEach(node2))
13454
- return void 0;
13455
- const element = node2;
13456
- const arrayName = element.getAttribute("slowForEach");
13457
- const jayIndex = element.getAttribute("jayIndex");
13458
- const jayTrackBy = element.getAttribute("jayTrackBy");
13459
- const trackBy = element.getAttribute("trackBy") || "id";
13460
- if (!arrayName || jayIndex === null || !jayTrackBy) {
13461
- return void 0;
13462
- }
13463
- return {
13464
- arrayName,
13465
- jayIndex: parseInt(jayIndex, 10),
13466
- jayTrackBy,
13467
- trackBy
13468
- };
13469
- }
13470
13437
  function isRecurse(node2) {
13471
13438
  return node2.nodeType !== NodeType.TEXT_NODE && node2.rawTagName?.toLowerCase() === "recurse";
13472
13439
  }
@@ -14210,7 +14177,7 @@ function renderReferenceManager(refs, target) {
14210
14177
  childRenderedRefManagers.push(rendered);
14211
14178
  });
14212
14179
  const childRefManager = childRefManagerMembers.length > 0 ? `, {
14213
- ${childRefManagerMembers.join(",\n")}
14180
+ ${childRefManagerMembers.join(",\n")}
14214
14181
  }` : "";
14215
14182
  const renderedRefManager = ` const [${name}, [${refVariables}]] =
14216
14183
  ${referenceManagerInit}(${options}[${elemRefsDeclarations}], [${elemCollectionRefsDeclarations}], [${compRefsDeclarations}], [${compCollectionRefsDeclarations}]${childRefManager});`;
@@ -14451,9 +14418,7 @@ const DIRECTIVE_ATTRIBUTES = /* @__PURE__ */ new Set([
14451
14418
  "foreach",
14452
14419
  "trackby",
14453
14420
  "ref",
14454
- "slowforeach",
14455
- "jayindex",
14456
- "jaytrackby",
14421
+ "slow",
14457
14422
  "jay-coordinate-base",
14458
14423
  "jay-scope",
14459
14424
  AsyncDirectiveTypes.loading.directive,
@@ -14481,18 +14446,6 @@ function validateForEachAccessor(forEach, variables) {
14481
14446
  ]);
14482
14447
  return { accessor, childVariables: variables.childVariableFor(accessor) };
14483
14448
  }
14484
- function validateSlowForEachAccessor(arrayName, variables) {
14485
- const accessor = parseAccessor(arrayName, variables);
14486
- if (accessor.resolvedType === JayUnknown)
14487
- return new RenderFragment("", Imports.none(), [
14488
- `slowForEach directive - failed to resolve array type [slowForEach=${arrayName}]`
14489
- ]);
14490
- if (!isArrayType$1(accessor.resolvedType))
14491
- return new RenderFragment("", Imports.none(), [
14492
- `slowForEach directive - resolved type is not an array [slowForEach=${arrayName}]`
14493
- ]);
14494
- return { accessor, childVariables: variables.childVariableFor(accessor) };
14495
- }
14496
14449
  function validateAsyncAccessor(property, directive, variables) {
14497
14450
  const accessor = parseAccessor(property, variables);
14498
14451
  if (accessor.resolvedType === JayUnknown)
@@ -14553,6 +14506,34 @@ function buildContractRefMap(refsTree) {
14553
14506
  walk(refsTree);
14554
14507
  return result;
14555
14508
  }
14509
+ function mergeContractStubRefs(templateRefs, contractRefs) {
14510
+ const templateRefNames = new Set(templateRefs.refs.map((r) => camelCase(r.ref)));
14511
+ const stubRefs = [];
14512
+ for (const contractRef of contractRefs.refs) {
14513
+ if (!templateRefNames.has(camelCase(contractRef.ref))) {
14514
+ stubRefs.push(
14515
+ mkRef(
14516
+ contractRef.originalName,
14517
+ contractRef.originalName,
14518
+ camelCase(`ref ${contractRef.originalName}`),
14519
+ contractRef.repeated,
14520
+ true,
14521
+ contractRef.viewStateType,
14522
+ contractRef.elementType
14523
+ )
14524
+ );
14525
+ }
14526
+ }
14527
+ if (stubRefs.length === 0)
14528
+ return templateRefs;
14529
+ return mkRefsTree(
14530
+ [...templateRefs.refs, ...stubRefs],
14531
+ templateRefs.children,
14532
+ templateRefs.repeated,
14533
+ templateRefs.imported?.refsTypeName,
14534
+ templateRefs.imported?.repeatedRefsTypeName
14535
+ );
14536
+ }
14556
14537
  const COORD_ATTR = "jay-coordinate-base";
14557
14538
  function expandContractType(renderedElement, baseName) {
14558
14539
  const contractPattern = new RegExp(
@@ -14689,7 +14670,6 @@ function renderBridge(types2, rootBodyElement, importStatements, elementType, pr
14689
14670
  headlessInstanceDefs: [],
14690
14671
  // Not used for bridge
14691
14672
  headlessInstanceCounter: { count: 0 },
14692
- coordinatePrefix: [],
14693
14673
  coordinateCounters: /* @__PURE__ */ new Map()
14694
14674
  });
14695
14675
  renderedBridge = optimizeRefs(renderedBridge, headlessImports);
@@ -14737,7 +14717,6 @@ function renderSandboxRoot(types2, rootBodyElement, importStatements, headlessIm
14737
14717
  headlessInstanceDefs: [],
14738
14718
  // Not used for sandbox
14739
14719
  headlessInstanceCounter: { count: 0 },
14740
- coordinatePrefix: [],
14741
14720
  coordinateCounters: /* @__PURE__ */ new Map()
14742
14721
  });
14743
14722
  let refsPart = renderedBridge.rendered.length > 0 ? `
@@ -19638,7 +19617,6 @@ function buildRenderContext(context) {
19638
19617
  headlessInstanceDefs: context.headlessInstanceDefs,
19639
19618
  headlessInstanceCounter: context.headlessInstanceCounter,
19640
19619
  // Element target still uses its own coordinate logic (DL#103: out of scope)
19641
- coordinatePrefix: [],
19642
19620
  coordinateCounters: /* @__PURE__ */ new Map()
19643
19621
  };
19644
19622
  }
@@ -19693,7 +19671,7 @@ function renderHydrateElement(element, context) {
19693
19671
  );
19694
19672
  const createAttributes = renderAttributes$1(element, createRenderContext);
19695
19673
  const needDynamicElement = createChildNodes.some(
19696
- (_) => _.nodeType === NodeType.ELEMENT_NODE && (isConditional(_) || isForEach(_) || isSlowForEach(_) || checkAsync(_).isAsync)
19674
+ (_) => _.nodeType === NodeType.ELEMENT_NODE && (isConditional(_) || isForEach(_) || checkAsync(_).isAsync)
19697
19675
  );
19698
19676
  const createElementFunc = needDynamicElement ? "de" : "e";
19699
19677
  const createElementImport = needDynamicElement ? Import.dynamicElement : Import.element;
@@ -19712,6 +19690,33 @@ ${context.indent.firstLine} ${createBody})`,
19712
19690
  childContent.refs
19713
19691
  );
19714
19692
  }
19693
+ if (isConditional(element) && context.interactivePaths.size > 0) {
19694
+ const condition = element.getAttribute("if");
19695
+ const viewStateVars = new Variables(
19696
+ context.variables.currentType,
19697
+ void 0,
19698
+ 0,
19699
+ "viewState"
19700
+ );
19701
+ const renderedCondition = parseServerCondition(condition, viewStateVars);
19702
+ const coordinate = element.getAttribute(COORD_ATTR) || "0";
19703
+ const childContent = renderHydrateElementContent(
19704
+ element,
19705
+ context,
19706
+ renderContext,
19707
+ coordinate,
19708
+ true
19709
+ );
19710
+ const adoption = childContent.rendered.trim();
19711
+ if (adoption) {
19712
+ return new RenderFragment(
19713
+ `${context.indent.firstLine}...(${renderedCondition.rendered} ? [${adoption}] : [])`,
19714
+ childContent.imports.plus(Import.adoptElement),
19715
+ [...renderedCondition.validations, ...childContent.validations],
19716
+ childContent.refs
19717
+ );
19718
+ }
19719
+ }
19715
19720
  if (isForEach(element)) {
19716
19721
  const { variables, indent } = context;
19717
19722
  const forEach = element.getAttribute("forEach");
@@ -19846,7 +19851,7 @@ ${indent.firstLine} ]` : "() => []";
19846
19851
  );
19847
19852
  const createAttributes = renderAttributes$1(element, createRenderContext);
19848
19853
  const forEachNeedsDynamic = createChildNodes.some(
19849
- (_) => _.nodeType === NodeType.ELEMENT_NODE && (isConditional(_) || isForEach(_) || isSlowForEach(_) || checkAsync(_).isAsync)
19854
+ (_) => _.nodeType === NodeType.ELEMENT_NODE && (isConditional(_) || isForEach(_) || checkAsync(_).isAsync)
19850
19855
  );
19851
19856
  const forEachElementFunc = forEachNeedsDynamic ? "de" : "e";
19852
19857
  const forEachElementImport = forEachNeedsDynamic ? Import.dynamicElement : Import.element;
@@ -19875,98 +19880,6 @@ ${indent.firstLine})`,
19875
19880
  );
19876
19881
  return nestRefs(forEachAccessor.terms, hydrateForEachFragment);
19877
19882
  }
19878
- if (isSlowForEach(element)) {
19879
- const slowForEachInfo = getSlowForEachInfo(element);
19880
- if (!slowForEachInfo) {
19881
- return new RenderFragment("", Imports.none(), [
19882
- `slowForEach element is missing required attributes (slowForEach, jayIndex, jayTrackBy)`
19883
- ]);
19884
- }
19885
- const { arrayName, jayIndex, jayTrackBy } = slowForEachInfo;
19886
- const { variables, indent } = context;
19887
- const slowValidated = validateSlowForEachAccessor(arrayName, variables);
19888
- if (isValidationError(slowValidated))
19889
- return slowValidated;
19890
- const { accessor: arrayAccessor, childVariables: slowForEachVariables } = slowValidated;
19891
- const parentTypeName = variables.currentType.name;
19892
- const itemTypeName = slowForEachVariables.currentType.name;
19893
- const paramName = arrayAccessor.rootVar;
19894
- const getItemsFragment = arrayAccessor.render().map((_) => `(${paramName}: ${parentTypeName}) => ${_}`);
19895
- const itemContext = {
19896
- ...context,
19897
- variables: slowForEachVariables,
19898
- indent: indent.child().child(),
19899
- dynamicRef: true,
19900
- insideSlowForEach: true
19901
- };
19902
- const itemChildNodes = filterContentNodes(element.childNodes);
19903
- const childFragments = itemChildNodes.map((child) => renderHydrateNode(child, itemContext));
19904
- const nonEmptyChildren = childFragments.filter((f) => f.rendered.trim());
19905
- if (nonEmptyChildren.length === 0) {
19906
- return RenderFragment.empty();
19907
- }
19908
- let callbackBody;
19909
- let callbackImports = Imports.none();
19910
- let callbackValidations = [];
19911
- let callbackRefs;
19912
- if (nonEmptyChildren.length === 1) {
19913
- callbackBody = nonEmptyChildren[0].rendered.trim();
19914
- callbackImports = nonEmptyChildren[0].imports;
19915
- callbackValidations = [...nonEmptyChildren[0].validations];
19916
- callbackRefs = nonEmptyChildren[0].refs;
19917
- } else {
19918
- const hasDynamicGroups = itemChildNodes.some(
19919
- (child) => child.nodeType === NodeType.ELEMENT_NODE && (isConditional(child) && conditionIsInteractive(
19920
- child.getAttribute("if"),
19921
- itemContext.interactivePaths
19922
- ) || isForEach(child) || isSlowForEach(child))
19923
- );
19924
- if (hasDynamicGroups) {
19925
- const childParts = [];
19926
- for (let i = 0; i < childFragments.length; i++) {
19927
- const frag = childFragments[i];
19928
- if (frag.rendered.trim()) {
19929
- childParts.push(frag.rendered);
19930
- callbackImports = callbackImports.plus(frag.imports);
19931
- callbackValidations.push(...frag.validations);
19932
- if (frag.refs)
19933
- callbackRefs = callbackRefs ? mergeRefsTrees(callbackRefs, frag.refs) : frag.refs;
19934
- } else if (itemChildNodes[i].nodeType === NodeType.ELEMENT_NODE) {
19935
- childParts.push(`${indent.firstLine} STATIC`);
19936
- callbackImports = callbackImports.plus(Import.STATIC);
19937
- }
19938
- }
19939
- const childrenArr = childParts.join(",\n");
19940
- const itemCoord = element.getAttribute(COORD_ATTR) || "";
19941
- callbackBody = `adoptDynamicElement('${itemCoord}', {}, [
19942
- ${childrenArr},
19943
- ${indent.firstLine} ])`;
19944
- callbackImports = callbackImports.plus(Import.adoptDynamicElement);
19945
- } else {
19946
- const itemCoord = element.getAttribute(COORD_ATTR) || "";
19947
- const childrenArr = nonEmptyChildren.map((f) => f.rendered).join(",\n");
19948
- callbackBody = `adoptElement('${itemCoord}', {}, [
19949
- ${childrenArr},
19950
- ${indent.firstLine} ])`;
19951
- for (const f of nonEmptyChildren) {
19952
- callbackImports = callbackImports.plus(f.imports);
19953
- callbackValidations.push(...f.validations);
19954
- if (f.refs)
19955
- callbackRefs = callbackRefs ? mergeRefsTrees(callbackRefs, f.refs) : f.refs;
19956
- }
19957
- callbackImports = callbackImports.plus(Import.adoptElement);
19958
- }
19959
- }
19960
- const slowForEachFragment = new RenderFragment(
19961
- `${indent.firstLine}slowForEachItem<${parentTypeName}, ${itemTypeName}>(${getItemsFragment.rendered}, ${jayIndex}, '${jayTrackBy}',
19962
- ${indent.firstLine}() => ${callbackBody}
19963
- ${indent.firstLine})`,
19964
- Imports.for(Import.slowForEachItem).plus(getItemsFragment.imports).plus(callbackImports),
19965
- [...getItemsFragment.validations, ...callbackValidations],
19966
- callbackRefs
19967
- );
19968
- return nestRefs(arrayName.split("."), slowForEachFragment);
19969
- }
19970
19883
  if (checkAsync(element).isAsync) {
19971
19884
  return RenderFragment.empty();
19972
19885
  }
@@ -20068,8 +19981,9 @@ ${adoptChildIndent.firstLine}])`,
20068
19981
  adoptChildren.refs
20069
19982
  );
20070
19983
  }
19984
+ const adoptMergedRefs = mergeContractStubRefs(adoptInlineBody.refs, headlessImport.refs);
20071
19985
  const { renderedRefsManager, refsManagerImport } = renderReferenceManager(
20072
- adoptInlineBody.refs,
19986
+ adoptMergedRefs,
20073
19987
  ReferenceManagerTarget.element
20074
19988
  );
20075
19989
  const adoptRenderFnCode = `
@@ -20125,7 +20039,6 @@ ${adoptInlineBody.rendered}
20125
20039
  // inside headfull FS component templates can be detected (DL#123)
20126
20040
  headlessContractNames: renderContext.headlessContractNames,
20127
20041
  headlessImports: renderContext.headlessImports,
20128
- coordinatePrefix: [],
20129
20042
  coordinateCounters: /* @__PURE__ */ new Map()
20130
20043
  };
20131
20044
  const createRenderedChildren = childNodes.map((_) => renderNode(_, createRenderContext)).reduce(
@@ -20145,7 +20058,8 @@ ${createRenderedChildren.rendered}
20145
20058
  } else {
20146
20059
  createInlineBody = createRenderedChildren;
20147
20060
  }
20148
- const { renderedRefsManager: createRefsManager, refsManagerImport: createRefsImport } = renderReferenceManager(createInlineBody.refs, ReferenceManagerTarget.element);
20061
+ const createMergedRefs = mergeContractStubRefs(createInlineBody.refs, headlessImport.refs);
20062
+ const { renderedRefsManager: createRefsManager, refsManagerImport: createRefsImport } = renderReferenceManager(createMergedRefs, ReferenceManagerTarget.element);
20149
20063
  createRenderFnCode = `
20150
20064
  function ${createRenderFnName}(options?: RenderElementOptions): ${preRenderType} {
20151
20065
  ${createRefsManager}
@@ -20475,7 +20389,6 @@ function renderHydrate(types2, body, importStatements, elementType, preRenderTyp
20475
20389
  headlessInstanceDefs: [],
20476
20390
  headlessInstanceCounter: { count: 0 },
20477
20391
  insideFastForEach: false,
20478
- insideSlowForEach: false,
20479
20392
  interactivePaths: buildInteractivePaths(contract)
20480
20393
  };
20481
20394
  const rootElement = ensureSingleChildElement(body);
@@ -20866,7 +20779,7 @@ function renderNode(node2, context) {
20866
20779
  if (childNodes.length === 1 && childNodes[0].nodeType === NodeType.TEXT_NODE)
20867
20780
  childIndent = childIndent.noFirstLineBreak();
20868
20781
  let needDynamicElement = childNodes.map(
20869
- (_) => isConditional(_) || isForEach(_) || isSlowForEach(_) || isRecurseWithData(_) || isWithData(_) || checkAsync(_).isAsync
20782
+ (_) => isConditional(_) || isForEach(_) || isRecurseWithData(_) || isWithData(_) || checkAsync(_).isAsync
20870
20783
  ).reduce((prev, current) => prev || current, false);
20871
20784
  let childRenders = childNodes.length === 0 ? RenderFragment.empty() : childNodes.map((_) => renderNode(_, contextForChildren)).reduce(
20872
20785
  (prev, current) => RenderFragment.merge(prev, current, ",\n"),
@@ -21033,8 +20946,9 @@ ${renderedChildren.rendered}
21033
20946
  inlineBody = renderedChildren;
21034
20947
  }
21035
20948
  }
20949
+ const mergedRefs = mergeContractStubRefs(inlineBody.refs, headlessImport.refs);
21036
20950
  const { renderedRefsManager, refsManagerImport } = renderReferenceManager(
21037
- inlineBody.refs,
20951
+ mergedRefs,
21038
20952
  ReferenceManagerTarget.element
21039
20953
  );
21040
20954
  const explicitRef = htmlElement.attributes.ref;
@@ -21042,7 +20956,7 @@ ${renderedChildren.rendered}
21042
20956
  if (explicitRef) {
21043
20957
  coordinateRef = explicitRef;
21044
20958
  } else {
21045
- const counterKey = [...newContext.coordinatePrefix, contractName].join("/");
20959
+ const counterKey = contractName;
21046
20960
  const localIndex = newContext.coordinateCounters.get(counterKey) ?? 0;
21047
20961
  newContext.coordinateCounters.set(counterKey, localIndex + 1);
21048
20962
  coordinateRef = `AR${localIndex}`;
@@ -21050,7 +20964,7 @@ ${renderedChildren.rendered}
21050
20964
  const isInsideForEach = newContext.insideFastForEach;
21051
20965
  const coordinateSuffix = `${contractName}:${coordinateRef}`;
21052
20966
  const instanceCoordBase = htmlElement.getAttribute("jay-coordinate-base");
21053
- const coordinateKey2 = isInsideForEach ? void 0 : instanceCoordBase || [...newContext.coordinatePrefix, coordinateSuffix].join("/");
20967
+ const coordinateKey2 = isInsideForEach ? void 0 : instanceCoordBase || coordinateSuffix;
21054
20968
  const renderFnCode = `
21055
20969
  // Inline template for headless component: ${contractName} #${idx}
21056
20970
  type ${elementType} = JayElement<${interactiveViewStateType}, ${refsTypeName}>;
@@ -21237,43 +21151,6 @@ const ${componentSymbol} = makeHeadlessInstanceComponent(
21237
21151
  forEachAccessPath,
21238
21152
  renderForEach(forEachFragment, forEachVariables, trackBy, childElement)
21239
21153
  );
21240
- } else if (isSlowForEach(htmlElement)) {
21241
- const slowForEachInfo = getSlowForEachInfo(htmlElement);
21242
- if (!slowForEachInfo) {
21243
- return new RenderFragment("", Imports.none(), [
21244
- `slowForEach element is missing required attributes (slowForEach, jayIndex, jayTrackBy)`
21245
- ]);
21246
- }
21247
- const { arrayName, jayIndex, jayTrackBy } = slowForEachInfo;
21248
- const slowValidated = validateSlowForEachAccessor(arrayName, variables);
21249
- if (isValidationError(slowValidated))
21250
- return slowValidated;
21251
- const { accessor: arrayAccessor, childVariables: slowForEachVariables } = slowValidated;
21252
- context.usedComponentImports.add(slowForEachVariables.currentType.name);
21253
- let newContext = {
21254
- ...context,
21255
- variables: slowForEachVariables,
21256
- indent: indent.child().noFirstLineBreak().withLastLineBreak(),
21257
- dynamicRef: true,
21258
- isInsideGuard: true,
21259
- // Mark that we're inside a guard
21260
- coordinatePrefix: [...context.coordinatePrefix, jayTrackBy]
21261
- };
21262
- let childElement = renderHtmlElement(htmlElement, newContext);
21263
- const parentTypeName = variables.currentType.name;
21264
- const itemTypeName = slowForEachVariables.currentType.name;
21265
- const paramName = arrayAccessor.rootVar;
21266
- const getItemsFragment = arrayAccessor.render().map((_) => `(${paramName}: ${parentTypeName}) => ${_}`);
21267
- const slowForEachFragment = new RenderFragment(
21268
- `${indent.firstLine}slowForEachItem<${parentTypeName}, ${itemTypeName}>(${getItemsFragment.rendered}, ${jayIndex}, '${jayTrackBy}',
21269
- ${indent.firstLine}() => ${childElement.rendered}
21270
- ${indent.firstLine})`,
21271
- childElement.imports.plus(Import.slowForEachItem).plus(getItemsFragment.imports),
21272
- [...getItemsFragment.validations, ...childElement.validations],
21273
- childElement.refs,
21274
- childElement.recursiveRegions
21275
- );
21276
- return nestRefs(arrayName.split("."), slowForEachFragment);
21277
21154
  } else if (checkAsync(htmlElement).isAsync) {
21278
21155
  const asyncDirective = checkAsync(htmlElement);
21279
21156
  const asyncProperty = htmlElement.getAttribute(asyncDirective.directive);
@@ -21412,8 +21289,6 @@ function renderFunctionImplementation$1(types2, rootBodyElement, importStatement
21412
21289
  // Accumulator for inline template definitions
21413
21290
  headlessInstanceCounter,
21414
21291
  // Counter for unique naming
21415
- coordinatePrefix: [],
21416
- // Root has empty coordinate prefix
21417
21292
  coordinateCounters: /* @__PURE__ */ new Map()
21418
21293
  // Scope-level counter for unique coordinates
21419
21294
  });
@@ -21666,6 +21541,9 @@ function generateElementBridgeFile(jayFile) {
21666
21541
  }
21667
21542
  function generateElementHydrateFile(jayFile, importerMode) {
21668
21543
  const types2 = generateTypes(jayFile.types);
21544
+ const headlessImports = jayFile.headlessImports?.filter((h) => !h.key) ?? [];
21545
+ const headlessContractNames = new Set(headlessImports.map((h) => h.contractName));
21546
+ assignCoordinates(jayFile.body, { headlessContractNames });
21669
21547
  const {
21670
21548
  renderedRefs,
21671
21549
  renderedElement,
@@ -22391,48 +22269,6 @@ ${indent.firstLine}}`,
22391
22269
  itemBody.validations
22392
22270
  );
22393
22271
  }
22394
- if (isSlowForEach(element)) {
22395
- const slowForEachInfo = getSlowForEachInfo(element);
22396
- if (slowForEachInfo) {
22397
- const { arrayName, jayIndex } = slowForEachInfo;
22398
- const slowValidated = validateSlowForEachAccessor(arrayName, variables);
22399
- if (isValidationError(slowValidated))
22400
- return slowValidated;
22401
- const { accessor: arrayAccessor, childVariables: slowForEachVariables } = slowValidated;
22402
- const arrayExpr = arrayAccessor.render().rendered;
22403
- const itemVar = slowForEachVariables.currentVar;
22404
- const itemContext = {
22405
- ...context,
22406
- variables: slowForEachVariables,
22407
- indent,
22408
- insideSlowForEach: true
22409
- };
22410
- const childContent = renderServerElementContent(element, itemContext, {
22411
- isRoot: true
22412
- });
22413
- const needsItemVar = childContent.rendered.includes(itemVar + ".");
22414
- if (needsItemVar) {
22415
- const itemIndent = new Indent(indent.curr + " ");
22416
- const indentedContext = {
22417
- ...context,
22418
- variables: slowForEachVariables,
22419
- indent: itemIndent,
22420
- insideSlowForEach: true
22421
- };
22422
- const indentedContent = renderServerElementContent(element, indentedContext, {
22423
- isRoot: true
22424
- });
22425
- return new RenderFragment(
22426
- `${indent.firstLine}{ const ${itemVar} = ${arrayExpr}?.[${jayIndex}]; if (${itemVar}) {
22427
- ${indentedContent.rendered}
22428
- ${indent.firstLine}}}`,
22429
- indentedContent.imports,
22430
- [...arrayAccessor.validations, ...indentedContent.validations]
22431
- );
22432
- }
22433
- return childContent;
22434
- }
22435
- }
22436
22272
  return renderServerElementContent(element, context);
22437
22273
  }
22438
22274
  function renderServerHeadlessInstance(element, context, contractName) {
@@ -22870,7 +22706,7 @@ function renderServerElementContent(element, context, options) {
22870
22706
  }
22871
22707
  }
22872
22708
  const refName = element.attributes.ref ? camelCase(element.attributes.ref) : null;
22873
- const needsCoordinate = options?.isRoot === true || isConditional(element) && conditionIsInteractive(element.getAttribute("if"), context.interactivePaths) || dynamicTextFragment !== null || refName !== null || hasDynamicAttributeBindings(element, variables) || hasInteractiveChildElements(childNodes) || hasMixedContentDynamicTextInteractive(childNodes, context.interactivePaths);
22709
+ const needsCoordinate = options?.isRoot === true || isConditional(element) || dynamicTextFragment !== null || refName !== null || hasDynamicAttributeBindings(element, variables) || hasInteractiveChildElements(childNodes) || hasMixedContentDynamicTextInteractive(childNodes, context.interactivePaths);
22874
22710
  const coordTemplate = needsCoordinate ? element.getAttribute(COORD_ATTR) : null;
22875
22711
  const isVoid = voidElements.has(element.rawTagName.toLowerCase());
22876
22712
  const closeTag = isVoid ? " />" : ">";
@@ -23059,7 +22895,6 @@ function generateServerElementFile(jayFile, _options) {
23059
22895
  headlessInstanceCounter: { count: 0 },
23060
22896
  varMappings: {},
23061
22897
  insideForEach: false,
23062
- insideSlowForEach: false,
23063
22898
  interactivePaths: buildInteractivePaths(jayFile.contract)
23064
22899
  };
23065
22900
  const rendered = renderServerElementContent(rootElement.val, context, {
@@ -29967,37 +29802,6 @@ function resolveTextBindings(text2, contextData, phaseMap, contextPath = "") {
29967
29802
  return new WithValidations(resolved, validationErrors);
29968
29803
  }
29969
29804
  function transformElement(element, phaseMap, contextPath, contextData) {
29970
- const forEachAttr = element.getAttribute("forEach");
29971
- if (forEachAttr) {
29972
- const fullPath = contextPath ? `${contextPath}.${forEachAttr}` : forEachAttr;
29973
- const phaseInfo = phaseMap.get(fullPath);
29974
- if (phaseInfo?.phase === "slow") {
29975
- const arrayValue = getValueByPath(contextData, forEachAttr);
29976
- if (Array.isArray(arrayValue)) {
29977
- const trackBy = element.getAttribute("trackBy") || "id";
29978
- const itemResults = arrayValue.map((item, index) => {
29979
- const cloned = element.clone();
29980
- cloned.removeAttribute("forEach");
29981
- cloned.removeAttribute("foreach");
29982
- cloned.removeAttribute("trackBy");
29983
- cloned.removeAttribute("trackby");
29984
- cloned.setAttribute("slowForEach", forEachAttr);
29985
- cloned.setAttribute("jayIndex", String(index));
29986
- const trackByValue = item && typeof item === "object" ? String(item[trackBy] || index) : String(index);
29987
- cloned.setAttribute("jayTrackBy", trackByValue);
29988
- const itemData = item;
29989
- return transformChildren(cloned, phaseMap, fullPath, itemData).map(
29990
- (children) => {
29991
- cloned.innerHTML = "";
29992
- children.forEach((child) => cloned.appendChild(child));
29993
- return cloned;
29994
- }
29995
- );
29996
- });
29997
- return WithValidations.all(itemResults);
29998
- }
29999
- }
30000
- }
30001
29805
  const ifAttr = element.getAttribute("if");
30002
29806
  if (ifAttr) {
30003
29807
  const slowContext = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jay-framework/compiler-jay-html",
3
- "version": "0.17.3",
3
+ "version": "0.18.0",
4
4
  "description": "",
5
5
  "license": "Apache-2.0",
6
6
  "main": "dist/index.js",
@@ -34,12 +34,12 @@
34
34
  },
35
35
  "author": "",
36
36
  "dependencies": {
37
- "@jay-framework/compiler-analyze-exported-types": "^0.17.3",
38
- "@jay-framework/compiler-shared": "^0.17.3",
39
- "@jay-framework/component": "^0.17.3",
40
- "@jay-framework/logger": "^0.17.3",
41
- "@jay-framework/runtime": "^0.17.3",
42
- "@jay-framework/secure": "^0.17.3",
37
+ "@jay-framework/compiler-analyze-exported-types": "^0.18.0",
38
+ "@jay-framework/compiler-shared": "^0.18.0",
39
+ "@jay-framework/component": "^0.18.0",
40
+ "@jay-framework/logger": "^0.18.0",
41
+ "@jay-framework/runtime": "^0.18.0",
42
+ "@jay-framework/secure": "^0.18.0",
43
43
  "@types/js-yaml": "^4.0.9",
44
44
  "change-case": "^4.1.2",
45
45
  "he": "^1.2.0",
@@ -52,8 +52,8 @@
52
52
  },
53
53
  "devDependencies": {
54
54
  "@caiogondim/strip-margin": "^1.0.0",
55
- "@jay-framework/4-react": "^0.17.3",
56
- "@jay-framework/dev-environment": "^0.17.3",
55
+ "@jay-framework/4-react": "^0.18.0",
56
+ "@jay-framework/dev-environment": "^0.18.0",
57
57
  "@testing-library/jest-dom": "^6.2.0",
58
58
  "@types/js-beautify": "^1",
59
59
  "@types/node": "^20.11.5",