npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@rdme/babel-plugin-jsx-ui5

v1.2.0

Published

Babel transformer for JSX syntax to UI5 RM calls

Downloads

10

Readme

@rdme/babel-plugin-jsx-ui5

npm i --save-dev @rdme/babel-plugin-jsx-ui5

Summary

@rdme/babel-plugin-jsx-ui5 is a babel plugin for transforming JSX expressions to UI5 RenderManager calls. Embedded controls, aggregations and event handlers are supported. It works for ES6 Classes, UI5 Control.extend calls and UI5 Renderer files, though event handlers are not supported for UI5 Renderer files, as it modifies the onAfterRendering method.

Usage

To use this plugin simply install it via npm i --save-dev @rdme/babel-plugin-jsx-ui5 and add it to your babel configuration like this:

{
	"plugins": ["@rdme/jsx-ui5"]
}

Control Data

To write control data, like control ids, etc. use the ui5control attribute. It supports an optional jsx expression containing the control.

Ex1:

<div ui5control />
// Becomes
rm.write("<div");
rm.writeControlData(control);
rm.writeClasses();
rm.write("/>");

Ex2:

<div ui5control={someControl} />
// Becomes
rm.write("<div");
rm.writeControlData(someControl);
rm.writeClasses();
rm.write("/>");

Element Data

Element data functions exactly like control data, just using the ui5element attribute instead.

IDs

ID attributes are automatically prefixed by the control id. It works with text nodes and jsx expressions.

Ex1:

<span id="someSpan" />
// Becomes
rm.write("<span");
rm.writeAttributeEscaped(control.getId() + '-' + "someSpan");
rm.writeClasses();
rm.write("/>");

Ex2:

<span id={control.getSomething()} />
// Becomes
rm.write("<span");
rm.writeAttributeEscaped(control.getId() + '-' + control.getSomething());
rm.writeClasses();
rm.write("/>");

Classes

Classes can be defined using a string with space-sepparated class name or a jsx expression. If a jsx expression is given, it may contain anything resembling an array, an object or a string. This does not have to be a literal.

Examples:

<div class="some class"></div>
<div class={["some","class"]}></div>
<div class={{some:true,class:true,foo:false}}></div>
// Will all render
<div class="some class"></div>

Styles

Styles can be defined using a string with styles or a jsx expression. If a jsx expression is given, it may contain anything resembling an array, an object or a string. This does not have to be a literal.

Examples:

<div style="width:10px;height:20px;"></div>
<div style={{width:"10px",height:"20px"}}></div>
<div style={[{name:'width',value:'10px'},{name:'height',value:'20px'}]}></div>
// Will all render
<div style="width: 10px; height: 20px"></div>

Event Handlers

Event handlers are special attributes starting with "on" (e.g. "onclick"). They expect a value in form of a jsx expression or string literal and are only supported inside of classes or UI5 'extend' expressions, as they modify or create the onAfterRendering method for the given control. These attributes will be stripped from the control and a special handler class ('__handler' + incrementing number) is added. Later in the onAfterRendering method the event handlers will be attached to the controls using jQuery. If a string is given as a value, it is assumed to be a method declared on the current control and will be bound correspondingly. If however a jsx expression is given, it will not be bound or accessed on "this", so it is necessary to bind it yourself. Also take note that since the contents of the expressions are moved to the onAfterRendering method, the this context changes from the renderer to the control.

Ex1:

// Renderer
<button onclick="_onButtonClick">Press Me</button>
// Becomes
// Renderer
rm.write("<button");
rm.addClass("__handler0");
rm.writeClasses();
rm.write(">");
rm.writeEscaped("Press Me");
rm.write("</button>");
// onAfterRendering
this.$().find('.__handler0').on('click',this._onButtonClick.bind(this));

Ex2:

// Renderer
<button onclick={this._onButtonClick.bind(this)}>Press Me</button>
// Becomes
// Renderer
rm.write("<button");
rm.addClass("__handler0");
rm.writeClasses();
rm.write(">");
rm.writeEscaped("Press Me");
rm.write("</button>");
// onAfterRendering
this.$().find('.__handler0').on('click',this._onButtonClick.bind(this));

Ex3:

// Renderer
<button onclick={alert.bind(window,"Hello World")}>Press Me</button>
// Becomes
// Renderer
rm.write("<button");
rm.addClass("__handler0");
rm.writeClasses();
rm.write(">");
rm.writeEscaped("Press Me");
rm.write("</button>");
// onAfterRendering
this.$().find('.__handler0').on('click',alert.bind(window,"Hello World"));

Ex4:

