@sap-ux/fe-fpm-writer 1.3.19 → 1.3.21

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.
@@ -60,14 +60,18 @@ export async function generateBuildingBlock(basePath, config, fs) {
60
60
  hasAggregation,
61
61
  aggregationNamespace
62
62
  };
63
- const templateDocument = getTemplateDocument({ ...processedBuildingBlockData, generateId: fnGenerateId }, xmlDocument, fs, manifest, templateConfig);
64
63
  const fullPageTemplate = isFullPageTemplate(buildingBlockData);
65
64
  const pageAggregationNames = getPageAggregationNames(buildingBlockData);
65
+ // The full page template renders a default IconTabBar that acts as the page's sticky subheader
66
+ // (removing the empty gap between header and tab bar). Generate its id once so the Page's
67
+ // stickySubheaderProvider and the IconTabBar share the same collision-safe id.
68
+ const stickySubheaderId = fullPageTemplate ? fnGenerateId('stickySubheaderBar') : undefined;
69
+ const templateDocument = getTemplateDocument({ ...processedBuildingBlockData, stickySubheaderId, generateId: fnGenerateId }, xmlDocument, fs, manifest, templateConfig);
66
70
  if (fullPageTemplate) {
67
71
  validateFullPageTemplateVersion(manifest);
68
72
  }
69
73
  if (pageAggregationNames) {
70
- appendPageAggregations(fs, xmlDocument, templateDocument, fnGenerateId, pageAggregationNames, fullPageTemplate);
74
+ appendPageAggregations(fs, xmlDocument, templateDocument, fnGenerateId, pageAggregationNames, fullPageTemplate, stickySubheaderId);
71
75
  }
