Skip to content

Commit

Permalink
feat: render SVG content with lit svg` (#904)
Browse files Browse the repository at this point in the history
### **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
  • Loading branch information
ilhan007 committed Nov 15, 2019
1 parent 17c25ff commit 59fead4
Show file tree
Hide file tree
Showing 10 changed files with 134 additions and 57 deletions.
58 changes: 28 additions & 30 deletions packages/fiori/src/ShellBar.hbs

Large diffs are not rendered by default.

7 changes: 7 additions & 0 deletions packages/fiori/src/ShellBar.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ import UI5Element from "@ui5/webcomponents-base/dist/UI5Element.js";
import litRender from "@ui5/webcomponents-base/dist/renderer/LitRenderer.js";
import ResizeHandler from "@ui5/webcomponents-base/dist/delegate/ResizeHandler.js";
import ItemNavigation from "@ui5/webcomponents-base/dist/delegate/ItemNavigation.js";
import { getFeature } from "@ui5/webcomponents-base/dist/FeaturesRegistry.js";
import AnimationMode from "@ui5/webcomponents-base/dist/types/AnimationMode.js";
import { getAnimationMode } from "@ui5/webcomponents-base/dist/config/AnimationMode.js";
import { isSpace, isEscape } from "@ui5/webcomponents-base/dist/events/PseudoEvents.js";
import { getRTL } from "@ui5/webcomponents-base/dist/config/RTL.js";
import StandardListItem from "@ui5/webcomponents/dist/StandardListItem.js";
Expand Down Expand Up @@ -101,6 +104,8 @@ const metadata = {

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

onBeforeRendering() {
this.coPilot = (getAnimationMode() === AnimationMode.Full) ? getFeature("CoPilotAnimation") : { animated: false };

this._hiddenIcons = this._itemsInfo.filter(info => {
const isHidden = (info.classes.indexOf("ui5-shellbar-hidden-button") !== -1);
const isSet = info.classes.indexOf("ui5-shellbar-invisible-button") === -1;
Expand Down
1 change: 1 addition & 0 deletions packages/main/bundle.esm.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import "./dist/json-imports/LocaleData.js"

import "./dist/features/InputElementsFormSupport.js";
import "./dist/features/InputSuggestions.js";
import "./dist/features/CoPilotAnimation.js";
import "./AllIcons.js";

import Badge from "./dist/Badge.js";
Expand Down
2 changes: 2 additions & 0 deletions packages/main/lib/hbs2lit/src/compiler.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ const HTMLLitVisitor = require("./litVisitor2");
const PartialsVisitor = require("./partialsVisitor");
const Handlebars = require("handlebars/dist/handlebars.min.js");
const includesReplacer = require("./includesReplacer");
const svgProcessor = require("./svgProcessor");

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

result = svgProcessor.process(result);
return result;
};

Expand Down
69 changes: 69 additions & 0 deletions packages/main/lib/hbs2lit/src/svgProcessor.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@

const svgrx = new RegExp(/<svg[\s\S]*?>([\s\S]*?)<\/svg>/, 'g');
const blockrx = /block[0-9]+/g;

function process(input) {
let matches;
let template = input;
let blockCounter = 0;

matches = getSVGMatches(template);

if (!matches.length) {
return template;
}

matches.forEach(match => {
//(1) extract the SVG content as a separate block
const svgContentGroup = match[1];
const block = getSVGBlock(svgContentGroup, ++blockCounter);

// (2) replace the SVG content with its block called, e.g ${blockSVG(context)}
template = template.replace(svgContentGroup, block.usage);

// (3) look for internal blocks in the SVG content and replace their `html with `svg
template = replaceInternalBlocks(template, svgContentGroup);

// (4) append the SVG block definiton (built in step 1), e.g const blockSVG = (context) => {return svg`.*`}
template += block.definition;
});

return template;
}

function getSVGMatches(template) {
let matches = [];

while (svgMatch = svgrx.exec(template)) {
matches.push(svgMatch);
if (svgrx.lastIndex === svgMatch.index) {
svgrx.lastIndex++;
}
}

return matches;
}

function getSVGBlock(input, blockCounter) {
return {
usage: `\${blockSVG${blockCounter}(context)}`,
definition: `\nconst blockSVG${blockCounter} = (context) => {return svg\`${input}\`};`,
};
}

function replaceInternalBlocks(template, svgContent) {
const internalBlocks = svgContent.match(blockrx) || [];

internalBlocks.forEach(blockName => {
const rx = new RegExp(`const ${blockName}.*(html\`).*};`);
template = template.replace(rx, (match, p1) => {
return match.replace(p1, "svg\`");
});
});

return template;
}

module.exports = {
process: process
};
17 changes: 17 additions & 0 deletions packages/main/src/Icon.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<svg
class="ui5-icon-root"
dir="{{dir}}"
viewBox="0 0 512 512"
role="img"
preserveAspectRatio="xMidYMid meet"
aria-label="{{accessibleNameText}}"
xmlns="http://www.w3.org/2000/svg"
>
{{#if hasIconTooltip}}
<title id="{{_id}}-tooltip">{{accessibleNameText}}</title>
{{/if}}

<g role="presentation">
<path transform="translate(0, 512) scale(1, -1)" d="{{d}}"/>
</g>
</svg>
2 changes: 1 addition & 1 deletion packages/main/src/Icon.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { getRTL } from "@ui5/webcomponents-base/dist/config/RTL.js";
import { getIconData, isIconURI } from "@ui5/webcomponents-base/dist/SVGIconRegistry.js";
import createStyleInHead from "@ui5/webcomponents-base/dist/util/createStyleInHead.js";
import { fetchI18nBundle, getI18nBundle } from "@ui5/webcomponents-base/dist/i18nBundle.js";
import IconTemplate from "./IconTemplate.lit.js";
import IconTemplate from "./generated/templates/IconTemplate.lit.js";

// Styles
import iconCss from "./generated/themes/Icon.css.js";
Expand Down
25 changes: 0 additions & 25 deletions packages/main/src/IconTemplate.lit.js

This file was deleted.

8 changes: 8 additions & 0 deletions packages/main/src/features/CoPilotAnimation.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion packages/main/test/pages/Icon.html
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
</head>

<body style="padding: 20px;">
<ui5-icon title="add equipment" style="width: 50px; height: 50px; border: 1px solid red; "id="myIcon" src="sap-icon://add-equipment"></ui5-icon>
<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>
<ui5-icon src="sap-icon://add-equipment" class="icon-blue icon-medium"></ui5-icon>
<ui5-icon src="sap-icon://add-equipment" class="icon-blue icon-small"></ui5-icon>
<ui5-icon src="sap-icon://add-employee" class="icon-red"></ui5-icon>
Expand Down

0 comments on commit 59fead4

Please sign in to comment.