// Renderer
<button onclick="fireButtonPress">Press Me</button>
// Becomes
// Renderer
rm.write("<button");
rm.addClass("__handler0");
rm.writeClasses();
rm.write(">");
rm.writeEscaped("Press Me");
rm.write("</button>");
// onAfterRendering
this.$().find('.__handler0').on('click',this.fireButtonPress.bind(this));

Spread Attributes

Spread attributes are supported in the form of arrays or objects. They will not be interpreted by the special attributes such as "id", "class", "style", "on*", "ui5*".

Aggregations

Aggregations with multiple controls can be embedded with <ui5aggregation> tags. They expect either a text node or jsx expression as a child. If a text node is given, it will look up the given text (trimmed) with control.getAggregation(text). If a jsx expression is given, it will just use it without wrapping it in a control.getAggregation call.

Ex1:

<ui5aggregation>content</ui5aggregation>
// Becomes
(control.getAggregation("content") || []).forEach(rm.renderControl.bind(rm));

Ex2:

<ui5aggregation>{control.getContent()}</ui5aggregation>
// Becomes
(control.getContent() || []).forEach(rm.renderControl.bind(rm));

Controls

Single control aggregations can be embedded with <ui5control> tags. Similar to aggregations with multiple controls, single control aggregations expect either a text node or jsx expression as a child. If a text node is given, it will look up the given text (trimmed) with control.getAggregation(text). If a jsx expression is given, it will just use it without wrapping it in a control.getAggregation call.

Ex1:

<ui5control>content</ui5control>
// Becomes
if(control.getAggregation("content")) rm.renderControl(control.getAggregation("content"));

Ex2:

<ui5control>{control.getContent()}</ui5control>
// Becomes
if(control.getContent()) rm.renderControl(control.getContent());

Icons

For UI5 Icons there exists a helper tag called <ui5icon>. It expects a text node or jsx expression as a child. If a text node is given, it is assumed to be an icon url or image source. If you need to provide additional classes or attributes, you can pass a jsx expression with an embedded array literal instead. All arguments provided in said array literal are passed to the UI5 RenderManager method writeIcon.

Ex1:

<ui5icon>sap-icon://accept</ui5icon>
// Becomes
rm.writeIcon("sap-icon://accept");

Ex2:

<ui5icon>{["sap-icon://value-help",["some-class"],{"aria-hidden":true}]}</ui5icon>
// Becomes
rm.writeIcon("sap-icon://value-help",["some-class"],{"aria-hidden":true});

Examples

UI5 Control

This will work out of the box without any other plugins

sap.ui.define(["sap/ui/core/Control"], function(Control) {
	return Control.extend("my.Control",{
		metadata: {
			properties: {
				title: { type: "string" },
			},
			aggregations: {
				content: { type: "sap.ui.core.Control", multiple: true },
				footer: { type: "sap.m.IBar", multiple: false }
			},
			events: {
				buttonPress: {}
			}
		},
		renderer: {
			render: function(rm, control) {
				rm.render(<div ui5control>
					<h1>{control.getTitle()}</h1>
					<div id="content">
						<ui5aggregation>content</ui5aggregation>
					</div>
					{this.renderFoobar(rm,control)}
					<button onclick="fireButtonPress">
						<ui5icon>sap-icon://accept</ui5icon>
						Press Me!
					</button>
					<ui5control>footer</ui5control>
				</div>);
			},
			renderFoobar: function(rm, control) {
				rm.render(<div id="foobar">
					<span>Foobar</span>
				</div>);
			},
		}
	});
});

ES6 Class

This needs additional plugins for import and exports and class properties (e.g. babel-plugin-transform-modules-ui5).

import Control from "sap/ui/core/Control";
export default class MyControl extends Control {
	static metadata = {
		properties: {
			title: { type: "string" },
		},
		aggregations: {
			content: { type: "sap.ui.core.Control", multiple: true },
			footer: { type: "sap.m.IBar", multiple: false }
		},
		events: {
			buttonPress: {}
		}
	},
	static renderer = {
		render(rm, control) {
			rm.render(<div ui5control>
				<h1>{control.getTitle()}</h1>
				<div id="content">
					<ui5aggregation>content</ui5aggregation>
				</div>
				{this.renderFoobar(rm,control)}
				<button onclick="fireButtonPress">
					<ui5icon>sap-icon://accept</ui5icon>
					Press Me!
				</button>
				<ui5control>footer</ui5control>
			</div>);
		},
		renderFoobar(rm, control) {
			rm.render(<div id="foobar">
				<span>Foobar</span>
			</div>);
		},
	}
}