72
76
  if (buildingBlockData.buildingBlockType === BuildingBlockType.RichTextEditor ||
73
77
  buildingBlockData.buildingBlockType === BuildingBlockType.RichTextEditorButtonGroups) {
@@ -315,7 +319,8 @@ export async function getSerializedFileContent(basePath, config, fs) {
315
319
  const xmlDocument = viewOrFragmentPath ? getUI5XmlDocument(basePath, viewOrFragmentPath, fs) : undefined;
316
320
  const { content: manifest, path: manifestPath } = await getManifest(basePath, fs, false);
317
321
  const fnGenerateId = buildingBlockData.generateId ?? (await createIdGenerator({ basePath, fsEditor: fs }));
318
- const content = getTemplateContent({ ...buildingBlockData, generateId: fnGenerateId }, xmlDocument, manifest, fs, true);
322
+ const stickySubheaderId = isFullPageTemplate(buildingBlockData) ? fnGenerateId('stickySubheaderBar') : undefined;
323
+ const content = getTemplateContent({ ...buildingBlockData, stickySubheaderId, generateId: fnGenerateId }, xmlDocument, manifest, fs, true);
319
324
  // For full Page templates, augment the snippet with all PAGE_AGGREGATIONS
320
325
  let viewOrFragmentContent = content;
321
326
  const pageAggNames = getPageAggregationNames(buildingBlockData);
@@ -333,7 +338,7 @@ export async function getSerializedFileContent(basePath, config, fs) {
333
338
  const snippetDoc = new DOMParser(getDOMParserOptions(TEMPLATE_NAMESPACES, (level, message) => {
334
339
  throw new Error(`Unable to parse Page building block snippet. Details: [${level}] - ${message}`);
335
340
  })).parseFromString(snippetContent, 'text/xml');
336
- appendPageAggregations(fs, nsDoc, snippetDoc, fnGenerateId, pageAggNames, isFullPageTemplate(buildingBlockData));
341
+ appendPageAggregations(fs, nsDoc, snippetDoc, fnGenerateId, pageAggNames, isFullPageTemplate(buildingBlockData), stickySubheaderId);
337
342
  const resultNode = snippetDoc.documentElement;
338
343
  viewOrFragmentContent = resultNode ? format(new XMLSerializer().serializeToString(resultNode)) : content;
339
344
  }
@@ -49,8 +49,9 @@ export declare function buildAggregationIds(aggName: PageAggregationName, genera
49
49
  * @param generateId - function to generate unique IDs
50
50
  * @param [aggNames] - aggregation names to append; defaults to all PAGE_AGGREGATIONS
51
51
  * @param useDefaults - when true, the items aggregation renders its default IconTabBar content
52
+ * @param stickySubheaderId - collision-safe id for the default IconTabBar, shared with the Page's stickySubheaderProvider
52
53
  */
53
- export declare function appendPageAggregations(fs: Editor, xmlDocument: Document, templateDocument: Document, generateId: IdGeneratorFunction, aggNames?: readonly PageAggregationName[], useDefaults?: boolean): void;
54
+ export declare function appendPageAggregations(fs: Editor, xmlDocument: Document, templateDocument: Document, generateId: IdGeneratorFunction, aggNames?: readonly PageAggregationName[], useDefaults?: boolean, stickySubheaderId?: string): void;
54
55
  /**
55
56
  * Reorders the child elements of a macros:Page node to match the canonical PAGE_AGGREGATIONS order.
56
57
  * Preserves relative order of siblings with the same local name. Pure whitespace text nodes are dropped
@@ -143,6 +143,7 @@ export function buildAggregationIds(aggName, generateId, existingIds = []) {
143
143
  * @param aggContext.showDefaultContent - when true, the items template renders the default IconTabBar
144
144
  * @param aggContext.ids - map of unique IDs for named controls in the template (e.g. ids.Button, ids.Link)
145
145
  * @param aggContext.aggIndex - 1-based counter for this aggregation add (used to number text/press handler names)
146
+ * @param aggContext.stickySubheaderId - collision-safe id for the default IconTabBar, shared with the Page's stickySubheaderProvider
146
147
  * @param fragMacrosNS - the namespace prefix resolved for sap.fe.macros
147
148
  * @param xmlDocument - the view XML document (used to inherit namespace declarations)
148
149
  * @returns parsed XML document whose documentElement contains the aggregation child nodes
@@ -167,8 +168,9 @@ function buildPageAggregationFragment(fs, aggName, aggContext, fragMacrosNS, xml
167
168
  * @param generateId - function to generate unique IDs
168
169
  * @param [aggNames] - aggregation names to append; defaults to all PAGE_AGGREGATIONS
169
170
  * @param useDefaults - when true, the items aggregation renders its default IconTabBar content
171
+ * @param stickySubheaderId - collision-safe id for the default IconTabBar, shared with the Page's stickySubheaderProvider
170
172
  */
171
- export function appendPageAggregations(fs, xmlDocument, templateDocument, generateId, aggNames = PAGE_AGGREGATIONS, useDefaults = true) {
173
+ export function appendPageAggregations(fs, xmlDocument, templateDocument, generateId, aggNames = PAGE_AGGREGATIONS, useDefaults = true, stickySubheaderId) {
172
174
  const fragMacrosNS = resolveMacrosPrefix(xmlDocument);
173
175
  const macrosPrefix = `${fragMacrosNS}:`;
174
176
  const pageElement = templateDocument.documentElement;
@@ -177,7 +179,7 @@ export function appendPageAggregations(fs, xmlDocument, templateDocument, genera
177
179
  const aggId = generateId(aggName);
178
180
  const showDefaultContent = aggName === 'items' && useDefaults;
179
181
  const ids = buildAggregationIds(aggName, generateId);
180
- const aggContext = { macrosPrefix, aggId, showDefaultContent, ids, aggIndex: 1 };
182
+ const aggContext = { macrosPrefix, aggId, showDefaultContent, ids, aggIndex: 1, stickySubheaderId };
181
183
  const aggDoc = buildPageAggregationFragment(fs, aggName, aggContext, fragMacrosNS, xmlDocument);
182
184
  for (const node of Array.from(aggDoc.documentElement.childNodes)) {
183
185
  if (node.nodeType === 1 /* Element */) {
@@ -398,6 +398,12 @@ export interface Page extends BuildingBlock {
398
398
  * When templateType is 'full', each entry is written as the inner XML of the corresponding aggregation.
399
399
  */
400
400
  aggregations?: Partial<Record<PageAggregationName, string>>;
401
+ /**
402
+ * Collision-safe id of the IconTabBar that acts as the page's sticky subheader.
403
+ * Set internally for the full template so the Page's stickySubheaderProvider and the
404
+ * generated IconTabBar share the same id. Not part of the public input.
405
+ */
406
+ stickySubheaderId?: string;
401
407
  }
402
408
  export declare const PAGE_TEMPLATE_COMMENT = "This is a sample template, event handlers should be added for implementation";
403
409
  export declare const MACROS_NAMESPACE_URI = "sap.fe.macros";
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@sap-ux/fe-fpm-writer",
3
3
  "description": "SAP Fiori elements flexible programming model writer",
4
- "version": "1.3.19",
4
+ "version": "1.3.21",
5
5
  "repository": {
6
6
  "type": "git",
7
7
  "url": "https://github.com/SAP/open-ux-tools.git",
@@ -31,9 +31,9 @@
31
31
  "semver": "7.8.5",
32
32
  "xml-formatter": "3.7.0",
33
33
  "xpath": "0.0.34",
34
- "@sap-ux/fiori-annotation-api": "1.1.0",
35
- "@sap-ux/i18n": "1.0.4",
36
- "@sap-ux/project-access": "2.2.1",
34
+ "@sap-ux/fiori-annotation-api": "1.1.1",
35
+ "@sap-ux/i18n": "1.0.5",
36
+ "@sap-ux/project-access": "2.2.2",
37
37
  "@sap-ux/logger": "1.0.3"
38
38
  },
39
39
  "devDependencies": {
@@ -2,5 +2,6 @@
2
2
  id="<%- data.id %>"<% if (data.title) { %>
3
3
  title="<%- data.title %>"<% } %><% if (data.description) { %>
4
4
  description="<%- data.description %>"<% } %><% if (data.templateType === 'full') { %>
5
- showFooter="true"<% } %>
6
- />
5
+ showFooter="true"
6
+ stickySubheaderProvider="<%- data.stickySubheaderId %>"<% } %>
7
+ />
@@ -1,7 +1,7 @@
1
1
  <<%- macrosPrefix %>items>
2
2
  <!-- Main content -->
3
3
  <% if (showDefaultContent) { -%>
4
- <IconTabBar id="iconTabBar<%- aggId %>" class="sapUiResponsiveContentPadding">
4
+ <IconTabBar id="<%- stickySubheaderId %>" class="sapUiResponsiveContentPadding">
5
5
  <items>
6
6
  <IconTabFilter id="iconTabFilter<%- aggId %>" text="Tab 1">
7
7
  </IconTabFilter>