Skip to content

Commit 59fead4

Browse files
authored
feat: render SVG content with lit svg` (#904)
### **Background** The SVG tag itself should be rendered with the html function, but its content must be rendered with the svg function of lit-html. Otherwise dynamic updates inside the svg do not work. ### **Othe changes** **ui5-icon** - Create Icon HBS template and remove the IconLitTemplate as it will be generated properly **ui5-shellbar** - Update ShellBar`s CoPilot animates (taken from latest openui5) - Make ShellBar`s animated CoPilot add-on feature, by default the CoPilot is displayed as static SVG . To make it animated you have the following public import: ```js import "@ui5/webcomponents/dist/features/CoPilotAnimation.js": ``` - Start considering the global `animationMode` config regarding the CoPilot animation BREAKING CHANGE: to get the ShellBar's coPilot animated you have to import the `@ui5/webcomponents/dist/features/CoPilotAnimation.js` module
1 parent 17c25ff commit 59fead4

File tree

10 files changed

+134
-57
lines changed

10 files changed

+134
-57
lines changed

packages/fiori/src/ShellBar.hbs

+28-30
Large diffs are not rendered by default.

packages/fiori/src/ShellBar.js

+7
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@ import UI5Element from "@ui5/webcomponents-base/dist/UI5Element.js";
22
import litRender from "@ui5/webcomponents-base/dist/renderer/LitRenderer.js";
33
import ResizeHandler from "@ui5/webcomponents-base/dist/delegate/ResizeHandler.js";
44
import ItemNavigation from "@ui5/webcomponents-base/dist/delegate/ItemNavigation.js";
5+
import { getFeature } from "@ui5/webcomponents-base/dist/FeaturesRegistry.js";
6+
import AnimationMode from "@ui5/webcomponents-base/dist/types/AnimationMode.js";
7+
import { getAnimationMode } from "@ui5/webcomponents-base/dist/config/AnimationMode.js";
58
import { isSpace, isEscape } from "@ui5/webcomponents-base/dist/events/PseudoEvents.js";
69
import { getRTL } from "@ui5/webcomponents-base/dist/config/RTL.js";
710
import StandardListItem from "@ui5/webcomponents/dist/StandardListItem.js";
@@ -101,6 +104,8 @@ const metadata = {
101104

102105
/**
103106
* Defines, if the product CoPilot icon would be displayed.
107+
* <br><b>Note:</b> By default the co-pilot is displayed as static SVG.
108+
* If you need an animated co-pilot, you can import the <code>"@ui5/webcomponents/dist/features/CoPilotAnimation.js"</code> module as add-on feature.
104109
* @type {boolean}
105110
* @defaultvalue false
106111
* @public
@@ -449,6 +454,8 @@ class ShellBar extends UI5Element {
449454
}
450455

451456
onBeforeRendering() {
457+
this.coPilot = (getAnimationMode() === AnimationMode.Full) ? getFeature("CoPilotAnimation") : { animated: false };
458+
452459
this._hiddenIcons = this._itemsInfo.filter(info => {
453460
const isHidden = (info.classes.indexOf("ui5-shellbar-hidden-button") !== -1);
454461
const isSet = info.classes.indexOf("ui5-shellbar-invisible-button") === -1;

packages/main/bundle.esm.js

+1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import "./dist/json-imports/LocaleData.js"
1313

1414
import "./dist/features/InputElementsFormSupport.js";
1515
import "./dist/features/InputSuggestions.js";
16+
import "./dist/features/CoPilotAnimation.js";
1617
import "./AllIcons.js";
1718

1819
import Badge from "./dist/Badge.js";

packages/main/lib/hbs2lit/src/compiler.js

+2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ const HTMLLitVisitor = require("./litVisitor2");
22
const PartialsVisitor = require("./partialsVisitor");
33
const Handlebars = require("handlebars/dist/handlebars.min.js");
44
const includesReplacer = require("./includesReplacer");
5+
const svgProcessor = require("./svgProcessor");
56

67
const removeWhiteSpaces = (source) => {
78
return source.replace(/\n+/g, "").replace(/\s+</g, "<").replace(/}}\s+{{/g, "}}{{");
@@ -29,6 +30,7 @@ const compileString = async (sInput, config) => {
2930
result += lv.blocks[key] + "\n";
3031
}
3132

33+
result = svgProcessor.process(result);
3234
return result;
3335
};
3436

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
2+
const svgrx = new RegExp(/<svg[\s\S]*?>([\s\S]*?)<\/svg>/, 'g');
3+
const blockrx = /block[0-9]+/g;
4+
5+
function process(input) {
6+
let matches;
7+
let template = input;
8+
let blockCounter = 0;
9+
10+
matches = getSVGMatches(template);
11+
12+
if (!matches.length) {
13+
return template;
14+
}
15+
16+
matches.forEach(match => {
17+
//(1) extract the SVG content as a separate block
18+
const svgContentGroup = match[1];
19+
const block = getSVGBlock(svgContentGroup, ++blockCounter);
20+
21+
// (2) replace the SVG content with its block called, e.g ${blockSVG(context)}
22+
template = template.replace(svgContentGroup, block.usage);
23+
24+
// (3) look for internal blocks in the SVG content and replace their `html with `svg
25+
template = replaceInternalBlocks(template, svgContentGroup);
26+
27+
// (4) append the SVG block definiton (built in step 1), e.g const blockSVG = (context) => {return svg`.*`}
28+
template += block.definition;
29+
});
30+
31+
return template;
32+
}
33+
34+
function getSVGMatches(template) {
35+
let matches = [];
36+
37+
while (svgMatch = svgrx.exec(template)) {
38+
matches.push(svgMatch);
39+
if (svgrx.lastIndex === svgMatch.index) {
40+
svgrx.lastIndex++;
41+
}
42+
}
43+
44+
return matches;
45+
}
46+
47+
function getSVGBlock(input, blockCounter) {
48+
return {
49+
usage: `\${blockSVG${blockCounter}(context)}`,
50+
definition: `\nconst blockSVG${blockCounter} = (context) => {return svg\`${input}\`};`,
51+
};
52+
}
53+
54+
function replaceInternalBlocks(template, svgContent) {
55+
const internalBlocks = svgContent.match(blockrx) || [];
56+
57+
internalBlocks.forEach(blockName => {
58+
const rx = new RegExp(`const ${blockName}.*(html\`).*};`);
59+
template = template.replace(rx, (match, p1) => {
60+
return match.replace(p1, "svg\`");
61+
});
62+
});
63+
64+
return template;
65+
}
66+
67+
module.exports = {
68+
process: process
69+
};

