Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add TSX template support #10046

Draft
wants to merge 4 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion packages/base/.eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,6 @@ package-scripts.cjs
src/renderer/directives/style-map.js
src/util/metaUrl.js
src/ssr-dom*
index.js
index.js
jsx-runtime.d.ts
jsx-dev-runtime.d.ts
7 changes: 5 additions & 2 deletions packages/base/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,9 @@
"url": "https://github.com/SAP/ui5-webcomponents.git",
"directory": "packages/base"
},
"types": "./dist",
"exports": {
"./jsx-runtime": "./dist/jsx-runtime.js",
"./jsx-dev-runtime": "./dist/jsx-dev-runtime.js",
"./dist/ssr-dom.js": {
"browser": "./dist/ssr-dom.js",
"node": "./dist/ssr-dom-shim.js",
Expand All @@ -33,6 +34,7 @@
"./bundle.esm.js": "./bundle.esm.js",
"./*": "./dist/*"
},
"types": "./dist",
"scripts": {
"clean": "nps clean",
"lint": "nps lint",
Expand All @@ -48,7 +50,8 @@
},
"dependencies": {
"@lit-labs/ssr-dom-shim": "^1.1.2",
"lit-html": "^2.0.1"
"lit-html": "^2.0.1",
"preact": "^10.24.3"
},
"devDependencies": {
"@openui5/sap.ui.core": "1.120.17",
Expand Down
27 changes: 27 additions & 0 deletions packages/base/src/jsx-dev-runtime.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// eslint-disable-next-line import/extensions
import { jsxDEV as _jsxDEV, Fragment as _Fragment } from "preact/jsx-runtime";
import type { JSX as _JSX } from "preact/jsx-runtime";
import type UI5Element from "./UI5Element.js";

// eslint-disable-next-line @typescript-eslint/no-namespace
declare namespace JSX {
export interface IntrinsicElements extends _JSX.IntrinsicElements {}
export type ElementClass = unknown;
export interface ElementAttributesProperty {
_jsxProps: any;
}
export interface HTMLAttributes extends _JSX.HTMLAttributes {}
export interface SVGAttributes extends _JSX.SVGAttributes {}
}

export function Fragment(props: Record<string, any>, context?: any) {
return _Fragment(props, context);
}
export function jsxDEV(type: string | typeof UI5Element, props: Record<string, any>, key: string) {
let tag = type;
if (typeof type === "function" && "getMetadata" in type) {
tag = type.getMetadata().getTag();
}
return _jsxDEV(tag as string, props, key);
}
export { JSX };
30 changes: 30 additions & 0 deletions packages/base/src/jsx-runtime.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// eslint-disable-next-line import/extensions
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "preact/jsx-runtime";
import type { JSX as _JSX } from "preact/jsx-runtime";
import type UI5Element from "./UI5Element.js";

// eslint-disable-next-line @typescript-eslint/no-namespace
declare namespace JSX {
export interface IntrinsicElements extends _JSX.IntrinsicElements {}
export type ElementClass = unknown;
export interface ElementAttributesProperty {
_jsxProps: any;
}
export interface HTMLAttributes extends _JSX.HTMLAttributes {}
export interface SVGAttributes extends _JSX.SVGAttributes {}
}

export function Fragment(props: Record<string, any>, context?: any) {
return _Fragment(props, context);
}
export function jsx(type: string | typeof UI5Element, props: Record<string, any>, key: string) {
let tag = type;
if (typeof type === "function" && "getMetadata" in type) {
tag = type.getMetadata().getTag();
}
return _jsx(tag as string, props, key);
}
export function jsxs(type: string, props: Record<string, any>, key: string) {
return _jsxs(type, props, key);
}
export { JSX };
14 changes: 14 additions & 0 deletions packages/base/src/renderer/JsxRenderer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import {
render,
} from "preact";

import type { TemplateResult } from "lit-html";

import type { Renderer } from "../UI5Element.js";
import type { TemplateFunctionResult } from "./executeTemplate.js";

const jsxRender: Renderer = (templateResult: TemplateFunctionResult, container: HTMLElement | DocumentFragment) => {
render(templateResult as TemplateResult, container);
};

export default jsxRender;
13 changes: 13 additions & 0 deletions packages/main/src/Icon.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ const ICON_NOT_FOUND = "ICON_NOT_FOUND";
@event("click", {
bubbles: true,
})
// eslint-disable-next-line @typescript-eslint/no-unsafe-declaration-merging
class Icon extends UI5Element implements IIcon {
/**
* Defines the component semantic design.
Expand Down Expand Up @@ -316,6 +317,18 @@ class Icon extends UI5Element implements IIcon {
}
}

type ElementProps<I> = Partial<Omit<I, keyof HTMLElement>>;

// JSX support
interface IconEvents {
onTabChange2: () => void
}

// eslint-disable-next-line @typescript-eslint/no-unsafe-declaration-merging
interface Icon {
_jsxProps: ElementProps<Icon> & Partial<IconEvents>;
}

Icon.define();

export default Icon;
Expand Down
9 changes: 5 additions & 4 deletions packages/main/src/Text.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@ import UI5Element from "@ui5/webcomponents-base/dist/UI5Element.js";
import customElement from "@ui5/webcomponents-base/dist/decorators/customElement.js";
import property from "@ui5/webcomponents-base/dist/decorators/property.js";
import slot from "@ui5/webcomponents-base/dist/decorators/slot.js";
import litRender from "@ui5/webcomponents-base/dist/renderer/LitRenderer.js";
import jsxRender from "@ui5/webcomponents-base/dist/renderer/JsxRenderer.js";
import { getScopedVarName } from "@ui5/webcomponents-base/dist/CustomElementsScope.js";
import i18n from "@ui5/webcomponents-base/dist/decorators/i18n.js";
import type I18nBundle from "@ui5/webcomponents-base/dist/i18nBundle.js";
import willShowContent from "@ui5/webcomponents-base/dist/util/willShowContent.js";
import type { TemplateFunction } from "@ui5/webcomponents-base/dist/renderer/executeTemplate.js";
import EmptyIndicatorMode from "./types/TextEmptyIndicatorMode.js";
// Template
import TextTemplate from "./generated/templates/TextTemplate.lit.js";
import TextTemplate2 from "./TextTemplate.js";

import {
EMPTY_INDICATOR_SYMBOL,
Expand Down Expand Up @@ -49,8 +50,8 @@ import styles from "./generated/themes/Text.css.js";
*/
@customElement({
tag: "ui5-text",
renderer: litRender,
template: TextTemplate,
renderer: jsxRender,
template: TextTemplate2 as unknown as TemplateFunction,
styles,
})
class Text extends UI5Element {
Expand Down
39 changes: 39 additions & 0 deletions packages/main/src/TextTemplate.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import type Text from "./Text.js";
import Icon from "./Icon.js";
declare module "preact/jsx-runtime" {
namespace JSX {
interface IntrinsicElements {
"ui5-icon": ElementProps<Icon> & { onTabChange?: (e: any) => void };
}
}
}

type ElementProps<I> = Partial<Omit<I, keyof HTMLElement>>;

function UI5Icon(props: ElementProps<Icon>) {
return <ui5-icon {...props}></ui5-icon>
}

// class Icon2{}

export default (props: Text) => {
return <>
<ui5-icon onTabChange={()=>{}} name="account" showTooltip={false}></ui5-icon>
<Icon name="appointment" design="Critical" mode="Decorative"></Icon>
{/* <Icon2 name="appointment" design="Critical" mode="Decorative"></Icon2> */}
<UI5Icon name="home" mode="Image"></UI5Icon>
{/* <GenUI5Icon name="home" mode="Image"></GenUI5Icon> */}
<span onClick={e => console.log(e)}>
<span> { props.emptyIndicatorMode } </span>
{ props._renderEmptyIndicator ?
<>
<span className="empty-indicator" aria-hidden="true">{ props._emptyIndicatorSymbol }</span>
<span className="empty-indicator-aria-label">{ props._emptyIndicatorAriaLabel }</span>
</>
:
<slot></slot>
}
</span>
</>
;
}
2 changes: 2 additions & 0 deletions packages/main/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
"tsBuildInfoFile": "dist/.tsbuildinfo",
"module": "NodeNext",
"moduleResolution": "NodeNext",
"jsx": "react-jsx",
"jsxImportSource": "@ui5/webcomponents-base",
"verbatimModuleSyntax": true,
"paths": {
"@ui5/webcomponents-base/dist/*": [
Expand Down
5 changes: 5 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -14417,6 +14417,11 @@ postinstall-postinstall@^2.1.0:
resolved "https://registry.yarnpkg.com/postinstall-postinstall/-/postinstall-postinstall-2.1.0.tgz#4f7f77441ef539d1512c40bd04c71b06a4704ca3"
integrity sha512-7hQX6ZlZXIoRiWNrbMQaLzUUfH+sSx39u8EJ9HYuDc1kLo9IXKWjM5RSquZN1ad5GnH8CGFM78fsAAQi3OKEEQ==

preact@^10.24.3:
version "10.24.3"
resolved "https://registry.yarnpkg.com/preact/-/preact-10.24.3.tgz#086386bd47071e3b45410ef20844c21e23828f64"
integrity sha512-Z2dPnBnMUfyQfSQ+GBdsGa16hz35YmLmtTLhM169uW944hYL6xzTYkJjC07j+Wosz733pMWx0fgON3JNw1jJQA==

prefix-matches@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/prefix-matches/-/prefix-matches-1.0.1.tgz#02e34ce27f33af48e68bbfce2aac2a004bc2b76c"
Expand Down
Loading