diff --git a/packages/base/.eslintignore b/packages/base/.eslintignore index 4561bc6e4ada..6fd845071650 100644 --- a/packages/base/.eslintignore +++ b/packages/base/.eslintignore @@ -16,4 +16,6 @@ package-scripts.cjs src/renderer/directives/style-map.js src/util/metaUrl.js src/ssr-dom* -index.js \ No newline at end of file +index.js +jsx-runtime.d.ts +jsx-dev-runtime.d.ts diff --git a/packages/base/package.json b/packages/base/package.json index 612c088ad1f6..e96da47003ab 100644 --- a/packages/base/package.json +++ b/packages/base/package.json @@ -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", @@ -33,6 +34,7 @@ "./bundle.esm.js": "./bundle.esm.js", "./*": "./dist/*" }, + "types": "./dist", "scripts": { "clean": "nps clean", "lint": "nps lint", @@ -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", diff --git a/packages/base/src/jsx-dev-runtime.ts b/packages/base/src/jsx-dev-runtime.ts new file mode 100644 index 000000000000..5c4d2ff73ded --- /dev/null +++ b/packages/base/src/jsx-dev-runtime.ts @@ -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, context?: any) { + return _Fragment(props, context); +} +export function jsxDEV(type: string | typeof UI5Element, props: Record, 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 }; diff --git a/packages/base/src/jsx-runtime.ts b/packages/base/src/jsx-runtime.ts new file mode 100644 index 000000000000..8d6894fc663c --- /dev/null +++ b/packages/base/src/jsx-runtime.ts @@ -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, context?: any) { + return _Fragment(props, context); +} +export function jsx(type: string | typeof UI5Element, props: Record, 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, key: string) { + return _jsxs(type, props, key); +} +export { JSX }; diff --git a/packages/base/src/renderer/JsxRenderer.ts b/packages/base/src/renderer/JsxRenderer.ts new file mode 100644 index 000000000000..910870c63c43 --- /dev/null +++ b/packages/base/src/renderer/JsxRenderer.ts @@ -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; diff --git a/packages/main/src/Icon.ts b/packages/main/src/Icon.ts index e594b4578902..83b07525083a 100644 --- a/packages/main/src/Icon.ts +++ b/packages/main/src/Icon.ts @@ -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. @@ -316,6 +317,18 @@ class Icon extends UI5Element implements IIcon { } } +type ElementProps = Partial>; + +// JSX support +interface IconEvents { + onTabChange2: () => void +} + +// eslint-disable-next-line @typescript-eslint/no-unsafe-declaration-merging +interface Icon { + _jsxProps: ElementProps & Partial; +} + Icon.define(); export default Icon; diff --git a/packages/main/src/Text.ts b/packages/main/src/Text.ts index 9e2049b9a73a..b05a775f34c5 100644 --- a/packages/main/src/Text.ts +++ b/packages/main/src/Text.ts @@ -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, @@ -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 { diff --git a/packages/main/src/TextTemplate.tsx b/packages/main/src/TextTemplate.tsx new file mode 100644 index 000000000000..a39008215e88 --- /dev/null +++ b/packages/main/src/TextTemplate.tsx @@ -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 & { onTabChange?: (e: any) => void }; + } + } + } + +type ElementProps = Partial>; + +function UI5Icon(props: ElementProps) { + return +} + +// class Icon2{} + +export default (props: Text) => { + return <> + {}} name="account" showTooltip={false}> + + {/* */} + + {/* */} + console.log(e)}> + { props.emptyIndicatorMode } + { props._renderEmptyIndicator ? + <> + + { props._emptyIndicatorAriaLabel } + + : + + } + + +; +} \ No newline at end of file diff --git a/packages/main/tsconfig.json b/packages/main/tsconfig.json index a1850462744a..80c6fc3daee3 100644 --- a/packages/main/tsconfig.json +++ b/packages/main/tsconfig.json @@ -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/*": [ diff --git a/yarn.lock b/yarn.lock index 23ffd110a9f3..9a36a078c4d9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -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"