packages/main/src/Icon.hbs

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<svg
2+
class="ui5-icon-root"
3+
dir="{{dir}}"
4+
viewBox="0 0 512 512"
5+
role="img"
6+
preserveAspectRatio="xMidYMid meet"
7+
aria-label="{{accessibleNameText}}"
8+
xmlns="http://www.w3.org/2000/svg"
9+
>
10+
{{#if hasIconTooltip}}
11+
<title id="{{_id}}-tooltip">{{accessibleNameText}}</title>
12+
{{/if}}
13+
14+
<g role="presentation">
15+
<path transform="translate(0, 512) scale(1, -1)" d="{{d}}"/>
16+
</g>
17+
</svg>

packages/main/src/Icon.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { getRTL } from "@ui5/webcomponents-base/dist/config/RTL.js";
44
import { getIconData, isIconURI } from "@ui5/webcomponents-base/dist/SVGIconRegistry.js";
55
import createStyleInHead from "@ui5/webcomponents-base/dist/util/createStyleInHead.js";
66
import { fetchI18nBundle, getI18nBundle } from "@ui5/webcomponents-base/dist/i18nBundle.js";
7-
import IconTemplate from "./IconTemplate.lit.js";
7+
import IconTemplate from "./generated/templates/IconTemplate.lit.js";
88

99
// Styles
1010
import iconCss from "./generated/themes/Icon.css.js";

packages/main/src/IconTemplate.lit.js

-25
This file was deleted.

packages/main/src/features/CoPilotAnimation.js

+8
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/main/test/pages/Icon.html

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
</head>
2424

2525
<body style="padding: 20px;">
26-
<ui5-icon title="add equipment" style="width: 50px; height: 50px; border: 1px solid red; "id="myIcon" src="sap-icon://add-equipment"></ui5-icon>
26+
<ui5-icon title="add equipment" style="width: 50px; height: 50px; border: 1px solid red; "id="myIcon" show-tooltip accessible-name="Hello SVG Icon" src="sap-icon://add-equipment"></ui5-icon>
2727
<ui5-icon src="sap-icon://add-equipment" class="icon-blue icon-medium"></ui5-icon>
2828
<ui5-icon src="sap-icon://add-equipment" class="icon-blue icon-small"></ui5-icon>
2929
<ui5-icon src="sap-icon://add-employee" class="icon-red"></ui5-icon>

0 commit comments

Comments
 (0)