diff --git a/.eslintrc.js b/.eslintrc.js index 3c4ce4ae326..a13fb684caf 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -68,7 +68,7 @@ module.exports = { camelcase: [ 'error', { - allow: ['sap_fiori_3', 'sap_fiori_3_dark'] + allow: ['sap_fiori_3', 'sap_fiori_3_dark', 'sap_belize', 'sap_belize_hcb', 'sap_belize_hcw'] } ], 'comma-dangle': 'error', diff --git a/.storybook/manager.js b/.storybook/manager.js index ca01b0f00d2..5f97dfb2760 100644 --- a/.storybook/manager.js +++ b/.storybook/manager.js @@ -32,5 +32,11 @@ addons.setConfig({ * sidebar tree animations * @type {Boolean} */ - sidebarAnimations: true + sidebarAnimations: true, + + /** + * enable/disable shortcuts + * @type {Boolean} + */ + enableShortcuts: false }); diff --git a/.storybook/preview.js b/.storybook/preview.js index 38bd9fb42a3..27a6a6fb7ef 100644 --- a/.storybook/preview.js +++ b/.storybook/preview.js @@ -3,17 +3,17 @@ import { makeDecorator } from '@storybook/addons'; import { addDecorator, addParameters } from '@storybook/react'; import { setTheme } from '@ui5/webcomponents-base/dist/config/Theme'; import '@ui5/webcomponents-base/dist/features/browsersupport/IE11'; -import '@ui5/webcomponents-fiori/dist/json-imports/Themes'; +import '@ui5/webcomponents-fiori/dist/generated/json-imports/Themes'; import '@ui5/webcomponents-react-base/polyfill/IE11'; import { ContentDensity } from '@ui5/webcomponents-react/lib/ContentDensity'; import { ThemeProvider } from '@ui5/webcomponents-react/lib/ThemeProvider'; import { Themes } from '@ui5/webcomponents-react/lib/Themes'; -import '@ui5/webcomponents/dist/json-imports/i18n'; -import '@ui5/webcomponents/dist/json-imports/Themes'; +import '@ui5/webcomponents-react/lib/ThemingSupport'; +import '@ui5/webcomponents-theme-base/dist/Assets'; +import '@ui5/webcomponents/dist/features/InputElementsFormSupport'; +import '@ui5/webcomponents/dist/generated/json-imports/i18n'; +import '@ui5/webcomponents/dist/generated/json-imports/Themes'; import '@webcomponents/webcomponentsjs/webcomponents-bundle'; -import { window } from 'global'; -import 'highlight.js/styles/solarized-dark.css'; -import qs from 'qs'; import React, { useEffect } from 'react'; import 'react-app-polyfill/ie11'; @@ -30,14 +30,14 @@ addParameters({ addDecorator(withKnobs); -const ThemeContainer = ({ theme, contentDensity, children, setQueryParam, direction }) => { +const ThemeContainer = ({ theme, contentDensity, children, direction }) => { useEffect(() => { if (contentDensity === ContentDensity.Compact) { document.body.classList.add('ui5-content-density-compact'); } else { document.body.classList.remove('ui5-content-density-compact'); } - }, [contentDensity, setQueryParam]); + }, [contentDensity]); useEffect(() => { document.querySelector('html').setAttribute('dir', direction.toLowerCase()); @@ -47,38 +47,18 @@ const ThemeContainer = ({ theme, contentDensity, children, setQueryParam, direct setTheme(theme); }, [theme]); - return children; + return {children}; }; const withQuery = makeDecorator({ - name: 'withQuery', - parameterName: 'query', + name: 'themr', + parameterName: 'themr', wrapper: (getStory, context) => { - function setQueryParam(queryObj) { - const iframe = window.parent.document.getElementById('storybook-preview-iframe'); - const [base, search] = iframe.src.split('?'); - const currentQuery = qs.parse(search, { ignoreQueryPrefix: true }); - iframe.src = `${base}?${qs.stringify({ ...currentQuery, ...queryObj })}`; - } - - let contentDensity; - try { - const iframe = window.parent.document.getElementById('storybook-preview-iframe'); - const currentQuery = qs.parse(iframe.src.split('?')[1]); - contentDensity = - currentQuery['sap-ui-compactSize'] && currentQuery['sap-ui-compactSize'] !== 'false' - ? ContentDensity.Compact - : ContentDensity.Cozy; - } catch (e) { - contentDensity = ContentDensity.Compact; - } - return ( {getStory(context)} @@ -86,14 +66,4 @@ const withQuery = makeDecorator({ } }); -const themr = makeDecorator({ - name: 'themr', - parameterName: 'themr', - skipIfNoParametersOrOptions: false, - wrapper: (getStory, context) => { - return {getStory(context)}; - } -}); - addDecorator(withQuery); -addDecorator(themr); diff --git a/config/jestsetup.ts b/config/jestsetup.ts index de97793de3e..920cf7dd571 100644 --- a/config/jestsetup.ts +++ b/config/jestsetup.ts @@ -5,7 +5,7 @@ import Adapter from 'enzyme-adapter-react-16'; import { createSerializer } from 'enzyme-to-json'; import ResizeObserver from 'resize-observer-polyfill'; import 'intersection-observer'; -import '@ui5/webcomponents/dist/json-imports/i18n'; +import '@ui5/webcomponents/dist/generated/json-imports/i18n'; process.env.NODE_ENV = 'test'; process.env.BABEL_ENV = 'test'; diff --git a/docs/welcome/Welcome.stories.mdx b/docs/welcome/Welcome.stories.mdx index c6976525ed7..22ebc913f9d 100644 --- a/docs/welcome/Welcome.stories.mdx +++ b/docs/welcome/Welcome.stories.mdx @@ -59,6 +59,27 @@ Then, you can use the Button in your app: You could import all components also from `@ui5/webcomponents-react` directly, but this will have a negative impact on your bundle size. +### Theming + +UI5 Web Components and UI5 Web Components for React are both coming with the `sap_fiori_3` a.k.a. `Quartz` Theme built in. +In case you want to change your applications' theme, you have to import a couple of modules: +```js +import { setTheme } from '@ui5/webcomponents-base/dist/config/Theme'; +import '@ui5/webcomponents-theme-base/dist/Assets'; +import '@ui5/webcomponents/dist/generated/json-imports/Themes'; +import '@ui5/webcomponents-fiori/dist/generated/json-imports/Themes'; // only if you are using the ShellBar or the Product Switch +import '@ui5/webcomponents-react/lib/ThemingSupport'; +``` + +In addition to call `setTheme` with a string parameter of the new theme, you must pass the new `theme` as a prop into the `ThemeProvider` component. +Passing the prop is a temporary solution until the UI5 Web Components are providing [all Theming Parameters](https://github.com/SAP/ui5-webcomponents/issues/1396).
+Available Themes: +- `sap_fiori_3` (default) +- `sap_fiori_dark` +- `sap_belize` +- `sap_belize_hcb` +- `sap_belize_hcw` + ### Configure Compact/Cozy setting UI5 Web Components supports ```Compact``` and ```Cozy``` mode. It is set to ```Cozy``` by default. To enable ```Compact``` globally, provide the option ```compactSize: true``` in the configuration ```script``` tag: diff --git a/package.json b/package.json index c4047e4600e..4c69c11747d 100644 --- a/package.json +++ b/package.json @@ -30,6 +30,9 @@ "@babel/core": "^7.8.7", "@babel/plugin-proposal-nullish-coalescing-operator": "^7.8.0", "@babel/plugin-proposal-optional-chaining": "^7.8.0", + "@rollup/plugin-json": "^4.0.2", + "@rollup/plugin-node-resolve": "^7.1.1", + "@rollup/plugin-replace": "^2.3.1", "@storybook/storybook-deployer": "^2.8.1", "@types/enzyme": "^3.10.5", "@types/jest": "^25.1.2", @@ -54,13 +57,8 @@ "eslint": "^6.8.0", "eslint-plugin-prefer-arrow": "^1.1.7", "eslint-plugin-react": "^7.18.3", - "esm": "^3.2.22", - "extract-comments": "^1.1.0", - "file-loader": "^5.0.2", - "file-url": "^3.0.0", "filesize": "^6.0.1", "glob": "^7.1.6", - "global": "^4.4.0", "google-closure-compiler": "^20200204.0.0", "gzip-size": "^5.1.0", "husky": "^4.2.1", @@ -77,30 +75,20 @@ "ncp": "^2.0.0", "npm-run-all": "^4.1.5", "prettier": "^1.19.1", - "puppeteer": "^2.1.1", - "qs": "^6.9.1", "react": "^16.8.6", "react-app-polyfill": "^1.0.6", "react-dom": "^16.8.6", "rimraf": "^3.0.1", - "rollup": "^1.31.0", + "rollup": "^2.3.1", "rollup-plugin-babel": "^4.3.2", - "rollup-plugin-commonjs": "^10.1.0", - "rollup-plugin-node-resolve": "^5.2.0", - "rollup-plugin-postcss": "^2.0.6", "rollup-plugin-prettier": "^0.6.0", - "rollup-plugin-replace": "^2.2.0", - "rollup-plugin-strip-banner": "^1.0.0", + "rollup-plugin-strip-banner": "^2.0.0", "shelljs": "^0.8.3", "sinon": "^8.1.1", "targz": "^1.0.1", "tmp": "^0.1.0", - "ts-node": "8.6.2", "tslint": "^6.0.0", - "typescript": "^3.8.3", - "util": "^0.12.0", - "webpack": "^4.42.0", - "webpack-cli": "^3.3.11" + "typescript": "^3.8.3" }, "resolutions": { "@types/react": "16.9.2" diff --git a/packages/base/package.json b/packages/base/package.json index bc0b44a76a9..1d56389f075 100644 --- a/packages/base/package.json +++ b/packages/base/package.json @@ -33,6 +33,9 @@ "resize-observer-polyfill": "^1.5.1", "smoothscroll-polyfill": "^0.4.4" }, + "devDependencies": { + "@sap-theming/theming-base-content": "11.1.18" + }, "peerDependencies": { "react": "^16.8.0", "react-jss": "^10.0.4" diff --git a/packages/base/scripts/cssVariables/parse.js b/packages/base/scripts/cssVariables/parse.js index a998fdb0d7f..70c831603be 100644 --- a/packages/base/scripts/cssVariables/parse.js +++ b/packages/base/scripts/cssVariables/parse.js @@ -1,7 +1,9 @@ const { writeFileSync } = require('fs'); -const { root } = require('./themeDesignerVariables'); +const { root } = require('@sap-theming/theming-base-content/content/Base/baseLib/sap_fiori_3/variables.json'); const PATHS = require('../../../../config/paths'); const path = require('path'); +const prettier = require('prettier'); +const prettierConfig = require('../../../../prettier.config'); const variables = Object.keys(root); @@ -21,4 +23,7 @@ for (const variable of variables) { } fileContent += '}\n'; -writeFileSync(path.join(PATHS.packages, 'base', 'src', 'styling', 'ThemingParameters.ts'), fileContent); +writeFileSync( + path.join(PATHS.packages, 'base', 'src', 'styling', 'ThemingParameters.ts'), + prettier.format(fileContent, prettierConfig) +); diff --git a/packages/base/scripts/cssVariables/themeDesignerVariables.json b/packages/base/scripts/cssVariables/themeDesignerVariables.json deleted file mode 100644 index 5122c1c03b0..00000000000 --- a/packages/base/scripts/cssVariables/themeDesignerVariables.json +++ /dev/null @@ -1,336 +0,0 @@ -{ - "root": { - "sapBrandColor": "#0a6ed1", - "sapHighlightColor": "#0854a0", - "sapBaseColor": "#fff", - "sapShellColor": "#354a5f", - "sapBackgroundColor": "#f7f7f7", - "sapFontFamily": "\"72\", \"72full\", Arial, Helvetica, sans-serif", - "sapFontHeaderFamily": "\"72\", \"72full\", Arial, Helvetica, sans-serif", - "sapFontSize": ".875rem", - "sapFontSmallSize": ".75rem", - "sapFontLargeSize": "1rem", - "sapFontHeader1Size": "2.25rem", - "sapFontHeader2Size": "1.5rem", - "sapFontHeader3Size": "1.25rem", - "sapFontHeader4Size": "1.125rem", - "sapFontHeader5Size": "1rem", - "sapFontHeader6Size": ".875rem", - "sapTextColor": "#32363a", - "sapLinkColor": "#0a6ed1", - "sapLink_Hover_Color": "#0854a0", - "sapLink_Active_Color": "#0a6ed1", - "sapLink_Visited_Color": "#0a6ed1", - "sapLink_InvertedColor": "#d3e8fd", - "sapCompanyLogo": "none", - "sapBackgroundImage": "none", - "sapBackgroundImageOpacity": "1.0", - "sapBackgroundImageRepeat": "false", - "sapSelectedColor": "#0854a0", - "sapActiveColor": "#0854a0", - "sapHighlightTextColor": "#fff", - "sapTitleColor": "#32363a", - "sapNegativeColor": "#bb0000", - "sapCriticalColor": "#e9730c", - "sapPositiveColor": "#107e3e", - "sapInformativeColor": "#0a6ed1", - "sapNeutralColor": "#6a6d70", - "sapNegativeElementColor": "#bb0000", - "sapCriticalElementColor": "#e9730c", - "sapPositiveElementColor": "#107e3e", - "sapInformativeElementColor": "#0a6ed1", - "sapNeutralElementColor": "#6a6d70", - "sapNegativeTextColor": "#bb0000", - "sapPositiveTextColor": "#107e3e", - "sapCriticalTextColor": "#e9730c", - "sapInformativeTextColor": "#053b70", - "sapNeutralTextColor": "#6a6d70", - "sapNeutralBorderColor": "#6a6d70", - "sapErrorColor": "#bb0000", - "sapErrorBorderColor": "#bb0000", - "sapWarningColor": "#e9730c", - "sapWarningBorderColor": "#e9730c", - "sapSuccessColor": "#107e3e", - "sapSuccessBorderColor": "#107e3e", - "sapInformationColor": "#0a6ed1", - "sapInformationBorderColor": "#0a6ed1", - "sapErrorBackground": "#ffebeb", - "sapWarningBackground": "#fef7f1", - "sapSuccessBackground": "#f1fdf6", - "sapInformationBackground": "#f5faff", - "sapNeutralBackground": "#f4f4f4", - "sapIndicationColor_1": "#880000", - "sapIndicationColor_2": "#bb0000", - "sapIndicationColor_3": "#e9730c", - "sapIndicationColor_4": "#107e3e", - "sapIndicationColor_5": "#0a6ed1", - "sapElement_LineHeight": "2.75rem", - "sapElement_Height": "2.25rem", - "sapElement_BorderWidth": ".0625rem", - "sapElement_BorderCornerRadius": ".25rem", - "sapElement_Compact_LineHeight": "2rem", - "sapElement_Compact_Height": "1.625rem", - "sapElement_Condensed_LineHeight": "1.5rem", - "sapElement_Condensed_Height": "1.375rem", - "sapContent_LineHeight": "1.4", - "sapContent_IconHeight": "1rem", - "sapContent_IconColor": "#0854a0", - "sapContent_ContrastIconColor": "#fff", - "sapContent_NonInteractiveIconColor": "#6a6d70", - "sapContent_MarkerIconColor": "#286eb4", - "sapContent_MarkerTextColor": "#0f828f", - "sapContent_ImagePlaceholderBackground": "#ccc", - "sapContent_ImagePlaceholderForegroundColor": "#fff", - "sapContent_RatedColor": "#d08014", - "sapContent_UnratedColor": "#89919a", - "sapContent_FocusColor": "#000", - "sapContent_FocusStyle": "dotted", - "sapContent_FocusWidth": ".0625rem", - "sapContent_ContrastFocusColor": "#fff", - "sapContent_ShadowColor": "#000", - "sapContent_ContrastShadowColor": "#fff", - "sapContent_Shadow0": "0 0 0 0.0625rem rgba(0,0,0,0.1), 0 0.125rem 0.5rem 0 rgba(0,0,0,0.1)", - "sapContent_Shadow1": "0 0 0 0.0625rem rgba(0,0,0,0.15), 0 0.125rem 0.5rem 0 rgba(0,0,0,0.3)", - "sapContent_Shadow2": "0 0 0 0.0625rem rgba(0,0,0,0.15), 0 0.625rem 1.875rem 0 rgba(0,0,0,0.3)", - "sapContent_Shadow3": "0 0 0 0.0625rem rgba(0,0,0,0.15), 0 1.25rem 5rem 0 rgba(0,0,0,0.3)", - "sapContent_TextShadow": "0 0 0.125rem #fff", - "sapContent_HeaderShadow": "0 0 0.25rem 0 rgba(0,0,0,0.15), inset 0 -0.0625rem 0 0 #d9d9d9", - "sapContent_SearchHighlightColor": "#d4f7db", - "sapContent_HelpColor": "#3f8600", - "sapContent_LabelColor": "#6a6d70", - "sapContent_MonospaceFontFamily": "lucida console, monospace", - "sapContent_DisabledTextColor": "rgba(50,54,58,0.6)", - "sapContent_DisabledOpacity": "0.4", - "sapContent_ContrastTextThreshold": "0.65", - "sapContent_ContrastTextColor": "#fff", - "sapContent_ForegroundColor": "#efefef", - "sapContent_ForegroundBorderColor": "#89919a", - "sapContent_ForegroundTextColor": "#32363a", - "sapContent_BadgeBackground": "#d04343", - "sapContent_DragAndDropActiveColor": "#0854a0", - "sapShell_Background": "#edeff0", - "sapShell_BackgroundImage": "linear-gradient(to bottom, #dfe3e4, #f3f4f5)", - "sapShell_BackgroundGradient": "linear-gradient(to bottom, #dfe3e4, #f3f4f5)", - "sapShell_BackgroundImageOpacity": "1.0", - "sapShell_BackgroundImageRepeat": "false", - "sapShell_BorderColor": "#354a5f", - "sapShell_TextColor": "#fff", - "sapShell_InteractiveTextColor": "#d1e8ff", - "sapShell_InteractiveBorderColor": "#7996b4", - "sapShell_GroupTitleTextColor": "#32363a", - "sapShell_Hover_Background": "#283848", - "sapShell_Active_Background": "#23303e", - "sapShell_Active_TextColor": "#fff", - "sapShell_Selected_Background": "#23303e", - "sapShell_Selected_TextColor": "#fff", - "sapShell_Selected_Hover_Background": "#23303e", - "sapShell_Favicon": "none", - "sapShell_Navigation_Background": "#fff", - "sapShell_Navigation_SelectedColor": "#0854a0", - "sapShell_Navigation_Selected_TextColor": "#0854a0", - "sapShell_Navigation_TextColor": "#32363a", - "sapShell_Shadow": "0 0 0.25rem 0 rgba(0,0,0,0.15), inset 0 -0.0625rem 0 0 rgba(0,0,0,0.15)", - "sapButton_BorderWidth": ".0625rem", - "sapButton_BorderCornerRadius": ".25rem", - "sapButton_Background": "#fff", - "sapButton_BorderColor": "#0854a0", - "sapButton_TextColor": "#0854a0", - "sapButton_Hover_Background": "#ebf5fe", - "sapButton_Hover_BorderColor": "#0854a0", - "sapButton_Hover_TextColor": "#0854a0", - "sapButton_IconColor": "#0854a0", - "sapButton_Active_Background": "#0854a0", - "sapButton_Active_BorderColor": "#0854a0", - "sapButton_Active_TextColor": "#fff", - "sapButton_Emphasized_Background": "#0a6ed1", - "sapButton_Emphasized_BorderColor": "#0a6ed1", - "sapButton_Emphasized_TextColor": "#fff", - "sapButton_Emphasized_Hover_Background": "#085caf", - "sapButton_Emphasized_Hover_BorderColor": "#085caf", - "sapButton_Emphasized_Hover_TextColor": "#fff", - "sapButton_Emphasized_Active_Background": "#0854a0", - "sapButton_Emphasized_Active_BorderColor": "#0854a0", - "sapButton_Emphasized_TextShadow": "transparent", - "sapButton_Accept_Background": "#fff", - "sapButton_Accept_BorderColor": "#107e3e", - "sapButton_Accept_Hover_Background": "#f1fdf6", - "sapButton_Accept_Hover_BorderColor": "#107e3e", - "sapButton_Accept_Hover_TextColor": "#107e3e", - "sapButton_Accept_Active_Background": "#0d6733", - "sapButton_Accept_Active_BorderColor": "#0d6733", - "sapButton_Accept_TextColor": "#107e3e", - "sapButton_Reject_Background": "#fff", - "sapButton_Reject_BorderColor": "#bb0000", - "sapButton_Reject_Hover_Background": "#ffebeb", - "sapButton_Reject_Hover_BorderColor": "#bb0000", - "sapButton_Reject_Hover_TextColor": "#b00", - "sapButton_Reject_Active_Background": "#a20000", - "sapButton_Reject_Active_BorderColor": "#a20000", - "sapButton_Reject_TextColor": "#b00", - "sapButton_Lite_Background": "transparent", - "sapButton_Lite_BorderColor": "transparent", - "sapButton_Lite_TextColor": "#0854a0", - "sapButton_Lite_Hover_Background": "#ebf5fe", - "sapButton_Lite_Hover_BorderColor": "#0854a0", - "sapButton_Lite_Hover_TextColor": "#0854a0", - "sapButton_Lite_Active_Background": "#0854a0", - "sapButton_Lite_Active_BorderColor": "#0854a0", - "sapButton_Selected_Background": "#0854a0", - "sapButton_Selected_BorderColor": "#0854a0", - "sapButton_Selected_TextColor": "#fff", - "sapButton_Selected_Hover_Background": "#095caf", - "sapButton_Selected_Hover_BorderColor": "#095caf", - "sapField_Background": "#fff", - "sapField_TextColor": "#32363a", - "sapField_PlaceholderTextColor": "#74777a", - "sapField_BorderColor": "#89919a", - "sapField_HelpBackground": "#fff", - "sapField_BorderWidth": ".0625rem", - "sapField_BorderCornerRadius": ".125rem", - "sapField_Hover_Background": "#fff", - "sapField_Hover_BorderColor": "#0854a0", - "sapField_Hover_HelpBackground": "#ebf5fe", - "sapField_Active_BorderColor": "#0854a0", - "sapField_Focus_Background": "#fff", - "sapField_Focus_BorderColor": "#89919a", - "sapField_Focus_HelpBackground": "#fff", - "sapField_ReadOnly_Background": "rgba(242,242,242,0.5)", - "sapField_ReadOnly_BorderColor": "#89919a", - "sapField_ReadOnly_HelpBackground": "rgba(242,242,242,0.5)", - "sapField_RequiredColor": "#ce3b3b", - "sapField_InvalidColor": "#bb0000", - "sapField_InvalidBackground": "#fff", - "sapField_WarningColor": "#e9730c", - "sapField_WarningBackground": "#fff", - "sapField_SuccessColor": "#107e3e", - "sapField_SuccessBackground": "#fff", - "sapField_InformationColor": "#0a6ed1", - "sapField_InformationBackground": "#fff", - "sapGroup_TitleBackground": "transparent", - "sapGroup_TitleBorderColor": "#d9d9d9", - "sapGroup_TitleTextColor": "#32363a", - "sapGroup_ContentBackground": "#fff", - "sapGroup_ContentBorderColor": "#d9d9d9", - "sapGroup_BorderWidth": ".0625rem", - "sapGroup_BorderCornerRadius": "0", - "sapGroup_FooterBackground": "transparent", - "sapToolbar_Background": "transparent", - "sapToolbar_SeparatorColor": "#d9d9d9", - "sapList_HeaderBackground": "#f2f2f2", - "sapList_HeaderBorderColor": "#e4e4e4", - "sapList_HeaderTextColor": "#32363a", - "sapList_BorderColor": "#e4e4e4", - "sapList_TextColor": "#32363a", - "sapList_Active_TextColor": "#fff", - "sapList_BorderWidth": ".0625rem", - "sapList_Active_Background": "#0854a0", - "sapList_SelectionBackgroundColor": "#e5f0fa", - "sapList_SelectionBorderColor": "#0854a0", - "sapList_Hover_SelectionBackground": "#d8e9f8", - "sapList_Background": "#fff", - "sapList_Hover_Background": "#f5f5f5", - "sapList_GroupHeaderBackground": "#fff", - "sapList_GroupHeaderBorderColor": "#d8d8d8", - "sapList_GroupHeaderTextColor": "#32363a", - "sapList_FooterBackground": "#fafafa", - "sapList_FooterTextColor": "#32363a", - "sapList_TableGroupHeaderBackground": "#efefef", - "sapList_TableGroupHeaderBorderColor": "#d8d8d8", - "sapList_TableGroupHeaderTextColor": "#32363a", - "sapList_TableFooterBorder": "#d8d8d8", - "sapList_TableFixedBorderColor": "#d8d8d8", - "sapScrollBar_FaceColor": "#949494", - "sapScrollBar_TrackColor": "#fff", - "sapScrollBar_BorderColor": "#949494", - "sapScrollBar_SymbolColor": "#0854a0", - "sapScrollBar_Dimension": ".75rem", - "sapScrollBar_Hover_FaceColor": "#8c8c8c", - "sapPageHeader_Background": "#fff", - "sapPageHeader_BorderColor": "#d9d9d9", - "sapPageHeader_TextColor": "#32363a", - "sapPageFooter_Background": "#fff", - "sapPageFooter_BorderColor": "#d9d9d9", - "sapPageFooter_TextColor": "#32363a", - "sapInfobar_Background": "#0f828f", - "sapInfobar_Hover_Background": "#0e7581", - "sapInfobar_Active_Background": "#0a545c", - "sapObjectHeader_Background": "#fff", - "sapObjectHeader_BorderColor": "#d9d9d9", - "sapBlockLayer_Background": "#000", - "sapTile_Background": "#fff", - "sapTile_Hover_Background": "#f5f5f5", - "sapTile_Active_Background": "#f5f5f5", - "sapTile_BorderColor": "transparent", - "sapTile_TitleTextColor": "#32363a", - "sapTile_TextColor": "#6a6d70", - "sapTile_IconColor": "#5a7da0", - "sapAccentColor1": "#d08014", - "sapAccentColor2": "#d04343", - "sapAccentColor3": "#db1f77", - "sapAccentColor4": "#c0399f", - "sapAccentColor5": "#6367de", - "sapAccentColor6": "#286eb4", - "sapAccentColor7": "#0f828f", - "sapAccentColor8": "#7ca10c", - "sapAccentColor9": "#925ace", - "sapAccentColor10": "#647987", - "sapLegendColor1": "#d58215", - "sapLegendColor2": "#dc5b5b", - "sapLegendColor3": "#db1f77", - "sapLegendColor4": "#9b3b3b", - "sapLegendColor5": "#cf5db3", - "sapLegendColor6": "#478fd6", - "sapLegendColor7": "#1193a2", - "sapLegendColor8": "#8b9668", - "sapLegendColor9": "#6c8298", - "sapLegendColor10": "#892971", - "sapLegendColor11": "#725a3a", - "sapLegendColor12": "#bb2f2f", - "sapLegendColor13": "#bc1b66", - "sapLegendColor14": "#8b714f", - "sapLegendColor15": "#606190", - "sapLegendColor16": "#597da1", - "sapLegendColor17": "#49797e", - "sapLegendColor18": "#687a33", - "sapLegendColor19": "#295989", - "sapLegendColor20": "#5154bd", - "sapChart_OrderedColor_1": "#5899da", - "sapChart_OrderedColor_2": "#e8743b", - "sapChart_OrderedColor_3": "#19a979", - "sapChart_OrderedColor_4": "#ed4a7b", - "sapChart_OrderedColor_5": "#945ecf", - "sapChart_OrderedColor_6": "#13a4b4", - "sapChart_OrderedColor_7": "#525df4", - "sapChart_OrderedColor_8": "#bf399e", - "sapChart_OrderedColor_9": "#6c8893", - "sapChart_OrderedColor_10": "#ee6868", - "sapChart_OrderedColor_11": "#2f6497", - "sapChart_Bad": "#dc0d0e", - "sapChart_Critical": "#de890d", - "sapChart_Good": "#3fa45b", - "sapChart_Neutral": "#848f94", - "sapChart_Sequence_1": "#5899da", - "sapChart_Sequence_2": "#e8743b", - "sapChart_Sequence_3": "#19a979", - "sapChart_Sequence_4": "#ed4a7b", - "sapChart_Sequence_5": "#945ecf", - "sapChart_Sequence_6": "#13a4b4", - "sapChart_Sequence_7": "#525df4", - "sapChart_Sequence_8": "#bf399e", - "sapChart_Sequence_9": "#6c8893", - "sapChart_Sequence_10": "#ee6868", - "sapChart_Sequence_11": "#2f6497", - "sapChart_Sequence_Neutral": "#848f94", - "sapFontUrl_SAP-icons_ttf": "url('../../../Base/baseLib/sap_fiori_3/fonts/SAP-icons.ttf')", - "sapFontUrl_SAP-icons_woff": "url('../../../Base/baseLib/sap_fiori_3/fonts/SAP-icons.woff')", - "sapFontUrl_SAP-icons_woff2": "url('../../../Base/baseLib/sap_fiori_3/fonts/SAP-icons.woff2')", - "sapFontUrl_72_Regular_woff2": "url('../../../Base/baseLib/sap_base_fiori/fonts/72-Regular.woff2')", - "sapFontUrl_72_Regular_woff": "url('../../../Base/baseLib/sap_base_fiori/fonts/72-Regular.woff')", - "sapFontUrl_72_Bold_woff2": "url('../../../Base/baseLib/sap_base_fiori/fonts/72-Bold.woff2')", - "sapFontUrl_72_Bold_woff": "url('../../../Base/baseLib/sap_base_fiori/fonts/72-Bold.woff')", - "sapFontUrl_72_Regular_full_woff2": "url('../../../Base/baseLib/sap_base_fiori/fonts/72-Regular-full.woff2')", - "sapFontUrl_72_Regular_full_woff": "url('../../../Base/baseLib/sap_base_fiori/fonts/72-Regular-full.woff')", - "sapFontUrl_72_Bold_full_woff2": "url('../../../Base/baseLib/sap_base_fiori/fonts/72-Bold-full.woff2')", - "sapFontUrl_72_Bold_full_woff": "url('../../../Base/baseLib/sap_base_fiori/fonts/72-Bold-full.woff')" - } -} diff --git a/packages/base/src/Device/Support.ts b/packages/base/src/Device/Support.ts index a878ba24b09..f89364cabaf 100644 --- a/packages/base/src/Device/Support.ts +++ b/packages/base/src/Device/Support.ts @@ -1,4 +1,4 @@ -import { supportTouch } from '@ui5/webcomponents-core/dist/sap/ui/Device'; +import { supportTouch } from '@ui5/webcomponents-base/dist/Device'; import '@ui5/webcomponents-react-base/third-party/modernizr'; declare const Modernizr: { diff --git a/packages/base/src/Device/index.ts b/packages/base/src/Device/index.ts index 7ee0d74553e..83b909c3410 100644 --- a/packages/base/src/Device/index.ts +++ b/packages/base/src/Device/index.ts @@ -1,4 +1,4 @@ -import { getBrowser, getOS, getSystem } from '@ui5/webcomponents-core/dist/sap/ui/Device'; +import { getBrowser, getOS, getSystem } from '@ui5/webcomponents-base/dist/Device'; import { EventRegistry } from './EventRegistry'; import { Media } from './Media'; import { Orientation } from './Orientation'; diff --git a/packages/base/src/styling/CssSizeVariables.ts b/packages/base/src/styling/CssSizeVariables.ts index ddf595c82e3..38baaed142a 100644 --- a/packages/base/src/styling/CssSizeVariables.ts +++ b/packages/base/src/styling/CssSizeVariables.ts @@ -41,32 +41,6 @@ export const cssVariablesStyles = ` --${CssSizeVariablesNames.sapWcrAnalyticalTableTreePaddingLevel1}:1.5rem; --${CssSizeVariablesNames.sapWcrAnalyticalTableTreePaddingLevel2}:2.25rem; --${CssSizeVariablesNames.sapWcrAnalyticalTableTreePaddingLevel3}:2.75rem; - - // TODO Remove those mappers after Web Components Update rc.6 - --sapFontHeaderFamily:var(--sapUiFontFamily); - --sapFontSmallSize:var(--sapMFontSmallSize); - --sapFontLargeSize:var(--sapMFontLargeSize); - --sapFontHeader1Size:var(--sapMFontHeader1Size); - --sapFontHeader2Size:var(--sapMFontHeader2Size); - --sapFontHeader3Size:var(--sapMFontHeader3Size); - --sapFontHeader4Size:var(--sapMFontHeader4Size); - --sapFontHeader5Size:var(--sapMFontHeader5Size); - --sapFontHeader6Size:var(--sapMFontHeader6Size); - --sapContent_Shadow0:var(--sapUiShadowLevel0); - --sapContent_Shadow1:var(--sapUiShadowLevel1); - --sapContent_Shadow2:var(--sapUiShadowLevel2); - --sapContent_Shadow3:var(--sapUiShadowLevel3); - --sapElement_BorderCornerRadius:0.25rem; - --sapLink_Visited_Color:var(--sapUiLinkVisited); - --sapLink_Hover_Color:var(--sapUiLinkHover); - --sapLink_InvertedColor:var(--sapUiLinkInverted); - --sapLink_Active_Color:var(--sapUiLinkActive); - --sapButton_Selected_Background:var(--sapUiSegmentedButtonSelectedBackground); - --sapButton_Selected_TextColor:var(--sapUiSegmentedButtonSelectedTextColor); - --sapButton_Selected_BorderColor:var(--sapUiSegmentedButtonSelectedHoverBorderColor); - --sapContent_ContrastIconColor:var(--sapUiContentContrastIconColor); - --sapButton_Active_Background:var(--sapUiSegmentedButtonActiveBackground); - --sapButton_Active_TextColor:var(--sapUiButtonActiveColor); } diff --git a/packages/base/src/styling/ThemingParameters.ts b/packages/base/src/styling/ThemingParameters.ts index 52f67a5ea0d..0e8e3bcbcd7 100644 --- a/packages/base/src/styling/ThemingParameters.ts +++ b/packages/base/src/styling/ThemingParameters.ts @@ -13,6 +13,8 @@ export const ThemingParameters = { sapShellColor: 'var(--sapShellColor)', sapBackgroundColor: 'var(--sapBackgroundColor)', sapFontFamily: 'var(--sapFontFamily)', + sapFontLightFamily: 'var(--sapFontLightFamily)', + sapFontBoldFamily: 'var(--sapFontBoldFamily)', sapFontHeaderFamily: 'var(--sapFontHeaderFamily)', sapFontSize: 'var(--sapFontSize)', sapFontSmallSize: 'var(--sapFontSmallSize)', @@ -71,6 +73,9 @@ export const ThemingParameters = { sapIndicationColor_3: 'var(--sapIndicationColor_3)', sapIndicationColor_4: 'var(--sapIndicationColor_4)', sapIndicationColor_5: 'var(--sapIndicationColor_5)', + sapIndicationColor_6: 'var(--sapIndicationColor_6)', + sapIndicationColor_7: 'var(--sapIndicationColor_7)', + sapIndicationColor_8: 'var(--sapIndicationColor_8)', sapElement_LineHeight: 'var(--sapElement_LineHeight)', sapElement_Height: 'var(--sapElement_Height)', sapElement_BorderWidth: 'var(--sapElement_BorderWidth)', @@ -114,7 +119,21 @@ export const ThemingParameters = { sapContent_ForegroundBorderColor: 'var(--sapContent_ForegroundBorderColor)', sapContent_ForegroundTextColor: 'var(--sapContent_ForegroundTextColor)', sapContent_BadgeBackground: 'var(--sapContent_BadgeBackground)', + sapContent_BadgeTextColor: 'var(--sapContent_BadgeTextColor)', + sapContent_Placeholderloading_Background: 'var(--sapContent_Placeholderloading_Background)', + sapContent_Placeholderloading_Gradient: 'var(--sapContent_Placeholderloading_Gradient)', sapContent_DragAndDropActiveColor: 'var(--sapContent_DragAndDropActiveColor)', + sapContent_Selected_Background: 'var(--sapContent_Selected_Background)', + sapContent_Selected_TextColor: 'var(--sapContent_Selected_TextColor)', + sapContent_Selected_Hover_Background: 'var(--sapContent_Selected_Hover_Background)', + sapContent_Illustrative_Color1: 'var(--sapContent_Illustrative_Color1)', + sapContent_Illustrative_Color2: 'var(--sapContent_Illustrative_Color2)', + sapContent_Illustrative_Color3: 'var(--sapContent_Illustrative_Color3)', + sapContent_Illustrative_Color4: 'var(--sapContent_Illustrative_Color4)', + sapContent_Illustrative_Color5: 'var(--sapContent_Illustrative_Color5)', + sapContent_Illustrative_Color6: 'var(--sapContent_Illustrative_Color6)', + sapContent_Illustrative_Color7: 'var(--sapContent_Illustrative_Color7)', + sapContent_Illustrative_Color8: 'var(--sapContent_Illustrative_Color8)', sapShell_Background: 'var(--sapShell_Background)', sapShell_BackgroundImage: 'var(--sapShell_BackgroundImage)', sapShell_BackgroundGradient: 'var(--sapShell_BackgroundGradient)', @@ -166,6 +185,11 @@ export const ThemingParameters = { sapButton_Accept_Active_Background: 'var(--sapButton_Accept_Active_Background)', sapButton_Accept_Active_BorderColor: 'var(--sapButton_Accept_Active_BorderColor)', sapButton_Accept_TextColor: 'var(--sapButton_Accept_TextColor)', + sapButton_Accept_Selected_Background: 'var(--sapButton_Accept_Selected_Background)', + sapButton_Accept_Selected_BorderColor: 'var(--sapButton_Accept_Selected_BorderColor)', + sapButton_Accept_Selected_TextColor: 'var(--sapButton_Accept_Selected_TextColor)', + sapButton_Accept_Selected_Hover_Background: 'var(--sapButton_Accept_Selected_Hover_Background)', + sapButton_Accept_Selected_Hover_BorderColor: 'var(--sapButton_Accept_Selected_Hover_BorderColor)', sapButton_Reject_Background: 'var(--sapButton_Reject_Background)', sapButton_Reject_BorderColor: 'var(--sapButton_Reject_BorderColor)', sapButton_Reject_Hover_Background: 'var(--sapButton_Reject_Hover_Background)', @@ -174,6 +198,11 @@ export const ThemingParameters = { sapButton_Reject_Active_Background: 'var(--sapButton_Reject_Active_Background)', sapButton_Reject_Active_BorderColor: 'var(--sapButton_Reject_Active_BorderColor)', sapButton_Reject_TextColor: 'var(--sapButton_Reject_TextColor)', + sapButton_Reject_Selected_Background: 'var(--sapButton_Reject_Selected_Background)', + sapButton_Reject_Selected_BorderColor: 'var(--sapButton_Reject_Selected_BorderColor)', + sapButton_Reject_Selected_TextColor: 'var(--sapButton_Reject_Selected_TextColor)', + sapButton_Reject_Selected_Hover_Background: 'var(--sapButton_Reject_Selected_Hover_Background)', + sapButton_Reject_Selected_Hover_BorderColor: 'var(--sapButton_Reject_Selected_Hover_BorderColor)', sapButton_Lite_Background: 'var(--sapButton_Lite_Background)', sapButton_Lite_BorderColor: 'var(--sapButton_Lite_BorderColor)', sapButton_Lite_TextColor: 'var(--sapButton_Lite_TextColor)', @@ -187,6 +216,57 @@ export const ThemingParameters = { sapButton_Selected_TextColor: 'var(--sapButton_Selected_TextColor)', sapButton_Selected_Hover_Background: 'var(--sapButton_Selected_Hover_Background)', sapButton_Selected_Hover_BorderColor: 'var(--sapButton_Selected_Hover_BorderColor)', + sapButton_Attention_Background: 'var(--sapButton_Attention_Background)', + sapButton_Attention_BorderColor: 'var(--sapButton_Attention_BorderColor)', + sapButton_Attention_TextColor: 'var(--sapButton_Attention_TextColor)', + sapButton_Attention_Hover_Background: 'var(--sapButton_Attention_Hover_Background)', + sapButton_Attention_Hover_BorderColor: 'var(--sapButton_Attention_Hover_BorderColor)', + sapButton_Attention_Hover_TextColor: 'var(--sapButton_Attention_Hover_TextColor)', + sapButton_Attention_Active_Background: 'var(--sapButton_Attention_Active_Background)', + sapButton_Attention_Active_BorderColor: 'var(--sapButton_Attention_Active_BorderColor)', + sapButton_Attention_Selected_Background: 'var(--sapButton_Attention_Selected_Background)', + sapButton_Attention_Selected_BorderColor: 'var(--sapButton_Attention_Selected_BorderColor)', + sapButton_Attention_Selected_TextColor: 'var(--sapButton_Attention_Selected_TextColor)', + sapButton_Attention_Selected_Hover_Background: 'var(--sapButton_Attention_Selected_Hover_Background)', + sapButton_Attention_Selected_Hover_BorderColor: 'var(--sapButton_Attention_Selected_Hover_BorderColor)', + sapButton_Negative_Background: 'var(--sapButton_Negative_Background)', + sapButton_Negative_BorderColor: 'var(--sapButton_Negative_BorderColor)', + sapButton_Negative_TextColor: 'var(--sapButton_Negative_TextColor)', + sapButton_Negative_Hover_Background: 'var(--sapButton_Negative_Hover_Background)', + sapButton_Negative_Hover_BorderColor: 'var(--sapButton_Negative_Hover_BorderColor)', + sapButton_Negative_Hover_TextColor: 'var(--sapButton_Negative_Hover_TextColor)', + sapButton_Negative_Active_Background: 'var(--sapButton_Negative_Active_Background)', + sapButton_Negative_Active_BorderColor: 'var(--sapButton_Negative_Active_BorderColor)', + sapButton_Critical_Background: 'var(--sapButton_Critical_Background)', + sapButton_Critical_BorderColor: 'var(--sapButton_Critical_BorderColor)', + sapButton_Critical_TextColor: 'var(--sapButton_Critical_TextColor)', + sapButton_Critical_Hover_Background: 'var(--sapButton_Critical_Hover_Background)', + sapButton_Critical_Hover_BorderColor: 'var(--sapButton_Critical_Hover_BorderColor)', + sapButton_Critical_Hover_TextColor: 'var(--sapButton_Critical_Hover_TextColor)', + sapButton_Critical_Active_Background: 'var(--sapButton_Critical_Active_Background)', + sapButton_Critical_Active_BorderColor: 'var(--sapButton_Critical_Active_BorderColor)', + sapButton_Success_Background: 'var(--sapButton_Success_Background)', + sapButton_Success_BorderColor: 'var(--sapButton_Success_BorderColor)', + sapButton_Success_TextColor: 'var(--sapButton_Success_TextColor)', + sapButton_Success_Hover_Background: 'var(--sapButton_Success_Hover_Background)', + sapButton_Success_Hover_BorderColor: 'var(--sapButton_Success_Hover_BorderColor)', + sapButton_Success_Hover_TextColor: 'var(--sapButton_Success_Hover_TextColor)', + sapButton_Success_Active_Background: 'var(--sapButton_Success_Active_Background)', + sapButton_Success_Active_BorderColor: 'var(--sapButton_Success_Active_BorderColor)', + sapButton_Neutral_Background: 'var(--sapButton_Neutral_Background)', + sapButton_Neutral_BorderColor: 'var(--sapButton_Neutral_BorderColor)', + sapButton_Neutral_TextColor: 'var(--sapButton_Neutral_TextColor)', + sapButton_Neutral_Hover_Background: 'var(--sapButton_Neutral_Hover_Background)', + sapButton_Neutral_Hover_BorderColor: 'var(--sapButton_Neutral_Hover_BorderColor)', + sapButton_Neutral_Hover_TextColor: 'var(--sapButton_Neutral_Hover_TextColor)', + sapButton_Neutral_Active_Background: 'var(--sapButton_Neutral_Active_Background)', + sapButton_Neutral_Active_BorderColor: 'var(--sapButton_Neutral_Active_BorderColor)', + sapButton_Track_Selected_Background: 'var(--sapButton_Track_Selected_Background)', + sapButton_Track_Selected_TextColor: 'var(--sapButton_Track_Selected_TextColor)', + sapButton_Track_Background: 'var(--sapButton_Track_Background)', + sapButton_Track_TextColor: 'var(--sapButton_Track_TextColor)', + sapButton_TokenBackground: 'var(--sapButton_TokenBackground)', + sapButton_TokenBorderColor: 'var(--sapButton_TokenBorderColor)', sapField_Background: 'var(--sapField_Background)', sapField_TextColor: 'var(--sapField_TextColor)', sapField_PlaceholderTextColor: 'var(--sapField_PlaceholderTextColor)', @@ -236,6 +316,7 @@ export const ThemingParameters = { sapList_Hover_SelectionBackground: 'var(--sapList_Hover_SelectionBackground)', sapList_Background: 'var(--sapList_Background)', sapList_Hover_Background: 'var(--sapList_Hover_Background)', + sapList_AlternatingBackground: 'var(--sapList_AlternatingBackground)', sapList_GroupHeaderBackground: 'var(--sapList_GroupHeaderBackground)', sapList_GroupHeaderBorderColor: 'var(--sapList_GroupHeaderBorderColor)', sapList_GroupHeaderTextColor: 'var(--sapList_GroupHeaderTextColor)', @@ -271,6 +352,7 @@ export const ThemingParameters = { sapTile_TitleTextColor: 'var(--sapTile_TitleTextColor)', sapTile_TextColor: 'var(--sapTile_TextColor)', sapTile_IconColor: 'var(--sapTile_IconColor)', + sapTile_SeparatorColor: 'var(--sapTile_SeparatorColor)', sapAccentColor1: 'var(--sapAccentColor1)', sapAccentColor2: 'var(--sapAccentColor2)', sapAccentColor3: 'var(--sapAccentColor3)', @@ -281,6 +363,9 @@ export const ThemingParameters = { sapAccentColor8: 'var(--sapAccentColor8)', sapAccentColor9: 'var(--sapAccentColor9)', sapAccentColor10: 'var(--sapAccentColor10)', + sapLegend_WorkingBackground: 'var(--sapLegend_WorkingBackground)', + sapLegend_NonWorkingBackground: 'var(--sapLegend_NonWorkingBackground)', + sapLegend_CurrentDateTime: 'var(--sapLegend_CurrentDateTime)', sapLegendColor1: 'var(--sapLegendColor1)', sapLegendColor2: 'var(--sapLegendColor2)', sapLegendColor3: 'var(--sapLegendColor3)', @@ -301,6 +386,26 @@ export const ThemingParameters = { sapLegendColor18: 'var(--sapLegendColor18)', sapLegendColor19: 'var(--sapLegendColor19)', sapLegendColor20: 'var(--sapLegendColor20)', + sapLegendBackgroundColor1: 'var(--sapLegendBackgroundColor1)', + sapLegendBackgroundColor2: 'var(--sapLegendBackgroundColor2)', + sapLegendBackgroundColor3: 'var(--sapLegendBackgroundColor3)', + sapLegendBackgroundColor4: 'var(--sapLegendBackgroundColor4)', + sapLegendBackgroundColor5: 'var(--sapLegendBackgroundColor5)', + sapLegendBackgroundColor6: 'var(--sapLegendBackgroundColor6)', + sapLegendBackgroundColor7: 'var(--sapLegendBackgroundColor7)', + sapLegendBackgroundColor8: 'var(--sapLegendBackgroundColor8)', + sapLegendBackgroundColor9: 'var(--sapLegendBackgroundColor9)', + sapLegendBackgroundColor10: 'var(--sapLegendBackgroundColor10)', + sapLegendBackgroundColor11: 'var(--sapLegendBackgroundColor11)', + sapLegendBackgroundColor12: 'var(--sapLegendBackgroundColor12)', + sapLegendBackgroundColor13: 'var(--sapLegendBackgroundColor13)', + sapLegendBackgroundColor14: 'var(--sapLegendBackgroundColor14)', + sapLegendBackgroundColor15: 'var(--sapLegendBackgroundColor15)', + sapLegendBackgroundColor16: 'var(--sapLegendBackgroundColor16)', + sapLegendBackgroundColor17: 'var(--sapLegendBackgroundColor17)', + sapLegendBackgroundColor18: 'var(--sapLegendBackgroundColor18)', + sapLegendBackgroundColor19: 'var(--sapLegendBackgroundColor19)', + sapLegendBackgroundColor20: 'var(--sapLegendBackgroundColor20)', sapChart_OrderedColor_1: 'var(--sapChart_OrderedColor_1)', sapChart_OrderedColor_2: 'var(--sapChart_OrderedColor_2)', sapChart_OrderedColor_3: 'var(--sapChart_OrderedColor_3)', @@ -335,8 +440,12 @@ export const ThemingParameters = { sapFontUrl_72_Regular_woff: 'var(--sapFontUrl_72_Regular_woff)', sapFontUrl_72_Bold_woff2: 'var(--sapFontUrl_72_Bold_woff2)', sapFontUrl_72_Bold_woff: 'var(--sapFontUrl_72_Bold_woff)', + sapFontUrl_72_Light_woff2: 'var(--sapFontUrl_72_Light_woff2)', + sapFontUrl_72_Light_woff: 'var(--sapFontUrl_72_Light_woff)', sapFontUrl_72_Regular_full_woff2: 'var(--sapFontUrl_72_Regular_full_woff2)', sapFontUrl_72_Regular_full_woff: 'var(--sapFontUrl_72_Regular_full_woff)', sapFontUrl_72_Bold_full_woff2: 'var(--sapFontUrl_72_Bold_full_woff2)', - sapFontUrl_72_Bold_full_woff: 'var(--sapFontUrl_72_Bold_full_woff)' + sapFontUrl_72_Bold_full_woff: 'var(--sapFontUrl_72_Bold_full_woff)', + sapFontUrl_72_Light_full_woff2: 'var(--sapFontUrl_72_Light_full_woff2)', + sapFontUrl_72_Light_full_woff: 'var(--sapFontUrl_72_Light_full_woff)' }; diff --git a/packages/main/package.json b/packages/main/package.json index dd4ba53188a..3104529074e 100644 --- a/packages/main/package.json +++ b/packages/main/package.json @@ -13,30 +13,24 @@ "author": "SAP SE (https://www.sap.com)", "license": "Apache-2.0", "sideEffects": [ - "@ui5/webcomponents-icons/dist/icons/*" + "@ui5/webcomponents-icons/dist/icons/*", + "*/ThemingSupport.js" ], "scripts": { "clean": "rimraf cjs components enums interfaces internal lib webComponents index.esm.js index.d.ts", - "generateWebComponents": "ts-node -O '{\"module\": \"commonjs\"}' -r esm ./scripts/wrapperGeneration/index.js --onlyStopForMerge", - "build": "webpack --config ./scripts/wrapperGeneration/webpack.config.js", "postbuild": "rollup -c rollup.config.js" }, "dependencies": { - "@ui5/webcomponents": "1.0.0-rc.5", - "@ui5/webcomponents-fiori": "1.0.0-rc.5", - "@ui5/webcomponents-icons": "1.0.0-rc.5", + "@ui5/webcomponents": "1.0.0-rc.6", + "@ui5/webcomponents-fiori": "1.0.0-rc.6", + "@ui5/webcomponents-icons": "1.0.0-rc.6", "@ui5/webcomponents-react-base": "^0.9.0-rc.5", "lodash.debounce": "^4.0.8", "react-content-loader": "^5.0.2", "react-jss": "10.0.4", "react-table": "7.0.0", - "react-toastify": "^5.5.0", "react-window": "^1.8.5" }, - "devDependencies": { - "diff": "^4.0.1", - "inquirer": "^7.0.0" - }, "peerDependencies": { "react": "^16.8.0", "react-dom": "^16.8.0" diff --git a/packages/main/scripts/create-library-export.js b/packages/main/scripts/create-library-export.js index 78cd7501f37..d288b18ee24 100644 --- a/packages/main/scripts/create-library-export.js +++ b/packages/main/scripts/create-library-export.js @@ -3,7 +3,7 @@ const fs = require('fs'); const PATHS = require('../../../config/paths'); const LIB_BASE_PATH = path.resolve(PATHS.packages, 'main', 'src', 'lib'); -const INTERNAL_COMPONENTS = ['withWebComponent', 'ScrollContext']; +const INTERNAL_COMPONENTS = ['withWebComponent', 'ScrollContext', 'ThemingSupport']; const allLibFiles = fs .readdirSync(LIB_BASE_PATH) diff --git a/packages/main/scripts/create-web-components-wrapper.js b/packages/main/scripts/create-web-components-wrapper.js new file mode 100644 index 00000000000..6fa36a7222e --- /dev/null +++ b/packages/main/scripts/create-web-components-wrapper.js @@ -0,0 +1,554 @@ +/* eslint-disable @typescript-eslint/no-var-requires */ +const mainWebComponentsSpec = require('@ui5/webcomponents/dist/api.json'); +const fioriWebComponentsSpec = require('@ui5/webcomponents-fiori/dist/api.json'); +const dedent = require('dedent'); +const prettier = require('prettier'); +const prettierConfig = require('../../../prettier.config'); +const path = require('path'); +const PATHS = require('../../../config/paths'); +const fs = require('fs'); + +const WEB_COMPONENTS_ROOT_DIR = path.join(PATHS.packages, 'main', 'src', 'webComponents'); + +const PRIVATE_COMPONENTS = new Set([ + 'CalendarHeader', + 'DefaultTheme', + 'DayPicker', + 'ListItem', + 'ListItemBase', + 'MessageBundleAssets', + 'MonthPicker', + 'Popup', + 'TabBase', + 'ThemePropertiesProvider', + 'YearPicker', + 'WheelSlider' +]); + +const COMPONENTS_WITHOUT_DEMOS = new Set(PRIVATE_COMPONENTS); +COMPONENTS_WITHOUT_DEMOS.add('CustomListItem'); +COMPONENTS_WITHOUT_DEMOS.add('GroupHeaderListItem'); +COMPONENTS_WITHOUT_DEMOS.add('Option'); +COMPONENTS_WITHOUT_DEMOS.add('ShellBarItem'); +COMPONENTS_WITHOUT_DEMOS.add('StandardListItem'); +COMPONENTS_WITHOUT_DEMOS.add('Tab'); +COMPONENTS_WITHOUT_DEMOS.add('TableCell'); +COMPONENTS_WITHOUT_DEMOS.add('TableColumn'); +COMPONENTS_WITHOUT_DEMOS.add('TableRow'); +COMPONENTS_WITHOUT_DEMOS.add('TabSeparator'); +COMPONENTS_WITHOUT_DEMOS.add('TimelineItem'); +COMPONENTS_WITHOUT_DEMOS.add('ProductSwitchItem'); +COMPONENTS_WITHOUT_DEMOS.add('ComboBoxItem'); +COMPONENTS_WITHOUT_DEMOS.add('MultiComboBoxItem'); +COMPONENTS_WITHOUT_DEMOS.add('SuggestionItem'); + +const componentsFromFioriPackage = new Set(fioriWebComponentsSpec.symbols.map((componentSpec) => componentSpec.module)); + +const capitalizeFirstLetter = (s) => s.charAt(0).toUpperCase() + s.slice(1); + +const getTypeScriptTypeForProperty = (property) => { + switch (property.type) { + // native ts types + case 'String': + case 'string': + return { + importStatement: null, + tsType: 'string' + }; + case 'undefined': + return { + importStatement: null, + tsType: 'unknown' + }; + case 'Integer': + case 'number': + return { + importStatement: null, + tsType: 'number' + }; + case 'boolean': + case 'Boolean': + return { + importStatement: null, + tsType: 'boolean' + }; + case 'Array': + return { + importStatement: null, + tsType: 'unknown[]' + }; + // react ts types + case 'Node[]': + case 'HTMLElement[]': + return { + tsType: 'ReactNode | ReactNode[]', + importStatement: "import { ReactNode } from 'react';" + }; + case 'HTMLElement': + return { + tsType: 'ReactNode', + importStatement: "import { ReactNode } from 'react';" + }; + // UI5 Web Component Enums + case 'AvatarBackgroundColor': + return { + importStatement: "import { AvatarBackgroundColor } from '@ui5/webcomponents-react/lib/AvatarBackgroundColor';", + tsType: 'AvatarBackgroundColor', + isEnum: true + }; + case 'AvatarFitType': + return { + importStatement: "import { AvatarFitType } from '@ui5/webcomponents-react/lib/AvatarFitType';", + tsType: 'AvatarFitType', + isEnum: true + }; + case 'AvatarShape': + return { + importStatement: "import { AvatarShape } from '@ui5/webcomponents-react/lib/AvatarShape';", + tsType: 'AvatarShape', + isEnum: true + }; + case 'AvatarSize': + return { + importStatement: "import { AvatarSize } from '@ui5/webcomponents-react/lib/AvatarSize';", + tsType: 'AvatarSize', + isEnum: true + }; + case 'BusyIndicatorSize': + return { + importStatement: "import { BusyIndicatorSize } from '@ui5/webcomponents-react/lib/BusyIndicatorSize';", + tsType: 'BusyIndicatorSize', + isEnum: true + }; + case 'ButtonDesign': + return { + importStatement: "import { ButtonDesign } from '@ui5/webcomponents-react/lib/ButtonDesign';", + tsType: 'ButtonDesign', + isEnum: true + }; + case 'CalendarType': + return { + importStatement: "import { CalendarType } from '@ui5/webcomponents-react/lib/CalendarType';", + tsType: 'CalendarType', + isEnum: true + }; + case 'CarouselArrowsPlacement': + return { + importStatement: + "import { CarouselArrowsPlacement } from '@ui5/webcomponents-react/lib/CarouselArrowsPlacement';", + tsType: 'CarouselArrowsPlacement', + isEnum: true + }; + case 'InputType': + return { + importStatement: "import { InputType } from '@ui5/webcomponents-react/lib/InputType';", + tsType: 'InputType', + isEnum: true + }; + case 'LinkDesign': + return { + importStatement: "import { LinkDesign } from '@ui5/webcomponents-react/lib/LinkDesign';", + tsType: 'LinkDesign', + isEnum: true + }; + case 'ListItemType': { + // TODO Should we use the singular ListItemType here? + return { + importStatement: "import { ListItemTypes } from '@ui5/webcomponents-react/lib/ListItemTypes';", + tsType: 'ListItemTypes', + isEnum: true + }; + } + case 'ListMode': { + return { + importStatement: "import { ListMode } from '@ui5/webcomponents-react/lib/ListMode';", + tsType: 'ListMode', + isEnum: true + }; + } + case 'ListSeparators': + return { + importStatement: "import { ListSeparators } from '@ui5/webcomponents-react/lib/ListSeparators';", + tsType: 'ListSeparators', + isEnum: true + }; + case 'MessageStripType': + return { + importStatement: "import { MessageStripType } from '@ui5/webcomponents-react/lib/MessageStripType';", + tsType: 'MessageStripType', + isEnum: true + }; + case 'PanelAccessibleRole': + return { + importStatement: "import { PanelAccessibleRoles } from '@ui5/webcomponents-react/lib/PanelAccessibleRoles';", + tsType: 'PanelAccessibleRoles', + isEnum: true + }; + case 'PopoverHorizontalAlign': + return { + importStatement: + "import { PopoverHorizontalAlign } from '@ui5/webcomponents-react/lib/PopoverHorizontalAlign';", + tsType: 'PopoverHorizontalAlign', + isEnum: true + }; + case 'PopoverPlacementType': + return { + importStatement: "import { PlacementType } from '@ui5/webcomponents-react/lib/PlacementType';", + tsType: 'PlacementType', + isEnum: true + }; + case 'PopoverVerticalAlign': + return { + importStatement: "import { PopoverVerticalAlign } from '@ui5/webcomponents-react/lib/PopoverVerticalAlign';", + tsType: 'PopoverVerticalAlign', + isEnum: true + }; + case 'SemanticColor': + return { + importStatement: "import { SemanticColor } from '@ui5/webcomponents-react/lib/SemanticColor';", + tsType: 'SemanticColor', + isEnum: true + }; + case 'TabLayout': + return { + importStatement: "import { TabLayout } from '@ui5/webcomponents-react/lib/TabLayout';", + tsType: 'TabLayout', + isEnum: true + }; + case 'TitleLevel': + return { + importStatement: "import { TitleLevel } from '@ui5/webcomponents-react/lib/TitleLevel';", + tsType: 'TitleLevel', + isEnum: true + }; + case 'ToastPlacement': + return { + importStatement: "import { ToastPlacement } from '@ui5/webcomponents-react/lib/ToastPlacement';", + tsType: 'ToastPlacement', + isEnum: true + }; + case 'ValueState': + return { + importStatement: "import { ValueState } from '@ui5/webcomponents-react/lib/ValueState';", + tsType: 'ValueState', + isEnum: true + }; + } +}; + +const getEventParameters = (parameters) => { + const resolvedEventParameters = parameters.map((property) => { + return { + ...property, + ...getTypeScriptTypeForProperty(property) + }; + }); + + const importStatements = []; + + const detailPayload = resolvedEventParameters.map((parameter) => { + if (parameter.importStatement) { + importStatements.push(parameter.importStatement); + } + return `${parameter.name}: ${parameter.tsType}`; + }); + + return { + tsType: `(event: CustomEvent<{${detailPayload.join('; ')}}>) => void`, + importStatements + }; +}; + +const createWebComponentWrapper = (name, types, importStatements, defaultProps) => { + return prettier.format( + ` + import { withWebComponent } from '@ui5/webcomponents-react/lib/withWebComponent'; + import UI5${name} from '@ui5/webcomponents${componentsFromFioriPackage.has(name) ? '-fiori' : ''}/dist/${name}'; + import React, { FC } from 'react'; + import { WithWebComponentPropTypes } from '../../internal/withWebComponent'; + ${importStatements.join('\n')} + + export interface ${name}PropTypes extends WithWebComponentPropTypes { + ${types.join('\n')} + } + + /** + * import { ${name} } from '@ui5/webcomponents-react/lib/${name}'; + *
+ * UI5 Web Components Playground + */ + const ${name}: FC<${name}PropTypes> = withWebComponent<${name}PropTypes>(UI5${name}); + + ${name}.displayName = '${name}'; + + ${name}.defaultProps = { + ${defaultProps.join(',\n')} + }; + + export { ${name} }; + + `, + prettierConfig + ); +}; + +const createWebComponentTest = (name) => { + return prettier.format( + ` + import { mount } from 'enzyme'; + import React from 'react'; + import { ${name} } from '@ui5/webcomponents-react/lib/${name}'; + + describe('${name}', () => { + test('Basic Test (generated)', () => { + const wrapper = mount(<${name} />); + expect(wrapper.render()).toMatchSnapshot(); + }); + }); + + `, + prettierConfig + ); +}; + +const createWebComponentDemo = (componentSpec, componentProps) => { + const componentName = componentSpec.module; + + const storybookImports = []; + const storybookKnobImports = new Set(); + const enumImports = []; + const storybookProps = []; + + const componentFiresEvents = componentSpec.events && componentSpec.events.length > 0; + if (componentFiresEvents) { + storybookImports.push("import { action } from '@storybook/addon-actions';"); + } + + const childrenProp = componentProps.find((prop) => prop.name === 'children'); + + const additionalComponentDocs = componentSpec.hasOwnProperty('appenddocs') ? componentSpec.appenddocs.split(' ') : []; + const additionalComponentImports = additionalComponentDocs.map( + (component) => `import { ${component} } from '@ui5/webcomponents-react/lib/${component}';` + ); + let additionalComponentsParameters = ''; + if (additionalComponentDocs.length > 0) { + additionalComponentsParameters = `, + parameters: { + subcomponents: { ${additionalComponentDocs.join(', ')} } + }`; + } + + componentProps + .filter((prop) => prop.name !== 'children') + .forEach((prop) => { + if (prop.importStatement) { + enumImports.push(prop.importStatement); + } + let storybookKnob = `${prop.name}={`; + if (prop.isEnum) { + storybookKnobImports.add('select'); + storybookKnob += `select('${prop.name}', ${prop.tsType}, ${prop.tsType}.${prop.defaultValue.replace( + /['"]/g, + '' + )})`; + } else if (prop.tsType === 'number') { + storybookKnobImports.add('number'); + storybookKnob += `number('${prop.name}', ${prop.defaultValue})`; + } else if (prop.tsType === 'boolean') { + storybookKnobImports.add('boolean'); + storybookKnob += `boolean('${prop.name}', ${prop.defaultValue === 'true'})`; + } else if (prop.tsType === 'string') { + storybookKnobImports.add('text'); + storybookKnob += `text('${prop.name}', ${prop.defaultValue})`; + } else { + console.warn(`Warning: Unknown Type for demo ${prop.name}: ${prop.tsType}`); + storybookKnob += 'null'; + } + + storybookKnob += '}'; + storybookProps.push(storybookKnob); + }); + + const eventProps = (componentSpec.events || []).map( + (event) => `on${capitalizeFirstLetter(event.name)}={action('on${capitalizeFirstLetter(event.name)}')}` + ); + + const componentBody = childrenProp ? `>Some Content` : ' />'; + + return prettier.format( + `import React from 'react'; + import { ${componentName} } from '@ui5/webcomponents-react/lib/${componentName}'; + ${storybookImports.join('\n')} + import { ${[...storybookKnobImports].join(', ')} } from '@storybook/addon-knobs'; + ${enumImports.join('\n')}; + ${additionalComponentImports.join('\n')} + + export default { + title: 'UI5 Web Components / ${componentName}', + component: ${componentName}${additionalComponentsParameters} + }; + + export const generatedDefaultStory = () => ( + <${componentName} + ${storybookProps.join('\n')} + ${eventProps.join('\n')} + ${componentBody} + ); + + generatedDefaultStory.story = { + name: 'Generated default story' + }; + + `, + prettierConfig + ); +}; + +const allWebComponents = [ + ...mainWebComponentsSpec.symbols.filter((spec) => !spec.module.startsWith('types/')), + ...fioriWebComponentsSpec.symbols.filter((spec) => !spec.module.startsWith('types/')) +]; + +const assignComponentPropertiesToMaps = (componentSpec, { properties, slots, events }) => { + (componentSpec.properties || []).forEach((prop) => { + if (!properties.has(prop.name)) { + properties.set(prop.name, prop); + } + }); + (componentSpec.slots || []).forEach((slot) => { + if (!slots.has(slot.name)) { + slots.set(slot.name, slot); + } + }); + (componentSpec.events || []).forEach((event) => { + if (!events.has(event.name)) { + events.set(event.name, event); + } + }); +}; + +const recursivePropertyResolver = (componentSpec, { properties, slots, events }) => { + assignComponentPropertiesToMaps(componentSpec, { properties, slots, events }); + if ( + componentSpec.extends === 'UI5Element' || + componentSpec.extends === 'sap.ui.webcomponents.base.UI5Element' || + componentSpec.extends === 'TabBase' // not longer existing but wrong docs, treat as UI5 Element + ) { + return { properties, slots, events }; + } + + const parentComponent = allWebComponents.find((c) => c.module === componentSpec.extends); + if (parentComponent) { + return recursivePropertyResolver(parentComponent, { properties, slots, events }); + } + throw new Error('Unknown Parent Component!'); +}; + +const resolveInheritedAttributes = (componentSpec) => { + if (componentSpec.extends === 'UI5Element' || componentSpec.extends === 'sap.ui.webcomponents.base.UI5Element') { + // no inheritance, just return the component + return componentSpec; + } + + const properties = new Map(); + const slots = new Map(); + const events = new Map(); + recursivePropertyResolver(componentSpec, { properties, slots, events }); + + componentSpec.properties = Array.from(properties.values()); + componentSpec.slots = Array.from(slots.values()); + componentSpec.events = Array.from(events.values()); + + return componentSpec; +}; + +const resolvedWebComponents = allWebComponents + .filter((spec) => spec.visibility === 'public') + .filter((spec) => !PRIVATE_COMPONENTS.has(spec.module)) + .map(resolveInheritedAttributes); + +resolvedWebComponents.forEach((componentSpec) => { + const propTypes = []; + const importStatements = []; + const defaultProps = []; + const allComponentProperties = [...(componentSpec.properties || []), ...(componentSpec.slots || [])] + .filter((prop) => prop.visibility === 'public' && prop.readonly !== 'true' && prop.static !== true) + .map((property) => { + const tsType = getTypeScriptTypeForProperty(property); + if (tsType.importStatement) { + importStatements.push(tsType.importStatement); + } + + if (property.name === 'default') { + property.name = 'children'; + } + + propTypes.push(dedent` + /** + * ${property.description} + */ + ${property.name}?: ${tsType.tsType}; + `); + + if (property.hasOwnProperty('defaultValue')) { + if (tsType.tsType === 'boolean') { + defaultProps.push(`${property.name}: ${property.defaultValue === 'true'}`); + } else if (tsType.isEnum === true) { + defaultProps.push(`${property.name}: ${tsType.tsType}.${property.defaultValue.replace(/['"]/g, '')}`); + } else { + defaultProps.push(`${property.name}: ${property.defaultValue}`); + } + } + + return { + ...property, + ...tsType + }; + }); + + (componentSpec.events || []) + .filter((eventSpec) => eventSpec.visibility === 'public') + .forEach((eventSpec) => { + const eventParameters = getEventParameters(eventSpec.parameters || []); + importStatements.push(...eventParameters.importStatements); + propTypes.push(dedent` + /** + * ${eventSpec.description} + */ + on${capitalizeFirstLetter(eventSpec.name)}?: ${eventParameters.tsType}; + `); + }); + + const uniqueAdditionalImports = [...new Set(importStatements)]; + + const webComponentWrapper = createWebComponentWrapper( + componentSpec.module, + propTypes, + uniqueAdditionalImports, + defaultProps + ); + + // check if folder exists and create it if necessary + const webComponentFolderPath = path.join(WEB_COMPONENTS_ROOT_DIR, componentSpec.module); + if (!fs.existsSync(webComponentFolderPath)) { + fs.mkdirSync(webComponentFolderPath); + } + if (!fs.existsSync(path.join(webComponentFolderPath, 'index.tsx'))) { + fs.writeFileSync(path.join(webComponentFolderPath, 'index.tsx'), webComponentWrapper); + } + + // create test + if (!fs.existsSync(path.join(webComponentFolderPath, `${componentSpec.module}.test.tsx`))) { + const webComponentTest = createWebComponentTest(componentSpec.module); + fs.writeFileSync(path.join(webComponentFolderPath, `${componentSpec.module}.test.tsx`), webComponentTest); + } + + // create demo + if ( + !fs.existsSync(path.join(webComponentFolderPath, `${componentSpec.module}.stories.tsx`)) && + !COMPONENTS_WITHOUT_DEMOS.has(componentSpec.module) + ) { + const webComponentDemo = createWebComponentDemo(componentSpec, allComponentProperties); + fs.writeFileSync(path.join(webComponentFolderPath, `${componentSpec.module}.stories.tsx`), webComponentDemo); + } +}); diff --git a/packages/main/scripts/wrapperGeneration/diff.js b/packages/main/scripts/wrapperGeneration/diff.js deleted file mode 100644 index 674d0f0641d..00000000000 --- a/packages/main/scripts/wrapperGeneration/diff.js +++ /dev/null @@ -1,60 +0,0 @@ -import { diffWordsWithSpace } from 'diff'; - -const colors = { - 'diff added': 32, - 'diff removed': 31 -}; - -function color(type, str) { - return '\u001b[' + colors[type] + 'm' + str + '\u001b[0m'; -} - -function pad(str, len) { - str = String(str); - return Array(len - str.length + 1).join(' ') + str; -} - -function colorLines(name, str) { - return str - .split('\n') - .map(function(str) { - return color(name, str); - }) - .join('\n'); -} - -function errorDiff(actual, expected) { - return diffWordsWithSpace(actual, expected) - .map(function(str) { - if (str.added) { - return colorLines('diff added', str.value); - } - if (str.removed) { - return colorLines('diff removed', str.value); - } - return str.value; - }) - .join(''); -} - -export function generateDiff(expected, actual) { - let msg = errorDiff(actual, expected); - - // linenos - const lines = msg.split('\n'); - if (lines.length > 4) { - const width = String(lines.length).length; - msg = lines - .map(function(str, i) { - return pad(++i, width) + ' |' + ' ' + str; - }) - .join('\n'); - } - - // legend - msg = '\n' + color('diff removed', 'New') + ' ' + color('diff added', 'Existing Wrapper') + '\n\n' + msg + '\n'; - - // indent - msg = msg.replace(/^/gm, ' '); - return msg; -} diff --git a/packages/main/scripts/wrapperGeneration/generateTypingStatements.js b/packages/main/scripts/wrapperGeneration/generateTypingStatements.js deleted file mode 100644 index 0c1ec0be3c2..00000000000 --- a/packages/main/scripts/wrapperGeneration/generateTypingStatements.js +++ /dev/null @@ -1,96 +0,0 @@ -const path = require('path'); - -const fiori3Enums = path.resolve(__dirname, '..', '..', 'src', 'enums'); - -const f4rEnums = { - ValueState: require(path.resolve(fiori3Enums, 'ValueState.ts')).ValueState, - ButtonDesign: require(path.resolve(fiori3Enums, 'ButtonDesign.ts')).ButtonDesign, - MessageStripType: require(path.resolve(fiori3Enums, 'MessageStripType.ts')).MessageStripType, - CalendarType: require(path.resolve(fiori3Enums, 'CalendarType.ts')).CalendarType, - PopoverHorizontalAlign: require(path.resolve(fiori3Enums, 'PopoverHorizontalAlign.ts')).PopoverHorizontalAlign, - InputType: require(path.resolve(fiori3Enums, 'InputType.ts')).InputType, - LinkDesign: require(path.resolve(fiori3Enums, 'LinkDesign.ts')).LinkDesign, - ListMode: require(path.resolve(fiori3Enums, 'ListMode.ts')).ListMode, - ListItemTypes: require(path.resolve(fiori3Enums, 'ListItemTypes.ts')).ListItemTypes, - ListSeparators: require(path.resolve(fiori3Enums, 'ListSeparators.ts')).ListSeparators, - PanelAccessibleRoles: require(path.resolve(fiori3Enums, 'PanelAccessibleRoles.ts')).PanelAccessibleRoles, - PlacementType: require(path.resolve(fiori3Enums, 'PlacementType.ts')).PlacementType, - PopoverVerticalAlign: require(path.resolve(fiori3Enums, 'PopoverVerticalAlign.ts')).PopoverVerticalAlign, - SemanticColor: require(path.resolve(fiori3Enums, 'SemanticColor.ts')).SemanticColor, - TitleLevel: require(path.resolve(fiori3Enums, 'TitleLevel.ts')).TitleLevel, - BusyIndicatorSize: require(path.resolve(fiori3Enums, 'BusyIndicatorSize.ts')).BusyIndicatorSize -}; - -function getDefaultPropValue(meta) { - if (meta.isEnum) { - if (f4rEnums[meta.tsType][meta.defaultValue]) { - // f4r enum exists and contains default Value - return `${meta.tsType}.${meta.defaultValue}`; - } else { - // f4r enum exists but does not contain default Value - return `'${meta.defaultValue}' as any`; - } - } - // primitives - return meta.defaultPropAsString ? `'${meta.defaultValue}'` : meta.defaultValue; -} - -function generateImportStatements(imports, reactImports) { - // "import React from 'react';\n", - let importStatements = Object.keys(imports).length > 0 ? Object.keys(imports).join('\n') : ''; - const reactImport = `import React${ - Object.keys(reactImports).length > 0 ? ', { ' + Object.keys(reactImports).join(', ') + ' }' : '' - } from 'react';`; - - return `${reactImport}\n${importStatements}`; -} - -function generateTypingStatements(typingMeta, componentName) { - const imports = {}; - const reactImports = { - FC: true - }; - let defaultPropsStatement = `${componentName}.defaultProps = {\n`; - let hasDefaultProps = false; - let firstDefaultProp = true; - const interfaceName = `${componentName}PropTypes`; - - let interfaceStatement = `export interface ${interfaceName} extends WithWebComponentPropTypes {\n`; - - Object.entries(typingMeta).forEach(([key, meta]) => { - if (meta.importStatement) { - imports[meta.importStatement] = true; - } - - if (meta.reactImport) { - reactImports[meta.reactImport] = true; - } - - // console.log(meta); - interfaceStatement = interfaceStatement.concat( - !interfaceStatement.endsWith('\n') ? '\n' : '', - `\t${key}?: ${meta.tsType}${meta.originalProp && meta.originalProp.multiple ? '[]' : ''}; // @generated\n` - ); - - if (Object.keys(meta).includes('defaultValue')) { - // console.log(meta); - hasDefaultProps = true; - const defaultPropValue = getDefaultPropValue(meta); - defaultPropsStatement = defaultPropsStatement.concat( - `${firstDefaultProp ? '' : ', // @generated\n'}\t${key}: ${defaultPropValue}` - ); - firstDefaultProp = false; - } - }); - - interfaceStatement += '}'; - defaultPropsStatement += ' // @generated\n};\n\n'; - return { - importStatements: generateImportStatements(imports, reactImports), - interfaceStatement, - interfaceName, - defaultPropsStatement: hasDefaultProps ? defaultPropsStatement : '' - }; -} - -module.exports = generateTypingStatements; diff --git a/packages/main/scripts/wrapperGeneration/generateTypingsWeb.js b/packages/main/scripts/wrapperGeneration/generateTypingsWeb.js deleted file mode 100644 index 68c091342d6..00000000000 --- a/packages/main/scripts/wrapperGeneration/generateTypingsWeb.js +++ /dev/null @@ -1,230 +0,0 @@ -import UI5CalendarType from '@ui5/webcomponents-base/dist/dates/CalendarType'; -import CSSSize from '@ui5/webcomponents-base/dist/types/CSSSize'; -import Integer from '@ui5/webcomponents-base/dist/types/Integer'; -import UI5ValueState from '@ui5/webcomponents-base/dist/types/ValueState'; -import UI5Icon from '@ui5/webcomponents/dist/Icon'; -import TimelineItem from '@ui5/webcomponents/dist/TimelineItem'; -import UI5BusyIndicatorSize from '@ui5/webcomponents/dist/types/BusyIndicatorSize'; -import UI5ButtonDesign from '@ui5/webcomponents/dist/types/ButtonDesign'; -import UI5InputType from '@ui5/webcomponents/dist/types/InputType'; -import UI5LinkDesign from '@ui5/webcomponents/dist/types/LinkDesign'; -import UI5ListItemTypes from '@ui5/webcomponents/dist/types/ListItemType'; -import UI5ListMode from '@ui5/webcomponents/dist/types/ListMode'; -import UI5ListSeparators from '@ui5/webcomponents/dist/types/ListSeparators'; -import UI5MessageStripType from '@ui5/webcomponents/dist/types/MessageStripType'; -import UI5PanelAccessibleRoles from '@ui5/webcomponents/dist/types/PanelAccessibleRole'; -import UI5PopoverHorizontalAligns from '@ui5/webcomponents/dist/types/PopoverHorizontalAlign'; -import UI5PopoverPlacementTypes from '@ui5/webcomponents/dist/types/PopoverPlacementType'; -import UI5PopoverVerticalAligns from '@ui5/webcomponents/dist/types/PopoverVerticalAlign'; -import UI5SemanticColors from '@ui5/webcomponents/dist/types/SemanticColor'; -import UI5TitleLevel from '@ui5/webcomponents/dist/types/TitleLevel'; - -const mappings = { - [UI5ButtonDesign]: { - importStatement: "import { ButtonDesign } from '@ui5/webcomponents-react/lib/ButtonDesign';", - tsType: 'ButtonDesign', - isEnum: true - }, - [UI5PopoverPlacementTypes]: { - importStatement: "import { PlacementType } from '@ui5/webcomponents-react/lib/PlacementType';", - tsType: 'PlacementType', - isEnum: true - }, - [UI5BusyIndicatorSize]: { - importStatement: "import { BusyIndicatorSize } from '@ui5/webcomponents-react/lib/BusyIndicatorSize';", - tsType: 'BusyIndicatorSize', - isEnum: true - }, - [UI5PopoverHorizontalAligns]: { - importStatement: "import { PopoverHorizontalAlign } from '@ui5/webcomponents-react/lib/PopoverHorizontalAlign';", - tsType: 'PopoverHorizontalAlign', - isEnum: true - }, - [UI5PopoverVerticalAligns]: { - importStatement: "import { PopoverVerticalAlign } from '@ui5/webcomponents-react/lib/PopoverVerticalAlign';", - tsType: 'PopoverVerticalAlign', - isEnum: true - }, - [UI5LinkDesign]: { - importStatement: "import { LinkDesign } from '@ui5/webcomponents-react/lib/LinkDesign';", - tsType: 'LinkDesign', - isEnum: true - }, - [UI5SemanticColors]: { - importStatement: "import { SemanticColor } from '@ui5/webcomponents-react/lib/SemanticColor';", - tsType: 'SemanticColor', - isEnum: true - }, - [UI5ListItemTypes]: { - importStatement: "import { ListItemTypes } from '@ui5/webcomponents-react/lib/ListItemTypes';", - tsType: 'ListItemTypes', - isEnum: true - }, - [UI5PanelAccessibleRoles]: { - importStatement: "import { PanelAccessibleRoles } from '@ui5/webcomponents-react/lib/PanelAccessibleRoles';", - tsType: 'PanelAccessibleRoles', - isEnum: true - }, - [UI5ListSeparators]: { - importStatement: "import { ListSeparators } from '@ui5/webcomponents-react/lib/ListSeparators';", - tsType: 'ListSeparators', - isEnum: true - }, - [UI5ListMode]: { - importStatement: "import { ListMode } from '@ui5/webcomponents-react/lib/ListMode';", - tsType: 'ListMode', - isEnum: true - }, - [UI5TitleLevel]: { - importStatement: "import { TitleLevel } from '@ui5/webcomponents-react/lib/TitleLevel';", - tsType: 'TitleLevel', - isEnum: true - }, - [UI5InputType]: { - importStatement: "import { InputType } from '@ui5/webcomponents-react/lib/InputType';", - tsType: 'InputType', - isEnum: true - }, - [UI5Icon]: { - tsType: 'any', - comment: 'UI5 Icon Web Component' - }, - [UI5CalendarType]: { - importStatement: "import { CalendarType } from '@ui5/webcomponents-react/lib/CalendarType';", - tsType: 'CalendarType', - isEnum: true - }, - [UI5ValueState]: { - importStatement: "import { ValueState } from '@ui5/webcomponents-react/lib/ValueState';", - tsType: 'ValueState', - isEnum: true - }, - [UI5MessageStripType]: { - importStatement: "import { MessageStripType } from '@ui5/webcomponents-react/lib/MessageStripType';", - tsType: 'MessageStripType', - isEnum: true - }, - [Boolean]: { - tsType: 'boolean', - defaultPropAsString: false - }, - [CSSSize]: { - tsType: "CSSProperties['width'] | CSSProperties['height']", - reactImport: 'CSSProperties' - }, - [String]: { - tsType: 'string' - }, - [Integer]: { - tsType: 'number', - defaultPropAsString: false - }, - [HTMLElement]: { - tsType: 'HTMLElement' - }, - [TimelineItem]: { - tsType: 'ReactNode', - reactImport: 'ReactNode' - } -}; - -const reactNodeType = { - tsType: 'ReactNode', - reactImport: 'ReactNode' -}; - -function parseSlots(meta, typings) { - Object.entries(meta.slots).forEach(([slotKey, slot]) => { - const typeMeta = mappings[slot.type]; - let propKey = slotKey === 'default' ? 'children' : slotKey; - - if (typeMeta) { - typings[propKey] = { - ...(typeMeta.tsType === 'HTMLElement' ? reactNodeType : typeMeta), - originalProp: slot - }; - } else { - typings[propKey] = { - tsType: 'any', - originalProp: slot - }; - } - }); -} - -function capitalizeFirstLetter(s) { - return s.charAt(0).toUpperCase() + s.slice(1); -} - -function mapEventName(event) { - return 'on' + capitalizeFirstLetter(event); -} - -function mapDefaultValue(val) { - return val === Infinity ? val.toString() : val; -} - -const defaultValueWhiteList = [undefined, null, Infinity]; - -function getDefaultProp(props, typeMeta, key) { - if (Object.keys(props).includes('defaultValue')) { - // if(key === 'minWidth') { - // console.log(props.defaultValue); - // console.log(JSON.stringify(props.defaultValue)); - // console.log(props.defaultValue === Infinity); - // console.log(props.defaultValue == null); - // console.log(!defaultValueWhiteList.includes(props.defaultValue) && !typeMeta.isEnum); - // } - return { - defaultValue: mapDefaultValue(props.defaultValue), - defaultPropAsString: - (typeMeta.hasOwnProperty('defaultPropAsString') ? typeMeta.defaultPropAsString : true) && - !defaultValueWhiteList.includes(props.defaultValue) && - !typeMeta.isEnum - }; - } - return null; -} - -export function generateTypings(meta) { - const typings = {}; - - Object.entries(meta.properties) - .filter(([key]) => !key.startsWith('_')) - .forEach(([key, prop]) => { - const typeMeta = mappings[prop.type]; - - if (typeMeta) { - const defaultProp = getDefaultProp(prop, typeMeta, key); - typings[key] = { - ...typeMeta, - ...(defaultProp || {}), - originalProp: prop - }; - } else { - typings[key] = { - tsType: 'any', - originalProp: prop - }; - } - }); - - Object.entries(meta.events) - .filter(([key]) => !key.startsWith('_')) - .forEach(([key]) => { - typings[mapEventName(key)] = { - tsType: '(event : CustomEvent) => void', - importStatement: "import { enrichEventWithDetails } from '@ui5/webcomponents-react-base/lib/Utils';" - }; - }); - - if (meta.usesNodeText) { - typings['children'] = { - tsType: 'string' - }; - } - - parseSlots(meta, typings); - - return typings; -} diff --git a/packages/main/scripts/wrapperGeneration/index.js b/packages/main/scripts/wrapperGeneration/index.js deleted file mode 100644 index 28c53dd9480..00000000000 --- a/packages/main/scripts/wrapperGeneration/index.js +++ /dev/null @@ -1,45 +0,0 @@ -const puppeteer = require('puppeteer'); -const fileUrl = require('file-url'); -const { createWrapperForComponent } = require('./steps/createWrapper'); -const { createDemoForComponent } = require('./steps/createDemo'); -const { createTestForComponent } = require('./steps/createTest'); - -let pattern; -let onlyStopForMerge = false; -const queue = []; - -process.argv.forEach((val) => { - if (val.startsWith('-pattern') || val.startsWith('--pattern')) { - pattern = val.split('=')[1]; - } else if (val.indexOf('onlyStopForMerge') !== -1) { - onlyStopForMerge = true; - } -}); - -async function executeQueue() { - for await (const msg of queue) { - if (!msg) { - return; - } - try { - const dto = JSON.parse(msg.text()); - if (!pattern || dto.componentName.indexOf(pattern) !== -1) { - await createWrapperForComponent(dto, { onlyStopForMerge }); - createTestForComponent(dto); - createDemoForComponent(dto); - } - } catch (e) { - console.error(e.message); - } - } -} - -(async () => { - const browser = await puppeteer.launch(); - const page = await browser.newPage(); - page.on('console', (msg) => { - queue.push(msg); - }); - await page.goto(fileUrl('./scripts/wrapperGeneration/puppeteer.html')); - await browser.close().then(executeQueue); -})(); diff --git a/packages/main/scripts/wrapperGeneration/parseComponentNames.js b/packages/main/scripts/wrapperGeneration/parseComponentNames.js deleted file mode 100644 index 72989659e84..00000000000 --- a/packages/main/scripts/wrapperGeneration/parseComponentNames.js +++ /dev/null @@ -1,41 +0,0 @@ -const fs = require('fs'); -const path = require('path'); -const PATHS = require('../../../../config/paths'); - -const PRIVATE_COMPONENTS = [ - 'CalendarHeader', - 'DefaultTheme', - 'DayPicker', - 'ListItem', - 'ListItemBase', - 'MessageBundleAssets', - 'MonthPicker', - 'Popup', - 'TabBase', - 'ThemePropertiesProvider', - 'YearPicker' -]; - -const appDirectory = fs.realpathSync(process.cwd()); -const folderName = path.resolve(appDirectory, 'scripts', 'wrapperGeneration', 'json'); - -if (!fs.existsSync(folderName)) { - fs.mkdirSync(folderName); -} - -// create list of modules -const webComponentsModulePath = path.resolve(PATHS.nodeModules, '@ui5', 'webcomponents', 'dist'); -const standardWebComponents = fs - .readdirSync(webComponentsModulePath) - .filter((file) => file.endsWith('.js')) - .map((file) => path.basename(file, '.js')) - .filter((file) => !PRIVATE_COMPONENTS.includes(file)); -fs.writeFileSync(path.resolve(folderName, 'webcomponents.json'), JSON.stringify(standardWebComponents)); - -const fioriWebComponentsFolder = path.resolve(PATHS.nodeModules, '@ui5', 'webcomponents-fiori', 'dist'); -const fioriWebComponents = fs - .readdirSync(fioriWebComponentsFolder) - .filter((file) => file.endsWith('.js')) - .map((file) => path.basename(file, '.js')) - .filter((file) => !PRIVATE_COMPONENTS.includes(file)); -fs.writeFileSync(path.resolve(folderName, 'webcomponents-fiori.json'), JSON.stringify(fioriWebComponents)); diff --git a/packages/main/scripts/wrapperGeneration/puppeteer.html b/packages/main/scripts/wrapperGeneration/puppeteer.html deleted file mode 100644 index 302e3c7cbda..00000000000 --- a/packages/main/scripts/wrapperGeneration/puppeteer.html +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/packages/main/scripts/wrapperGeneration/puppeteerScript.js b/packages/main/scripts/wrapperGeneration/puppeteerScript.js deleted file mode 100644 index 4bf9de95000..00000000000 --- a/packages/main/scripts/wrapperGeneration/puppeteerScript.js +++ /dev/null @@ -1,34 +0,0 @@ -import { generateTypings } from './generateTypingsWeb'; - -const modules = require('./json/webcomponents'); -const fioriWebComponents = require('./json/webcomponents-fiori'); - -const createAndLogDto = (componentName, module) => { - const WebComponent = module.default; - if (WebComponent && WebComponent.getMetadata) { - const metadata = WebComponent.getMetadata().metadata; - const dto = { - componentName, - metadata, - typings: generateTypings(metadata) - }; - console.log(JSON.stringify(dto)); - } -}; - -modules.forEach((moduleName) => { - import( - /* webpackMode: "eager" */ - '@ui5/webcomponents/dist/' + moduleName - ).then((module) => { - createAndLogDto(moduleName, module); - }); -}); -fioriWebComponents.forEach((moduleName) => { - import( - /* webpackMode: "eager" */ - '@ui5/webcomponents-fiori/dist/' + moduleName - ).then((module) => { - createAndLogDto(moduleName, module); - }); -}); diff --git a/packages/main/scripts/wrapperGeneration/showOptions.js b/packages/main/scripts/wrapperGeneration/showOptions.js deleted file mode 100644 index 856b6b32685..00000000000 --- a/packages/main/scripts/wrapperGeneration/showOptions.js +++ /dev/null @@ -1,245 +0,0 @@ -import { generateDiff } from './diff'; - -const inquirer = require('inquirer'); -const fs = require('fs'); -const chalk = require('chalk'); - -function getEssentials(str) { - return str.replace(/[\n ]/g, ''); -} - -function parseStatement(statement) { - if (!statement) { - return {}; - } - return statement.split('\n').reduce((acc, line) => { - if (line.indexOf(':') !== -1) { - const parts = line.split(/:(.+)/); - const isGenerated = parts[1].indexOf('// @generated') !== -1; - acc[parts[0]] = { - value: parts[1].replace('// @generated', '').trim(), - isGenerated - }; - } - return acc; - }, {}); -} - -function filterObject(obj, propKey, constraint) { - return Object.entries(obj) - .filter(([key, item]) => item[propKey] === constraint) - .reduce((acc, [key, value]) => { - acc[key] = value; - return acc; - }, {}); -} - -function formatKey(key) { - let formattedKey = key.replace(/^[ ]+/g, ''); - return formattedKey.startsWith('\t') ? formattedKey : '\t' + formattedKey; -} - -function formatDefaultPropValue(val, isLast) { - return isLast ? val.replace(',', '') : val.trim().endsWith(',') ? val : `${val.trim()},`; -} - -function detectChanges(newProps, oldProps) { - let changesFound = false; - - Object.entries(newProps).forEach(([key, item]) => { - const existingItem = oldProps[key]; - if (existingItem) { - if ( - (existingItem.value === item.value && !existingItem.isGenerated) || - (existingItem.value !== item.value && existingItem.isGenerated) - ) { - changesFound = true; - } - } else { - changesFound = true; - } - }); - - Object.entries(oldProps) - .filter(([key, item]) => item.isGenerated) - .forEach(([key]) => { - if (!newProps[key]) { - changesFound = true; - } - }); - - return changesFound; -} - -async function showOptions(componentName, tsTypings, indexPath, jsxContent, onlyStopForMerge) { - const existingWrapperContent = fs.readFileSync(indexPath, 'utf8'); - - if (getEssentials(existingWrapperContent) === getEssentials(jsxContent)) { - return; - } - - const defaultPropsRegex = new RegExp(`${componentName}\.defaultProps(.|\\n)*?};`); - const interfaceRegex = /export interface(.|\n)*?}/; - - const oldInterfaceString = interfaceRegex.exec(existingWrapperContent)[0]; - const oldDefaultPropsRegexResult = defaultPropsRegex.exec(existingWrapperContent); - const oldDefaultPropsString = oldDefaultPropsRegexResult ? oldDefaultPropsRegexResult[0] : null; - const newDefaultPropString = tsTypings.defaultPropsStatement; - const newInterfaceString = tsTypings.interfaceStatement; - const diff = generateDiff(existingWrapperContent, jsxContent); - - const newInterface = parseStatement(newInterfaceString); - const oldInterface = parseStatement(oldInterfaceString); - - const newDefaultProps = parseStatement(newDefaultPropString); - const oldDefaultProps = parseStatement(oldDefaultPropsString); - - const mergeOption = { - name: 'Merge interface/default Props Statement', - value: 'mergeInterface' - }; - - const showMergeOption = detectChanges(newInterface, oldInterface) || detectChanges(newDefaultProps, oldDefaultProps); - if (onlyStopForMerge && !showMergeOption) { - return; - } - - function mergeObjects(obj1, obj2) { - let filteredObj1 = {}; - let filteredObj2 = obj2; - Object.entries(obj1).forEach(([key, item]) => { - const existingItem = obj2[key]; - - if (!existingItem) { - filteredObj1[key] = item; - } else { - if (item.value === existingItem.value) { - filteredObj1[key] = { - ...item, - isGenerated: true - }; - delete filteredObj2[key]; - } - } - }); - - return { - ...filteredObj1, - ...filteredObj2 - }; - } - - function mergeWrappers() { - let mergedWrapper = existingWrapperContent; - - if (newInterfaceString !== oldInterfaceString) { - const manuallyAddedProps = filterObject(oldInterface, 'isGenerated', false); - const mergedInterface = mergeObjects(newInterface, manuallyAddedProps); - - const interfaceName = `${componentName}PropTypes`; - - let mergedInterfaceStatement = `export interface ${interfaceName} extends WithWebComponentPropTypes {\n`; - - Object.entries(mergedInterface).forEach(([key, item]) => { - mergedInterfaceStatement = mergedInterfaceStatement.concat( - !mergedInterfaceStatement.endsWith('\n') ? '\n' : '', - `${formatKey(key)}: ${item.value}${item.isGenerated ? ' // @generated' : ''}\n` - ); - }); - mergedInterfaceStatement += '}'; - mergedWrapper = mergedWrapper.replace(interfaceRegex, mergedInterfaceStatement); - } - - if (newDefaultPropString && newDefaultPropString !== '' && newDefaultPropString !== oldDefaultPropsString) { - const manuallyAddedDefaultProps = filterObject(oldDefaultProps, 'isGenerated', false); - const mergedDefaultProps = mergeObjects(newDefaultProps, manuallyAddedDefaultProps); - - let mergedDefaultPropsStatement = `${componentName}.defaultProps = {\n`; - - const defaultPropsCount = Object.keys(mergedDefaultProps).length; - Object.entries(mergedDefaultProps).forEach(([key, item], index) => { - mergedDefaultPropsStatement = mergedDefaultPropsStatement.concat( - !mergedDefaultPropsStatement.endsWith('\n') ? '\n' : '', - `${formatKey(key)}: ${formatDefaultPropValue(item.value, index === defaultPropsCount - 1)} ${ - item.isGenerated ? '// @generated' : '' - }` - ); - }); - - mergedDefaultPropsStatement = `${mergedDefaultPropsStatement}\n};`; - - if (defaultPropsRegex.test(mergedWrapper)) { - mergedWrapper = mergedWrapper.replace(defaultPropsRegex, mergedDefaultPropsStatement); - } else { - const exportPattern = `export { ${componentName} };\n`; - mergedWrapper = mergedWrapper.replace( - new RegExp(exportPattern), - `${mergedDefaultPropsStatement}\n\n${exportPattern}` - ); - } - } - return mergedWrapper; - } - - const showPrompt = () => { - return inquirer - .prompt([ - { - type: 'list', - message: `${componentName} Wrapper already exists. What do you want to do?`, - name: componentName, - choices: [ - { - name: 'Keep existing wrapper', - value: 'keepOldWrapper' - }, - { - name: 'Accept New Wrapper', - value: 'acceptNewWrapper' - }, - ...(showMergeOption ? [mergeOption] : []), - new inquirer.Separator(), - { - name: 'Print New Wrapper', - value: 'printNewWrapper' - }, - { - name: 'Print Old Wrapper', - value: 'printOldWrapper' - }, - { - name: 'Print Diff', - value: 'printDiff' - } - ] - } - ]) - .then((answers) => { - switch (answers[componentName]) { - case 'acceptNewWrapper': - fs.writeFileSync(indexPath, jsxContent); - console.log(chalk.green(`Wrapper for ${componentName} overwritten`)); - break; - case 'mergeInterface': - const mergedFileContent = mergeWrappers(); - fs.writeFileSync(indexPath, mergedFileContent); - break; - case 'printNewWrapper': - console.log(jsxContent); - return showPrompt(); - case 'printOldWrapper': - console.log(existingWrapperContent); - return showPrompt(); - case 'printDiff': - console.log(diff); - return showPrompt(); - } - }); - }; - - console.log(chalk.cyan(`\n\n${componentName} Wrapper already exists. See changes:`)); - console.log(diff); - await showPrompt(); -} - -module.exports = showOptions; diff --git a/packages/main/scripts/wrapperGeneration/steps/createDemo.js b/packages/main/scripts/wrapperGeneration/steps/createDemo.js deleted file mode 100644 index a1bdae42468..00000000000 --- a/packages/main/scripts/wrapperGeneration/steps/createDemo.js +++ /dev/null @@ -1,173 +0,0 @@ -const fs = require('fs'); -const path = require('path'); -const dedent = require('dedent'); -const prettier = require('prettier'); -const PATHS = require('../../../../../config/paths'); - -const WEB_COMPONENTS_ROOT_DIR = path.join(PATHS.packages, 'main', 'src', 'webComponents'); - -const COMPONENT_DEMO_BLACKLIST = [ - 'CalendarHeader', - 'CustomListItem', - 'DayPicker', - 'GroupHeaderListItem', - 'ListItem', - 'ListItemBase', - 'MonthPicker', - 'Option', - 'Popup', - 'ShellBarItem', - 'StandardListItem', - 'Tab', - 'TabBase', - 'TableCell', - 'TableColumn', - 'TableRow', - 'TabSeparator', - 'TimelineItem', - 'YearPicker' -]; - -function checkForDefaultProp(meta, alt) { - return meta.hasOwnProperty('defaultProp') ? meta.defaultProp : alt; -} - -const knownNumbers = { - timestamp: +new Date() -}; - -function getKnownNumber(key, meta) { - const knownNumber = knownNumbers[key]; - return knownNumber ? knownNumber : checkForDefaultProp(meta, 42); -} - -const knownStrings = { - icon: "'add'" -}; - -function getStringValue(key, meta) { - const knownString = knownStrings[key]; - return knownString ? knownString : checkForDefaultProp(meta, "'generatedString'"); -} - -function buildPropWithKnob(knob, meta, key, alt) { - return `${knob}('${key}', ${checkForDefaultProp(meta, alt)})`; -} - -function createDemoForComponent(dto) { - const componentName = dto.componentName; - - if (COMPONENT_DEMO_BLACKLIST.includes(componentName)) { - console.warn(`Skip demo generation for ${componentName} because it is blacklisted.`); - return; - } - - const demoPath = path.resolve(WEB_COMPONENTS_ROOT_DIR, componentName, 'demo.stories.tsx'); - - if (fs.existsSync(demoPath)) { - return; - } - - const storyBookImports = {}; - let importStorybookActions = false; - const imports = {}; - const props = {}; - - function getPropValue(key, meta) { - if (meta.tsType === 'boolean') { - storyBookImports['boolean'] = true; - return buildPropWithKnob('boolean', meta, key, false); - } else if (meta.tsType === 'number') { - return '42'; - } else if (meta.tsType === 'string') { - return getStringValue(key, meta); - } else if (meta.isEnum) { - storyBookImports['select'] = true; - return `select('${key}', ${meta.tsType}, ${checkForDefaultProp(meta, 'null')})`; - } else if (meta.tsType === '(event : CustomEvent) => void') { - importStorybookActions = true; - return `action('${key}')`; - } else { - return 'null'; - } - } - - Object.entries(dto.typings).forEach(([key, meta]) => { - let propStatement = ''; - if (key === 'children') { - if (meta.tsType === 'string') { - propStatement = 'Some Content'; - } else { - propStatement = 'null'; - } - } else { - propStatement += `\t\t${key}={`; - let valueString = meta.multiple ? '[' : ''; - - valueString += getPropValue(key, meta); - - if (meta.importStatement) { - imports[meta.importStatement] = true; - } - valueString += meta.multiple ? ']' : ''; - propStatement += valueString; - propStatement += '}\n'; - } - props[key] = propStatement; - }); - - const hasProps = !!Object.keys(props).filter((prop) => !prop.children); - const hasChildren = !!props.children; - - const getStorybookImports = () => { - let storybookImportStatements = ''; - if (Object.keys(storyBookImports).length > 0) { - storybookImportStatements += `import { ${Object.keys(storyBookImports).join( - ', ' - )} } from '@storybook/addon-knobs'`; - } - if (importStorybookActions) { - if (storybookImportStatements.length > 0) storybookImportStatements += '\n'; - storybookImportStatements += "import { action } from '@storybook/addon-actions';"; - } - return storybookImportStatements; - }; - - const tsxContent = dedent` - import React from 'react'; - ${Object.keys(imports).join('\n')} - ${getStorybookImports()} - import { ${componentName} } from '@ui5/webcomponents-react/lib/${componentName}'; - import notes from './${componentName}.md'; - - export default { - title: '4 UI5 Web Components / ${componentName}', - component: ${componentName}, - parameters: { - notes - } - }; - - export const generatedDefaultStory = () => ( - <${componentName}${hasProps ? '' : hasChildren ? ' />' : '>'} - ${Object.entries(props) - .map(([key, string]) => (key === 'children' ? '' : string)) - .join('')} - ${hasProps ? (hasChildren ? '\t>' : '\t/>') : ''} - ${hasChildren ? `\t\t${props.children}` : ''} - ${hasChildren ? `\t` : ''} - ); - - generatedDefaultStory.story = { - name: 'Generated Default Story' - }; - - `; - - fs.writeFileSync(demoPath, prettier.format(tsxContent)); - console.log(`Demo created for component ${componentName}`); -} - -module.exports = { - createDemoForComponent -}; diff --git a/packages/main/scripts/wrapperGeneration/steps/createTest.js b/packages/main/scripts/wrapperGeneration/steps/createTest.js deleted file mode 100644 index d436d7de52f..00000000000 --- a/packages/main/scripts/wrapperGeneration/steps/createTest.js +++ /dev/null @@ -1,32 +0,0 @@ -const { readdirSync, statSync, writeFileSync, existsSync } = require('fs'); -const path = require('path'); -const prettier = require('prettier'); -const PATHS = require('../../../../../config/paths'); - -const WEB_COMPONENTS_ROOT_DIR = path.join(PATHS.packages, 'main', 'src', 'webComponents'); - -const createTestForComponent = (dto) => { - const component = dto.componentName; - const absPath = path.join(WEB_COMPONENTS_ROOT_DIR, component, `${component}.test.tsx`); - if (existsSync(absPath)) { - return; - } - const jsxContent = ` -import { mount } from 'enzyme'; -import React from 'react'; -import { ${component} } from '@ui5/webcomponents-react/lib/${component}'; - -describe('${component}', () => { - test('Basic Test (generated)', () => { - const wrapper = mount(<${component} />); - expect(wrapper.render()).toMatchSnapshot(); - }); -}); - -`; - writeFileSync(absPath, prettier.format(jsxContent)); -}; - -module.exports = { - createTestForComponent -}; diff --git a/packages/main/scripts/wrapperGeneration/steps/createWrapper.js b/packages/main/scripts/wrapperGeneration/steps/createWrapper.js deleted file mode 100644 index 34e5a41ecfd..00000000000 --- a/packages/main/scripts/wrapperGeneration/steps/createWrapper.js +++ /dev/null @@ -1,95 +0,0 @@ -const path = require('path'); -const chalk = require('chalk'); -const fs = require('fs'); -const showOptions = require('../showOptions'); -const generateTypingStatements = require('../generateTypingStatements'); -const PATHS = require('../../../../../config/paths'); - -const UI5_PLAYGROUND_WHITELIST = [ - 'Badge', - 'BusyIndicator', - 'Button', - 'Card', - 'CheckBox', - 'DatePicker', - 'Dialog', - 'Icon', - 'Input', - 'Label', - 'Link', - 'List', - 'MessageStrip', - 'MultiComboBox', - 'Panel', - 'RadioButton', - 'Select', - 'ShellBar', - 'Switch', - 'TabContainer', - 'Table', - 'TextArea', - 'Timeline', - 'Title', - 'ToggleButton' -]; - -const PKG_SRC = path.join(PATHS.packages, 'main', 'src'); -const WEB_COMPONENTS_ROOT_DIR = path.join(PKG_SRC, 'webComponents'); - -async function createWrapperForComponent(dto, options = {}) { - const componentName = dto.componentName; - const ui5ComponentName = `UI5${componentName}`; - const { onlyStopForMerge } = options; - - const folderName = path.resolve(WEB_COMPONENTS_ROOT_DIR, componentName); - const libFolder = path.resolve(PKG_SRC, 'lib'); - - if (!fs.existsSync(folderName)) { - fs.mkdirSync(folderName); - } - - const tsTypings = generateTypingStatements(dto.typings, dto.componentName); - const indexPath = path.resolve(folderName, 'index.tsx'); - - const jsxContent = ''.concat( - tsTypings.importStatements, - `import ${ui5ComponentName} from '@ui5/webcomponents/dist/${componentName}';\n`, - "import { withWebComponent } from '@ui5/webcomponents-react/lib/withWebComponent';", - "import { WithWebComponentPropTypes } from '../../internal/withWebComponent';", - '\n\n', - tsTypings.interfaceStatement, - '\n\n', - '/**\n', - ` * import { BusyIndicator } from '@ui5/webcomponents-react/lib/${componentName}';\n`, - UI5_PLAYGROUND_WHITELIST.includes(componentName) ? ` *
\n` : '', - UI5_PLAYGROUND_WHITELIST.includes(componentName) - ? ` * UI5 Web Components Playground\n` - : '', - ' */\n', - `const ${componentName}: FC<${tsTypings.interfaceName}> = withWebComponent<${tsTypings.interfaceName}>(${ui5ComponentName});`, - '\n\n', - `${componentName}.displayName = '${componentName}';`, - '\n\n', - tsTypings.defaultPropsStatement, - `export { ${componentName} };\n` - ); - - const libContent = `import { ${componentName} } from '../webComponents/${componentName}'; - - export { ${componentName} }; - - `; - - if (fs.existsSync(indexPath)) { - // update interface and defaultProps - return showOptions(componentName, tsTypings, indexPath, jsxContent, onlyStopForMerge); - } else { - fs.writeFileSync(indexPath, jsxContent); - fs.writeFileSync(path.resolve(libFolder, `${componentName}.ts`), libContent); - console.log(chalk.green(`Wrapper for ${componentName} created`)); - } -} - -module.exports = { - createWrapperForComponent -}; diff --git a/packages/main/scripts/wrapperGeneration/webpack.config.js b/packages/main/scripts/wrapperGeneration/webpack.config.js deleted file mode 100644 index f52856abdf7..00000000000 --- a/packages/main/scripts/wrapperGeneration/webpack.config.js +++ /dev/null @@ -1,44 +0,0 @@ -require('./parseComponentNames'); - -module.exports = { - entry: __dirname + '/puppeteerScript.js', - output: { - path: __dirname + '/dist', - filename: 'build.js' - }, - mode: 'development', - bail: true, - externals: { - qunit: 'qunit' - }, - module: { - rules: [ - { - test: /\.js$/, - loader: 'babel-loader', - exclude: { - test: [/types\/CustomListItem.js/, /test-resources/, /entrypoints/] - }, - options: { - plugins: ['@babel/plugin-syntax-dynamic-import', '@babel/plugin-proposal-object-rest-spread'] - } - }, - { - test: /\.(woff(2)?|ttf|eot|svg)(\?v=\d+\.\d+\.\d+)?$/, - loader: 'file-loader', - options: { - name: '[name].[ext]', - outputPath: 'fonts/' - } - }, - { - test: [/cldr\/.*\.json$/, /i18n\/.*\.json$/, /\.properties$/], - loader: 'file-loader', - options: { - name: 'static/media/[name].[ext]' - }, - type: 'javascript/auto' - } - ] - } -}; diff --git a/packages/main/src/components/ActionSheet/__snapshots__/ActionSheet.test.tsx.snap b/packages/main/src/components/ActionSheet/__snapshots__/ActionSheet.test.tsx.snap index 2e90629dfca..edc50675219 100644 --- a/packages/main/src/components/ActionSheet/__snapshots__/ActionSheet.test.tsx.snap +++ b/packages/main/src/components/ActionSheet/__snapshots__/ActionSheet.test.tsx.snap @@ -7,11 +7,13 @@ Array [ > , @@ -25,12 +27,14 @@ Array [ Reject This is my super long text! @@ -45,11 +49,13 @@ Array [ > , diff --git a/packages/main/src/components/AnalyticalTable/AnalyticalTable.test.tsx b/packages/main/src/components/AnalyticalTable/AnalyticalTable.test.tsx index 115ca758136..5e79e6247a9 100644 --- a/packages/main/src/components/AnalyticalTable/AnalyticalTable.test.tsx +++ b/packages/main/src/components/AnalyticalTable/AnalyticalTable.test.tsx @@ -152,7 +152,7 @@ describe('AnalyticalTable', () => { .at(1) .instance(); // @ts-ignore - component.onclick({}); + component.click(); expect(wrapper.render()).toMatchSnapshot(); @@ -162,7 +162,7 @@ describe('AnalyticalTable', () => { .at(0) .instance(); // @ts-ignore - component.onclick({}); + component.click(); expect(wrapper.render()).toMatchSnapshot(); }); diff --git a/packages/main/src/components/AnalyticalTable/__snapshots__/AnalyticalTable.test.tsx.snap b/packages/main/src/components/AnalyticalTable/__snapshots__/AnalyticalTable.test.tsx.snap index 3253e7d6164..15cc41589ec 100644 --- a/packages/main/src/components/AnalyticalTable/__snapshots__/AnalyticalTable.test.tsx.snap +++ b/packages/main/src/components/AnalyticalTable/__snapshots__/AnalyticalTable.test.tsx.snap @@ -51,6 +51,7 @@ exports[`AnalyticalTable Alternate Row Color 1`] = ` Sort Ascending @@ -74,7 +74,6 @@ exports[`AnalyticalTable Alternate Row Color 1`] = ` Sort Descending @@ -115,6 +114,7 @@ exports[`AnalyticalTable Alternate Row Color 1`] = ` Sort Ascending @@ -138,7 +137,6 @@ exports[`AnalyticalTable Alternate Row Color 1`] = ` Sort Descending @@ -179,6 +177,7 @@ exports[`AnalyticalTable Alternate Row Color 1`] = ` Sort Ascending @@ -202,7 +200,6 @@ exports[`AnalyticalTable Alternate Row Color 1`] = ` Sort Descending @@ -244,6 +241,7 @@ exports[`AnalyticalTable Alternate Row Color 1`] = ` Sort Ascending @@ -267,7 +264,6 @@ exports[`AnalyticalTable Alternate Row Color 1`] = ` Sort Descending @@ -546,6 +542,7 @@ exports[`AnalyticalTable Loading - Loader 1`] = ` Sort Ascending @@ -569,7 +565,6 @@ exports[`AnalyticalTable Loading - Loader 1`] = ` Sort Descending @@ -610,6 +605,7 @@ exports[`AnalyticalTable Loading - Loader 1`] = ` Sort Ascending @@ -633,7 +628,6 @@ exports[`AnalyticalTable Loading - Loader 1`] = ` Sort Descending @@ -674,6 +668,7 @@ exports[`AnalyticalTable Loading - Loader 1`] = ` Sort Ascending @@ -697,7 +691,6 @@ exports[`AnalyticalTable Loading - Loader 1`] = ` Sort Descending @@ -739,6 +732,7 @@ exports[`AnalyticalTable Loading - Loader 1`] = ` Sort Ascending @@ -762,7 +755,6 @@ exports[`AnalyticalTable Loading - Loader 1`] = ` Sort Descending @@ -1041,6 +1033,7 @@ exports[`AnalyticalTable Loading - Placeholder 1`] = ` Sort Ascending @@ -1064,7 +1056,6 @@ exports[`AnalyticalTable Loading - Placeholder 1`] = ` Sort Descending @@ -1105,6 +1096,7 @@ exports[`AnalyticalTable Loading - Placeholder 1`] = ` Sort Ascending @@ -1128,7 +1119,6 @@ exports[`AnalyticalTable Loading - Placeholder 1`] = ` Sort Descending @@ -1169,6 +1159,7 @@ exports[`AnalyticalTable Loading - Placeholder 1`] = ` Sort Ascending @@ -1192,7 +1182,6 @@ exports[`AnalyticalTable Loading - Placeholder 1`] = ` Sort Descending @@ -1234,6 +1223,7 @@ exports[`AnalyticalTable Loading - Placeholder 1`] = ` Sort Ascending @@ -1257,7 +1246,6 @@ exports[`AnalyticalTable Loading - Placeholder 1`] = ` Sort Descending @@ -1584,6 +1572,7 @@ exports[`AnalyticalTable Tree Table 1`] = ` Sort Ascending @@ -1607,7 +1595,6 @@ exports[`AnalyticalTable Tree Table 1`] = ` Sort Descending @@ -1620,10 +1607,13 @@ exports[`AnalyticalTable Tree Table 1`] = ` style="padding: 0px 1rem;" > Sort Ascending @@ -1689,7 +1679,6 @@ exports[`AnalyticalTable Tree Table 1`] = ` Sort Descending @@ -1702,10 +1691,13 @@ exports[`AnalyticalTable Tree Table 1`] = ` style="padding: 0px 1rem;" > Sort Ascending @@ -1771,7 +1763,6 @@ exports[`AnalyticalTable Tree Table 1`] = ` Sort Descending @@ -1784,10 +1775,13 @@ exports[`AnalyticalTable Tree Table 1`] = ` style="padding: 0px 1rem;" > Sort Ascending @@ -1854,7 +1848,6 @@ exports[`AnalyticalTable Tree Table 1`] = ` Sort Descending @@ -1867,10 +1860,13 @@ exports[`AnalyticalTable Tree Table 1`] = ` style="padding: 0px 1rem;" > @@ -2212,6 +2209,7 @@ exports[`AnalyticalTable custom row height 1`] = ` Sort Ascending @@ -2235,7 +2232,6 @@ exports[`AnalyticalTable custom row height 1`] = ` Sort Descending @@ -2276,6 +2272,7 @@ exports[`AnalyticalTable custom row height 1`] = ` Sort Ascending @@ -2299,7 +2295,6 @@ exports[`AnalyticalTable custom row height 1`] = ` Sort Descending @@ -2340,6 +2335,7 @@ exports[`AnalyticalTable custom row height 1`] = ` Sort Ascending @@ -2363,7 +2358,6 @@ exports[`AnalyticalTable custom row height 1`] = ` Sort Descending @@ -2405,6 +2399,7 @@ exports[`AnalyticalTable custom row height 1`] = ` Sort Ascending @@ -2428,7 +2422,6 @@ exports[`AnalyticalTable custom row height 1`] = ` Sort Descending @@ -2707,6 +2700,7 @@ exports[`AnalyticalTable render without data 1`] = ` Sort Ascending @@ -2730,7 +2723,6 @@ exports[`AnalyticalTable render without data 1`] = ` Sort Descending @@ -2771,6 +2763,7 @@ exports[`AnalyticalTable render without data 1`] = ` Sort Ascending @@ -2794,7 +2786,6 @@ exports[`AnalyticalTable render without data 1`] = ` Sort Descending @@ -2835,6 +2826,7 @@ exports[`AnalyticalTable render without data 1`] = ` Sort Ascending @@ -2858,7 +2849,6 @@ exports[`AnalyticalTable render without data 1`] = ` Sort Descending @@ -2900,6 +2890,7 @@ exports[`AnalyticalTable render without data 1`] = ` Sort Ascending @@ -2923,7 +2913,6 @@ exports[`AnalyticalTable render without data 1`] = ` Sort Descending @@ -3000,6 +2989,7 @@ exports[`AnalyticalTable test Asc desc 1`] = ` Sort Ascending @@ -3023,7 +3012,6 @@ exports[`AnalyticalTable test Asc desc 1`] = ` Sort Descending @@ -3064,6 +3052,7 @@ exports[`AnalyticalTable test Asc desc 1`] = ` Sort Ascending @@ -3087,7 +3075,6 @@ exports[`AnalyticalTable test Asc desc 1`] = ` Sort Descending @@ -3128,6 +3115,7 @@ exports[`AnalyticalTable test Asc desc 1`] = ` Sort Ascending @@ -3151,7 +3138,6 @@ exports[`AnalyticalTable test Asc desc 1`] = ` Sort Descending @@ -3193,6 +3179,7 @@ exports[`AnalyticalTable test Asc desc 1`] = ` Sort Ascending @@ -3216,7 +3202,6 @@ exports[`AnalyticalTable test Asc desc 1`] = ` Sort Descending @@ -3490,15 +3475,12 @@ exports[`AnalyticalTable test Asc desc 2`] = `
- -
+ /> Sort Ascending @@ -3522,7 +3503,6 @@ exports[`AnalyticalTable test Asc desc 2`] = ` Sort Descending @@ -3563,6 +3543,7 @@ exports[`AnalyticalTable test Asc desc 2`] = ` Sort Ascending @@ -3586,7 +3566,6 @@ exports[`AnalyticalTable test Asc desc 2`] = ` Sort Descending @@ -3627,6 +3606,7 @@ exports[`AnalyticalTable test Asc desc 2`] = ` Sort Ascending @@ -3650,7 +3629,6 @@ exports[`AnalyticalTable test Asc desc 2`] = ` Sort Descending @@ -3692,6 +3670,7 @@ exports[`AnalyticalTable test Asc desc 2`] = ` Sort Ascending @@ -3715,7 +3693,6 @@ exports[`AnalyticalTable test Asc desc 2`] = ` Sort Descending @@ -3751,9 +3728,9 @@ exports[`AnalyticalTable test Asc desc 2`] = ` - bla + Fra
- 20 + 40
- Nei + MAR
- 50 + 28
@@ -3810,9 +3787,9 @@ exports[`AnalyticalTable test Asc desc 2`] = ` - Fra + bla
- 40 + 20
- MAR + Nei
- 28 + 50
@@ -3989,15 +3966,12 @@ exports[`AnalyticalTable test Asc desc 3`] = `
- -
+ /> Sort Ascending @@ -4021,7 +3994,6 @@ exports[`AnalyticalTable test Asc desc 3`] = ` Sort Descending @@ -4062,6 +4034,7 @@ exports[`AnalyticalTable test Asc desc 3`] = ` Sort Ascending @@ -4085,7 +4057,6 @@ exports[`AnalyticalTable test Asc desc 3`] = ` Sort Descending @@ -4126,6 +4097,7 @@ exports[`AnalyticalTable test Asc desc 3`] = ` Sort Ascending @@ -4149,7 +4120,6 @@ exports[`AnalyticalTable test Asc desc 3`] = ` Sort Descending @@ -4191,6 +4161,7 @@ exports[`AnalyticalTable test Asc desc 3`] = ` Sort Ascending @@ -4214,7 +4184,6 @@ exports[`AnalyticalTable test Asc desc 3`] = ` Sort Descending @@ -4493,6 +4462,7 @@ exports[`AnalyticalTable test drag and drop of a draggable column 1`] = ` Sort Ascending @@ -4516,7 +4485,6 @@ exports[`AnalyticalTable test drag and drop of a draggable column 1`] = ` Sort Descending @@ -4557,6 +4525,7 @@ exports[`AnalyticalTable test drag and drop of a draggable column 1`] = ` Sort Ascending @@ -4580,7 +4548,6 @@ exports[`AnalyticalTable test drag and drop of a draggable column 1`] = ` Sort Descending @@ -4621,6 +4588,7 @@ exports[`AnalyticalTable test drag and drop of a draggable column 1`] = ` Sort Ascending @@ -4644,7 +4611,6 @@ exports[`AnalyticalTable test drag and drop of a draggable column 1`] = ` Sort Descending @@ -4686,6 +4652,7 @@ exports[`AnalyticalTable test drag and drop of a draggable column 1`] = ` Sort Ascending @@ -4709,7 +4675,6 @@ exports[`AnalyticalTable test drag and drop of a draggable column 1`] = ` Sort Descending @@ -5038,6 +5003,7 @@ exports[`AnalyticalTable with highlight row 1`] = ` Sort Ascending @@ -5061,7 +5026,6 @@ exports[`AnalyticalTable with highlight row 1`] = ` Sort Descending @@ -5102,6 +5066,7 @@ exports[`AnalyticalTable with highlight row 1`] = ` Sort Ascending @@ -5125,7 +5089,6 @@ exports[`AnalyticalTable with highlight row 1`] = ` Sort Descending @@ -5166,6 +5129,7 @@ exports[`AnalyticalTable with highlight row 1`] = ` Sort Ascending @@ -5189,7 +5152,6 @@ exports[`AnalyticalTable with highlight row 1`] = ` Sort Descending @@ -5231,6 +5193,7 @@ exports[`AnalyticalTable with highlight row 1`] = ` Sort Ascending @@ -5254,7 +5216,6 @@ exports[`AnalyticalTable with highlight row 1`] = ` Sort Descending @@ -5597,6 +5558,7 @@ exports[`AnalyticalTable without selection Column 1`] = ` Sort Ascending @@ -5620,7 +5581,6 @@ exports[`AnalyticalTable without selection Column 1`] = ` Sort Descending @@ -5661,6 +5621,7 @@ exports[`AnalyticalTable without selection Column 1`] = ` Sort Ascending @@ -5684,7 +5644,6 @@ exports[`AnalyticalTable without selection Column 1`] = ` Sort Descending @@ -5725,6 +5684,7 @@ exports[`AnalyticalTable without selection Column 1`] = ` Sort Ascending @@ -5748,7 +5707,6 @@ exports[`AnalyticalTable without selection Column 1`] = ` Sort Descending @@ -5790,6 +5748,7 @@ exports[`AnalyticalTable without selection Column 1`] = ` Sort Ascending @@ -5813,7 +5771,6 @@ exports[`AnalyticalTable without selection Column 1`] = ` Sort Descending diff --git a/packages/main/src/components/Avatar/Avatar.jss.ts b/packages/main/src/components/Avatar/Avatar.jss.ts deleted file mode 100644 index e895a5f3b27..00000000000 --- a/packages/main/src/components/Avatar/Avatar.jss.ts +++ /dev/null @@ -1,86 +0,0 @@ -import { ThemingParameters } from '@ui5/webcomponents-react-base/lib/ThemingParameters'; -import { CSSProperties } from 'react'; - -const size = (s): CSSProperties => ({ - height: s, - width: s, - minWidth: s, - maxWidth: s, - lineHeight: s, - textAlign: 'center' -}); - -const styles = { - // outer flexbox - avatar: { - backgroundColor: ThemingParameters.sapAccentColor7, - color: ThemingParameters.sapContent_ContrastTextColor, - fontFamily: ThemingParameters.sapFontFamily, - display: 'flex', - justifyContent: 'center', - alignItems: 'center', - backgroundSize: 'cover', - backgroundPosition: 'center', - borderRadius: '0.25rem', - '--sapContent_NonInteractiveIconColor': ThemingParameters.sapContent_ContrastIconColor - }, - // borderRadius 100% - circle: { - borderRadius: '100%' - }, - // biggest avatar; 7rem - sizeXL: { - ...size('7rem'), - fontSize: '3rem', - '& ui5-icon': { - width: '3rem', - height: '3rem' - } - }, - // 5rem - sizeL: { - ...size('5rem'), - fontSize: '2.25rem', - '& ui5-icon': { - width: '2.25rem', - height: '2.25rem' - } - }, - // 4rem - sizeM: { - ...size('4rem'), - fontSize: '1.5rem', - '& ui5-icon': { - width: '1.5rem', - height: '1.5rem' - } - }, - // 3rem - sizeS: { - ...size('3rem'), - fontSize: '1.125rem', - '& ui5-icon': { - width: '1.125rem', - height: '1.125rem' - } - }, - // 2rem - sizeXS: { - ...size('2rem'), - fontSize: '1rem', - '& ui5-icon': { - width: '1rem', - height: '1rem' - } - }, - sizeCustom: ({ customFontSize, customDisplaySize }) => ({ - ...size(customDisplaySize), - fontSize: customFontSize, - '& ui5-icon': { - width: customFontSize, - height: customFontSize - } - }) -}; - -export default styles; diff --git a/packages/main/src/components/Avatar/Avatar.test.tsx b/packages/main/src/components/Avatar/Avatar.test.tsx deleted file mode 100644 index d86cb86de66..00000000000 --- a/packages/main/src/components/Avatar/Avatar.test.tsx +++ /dev/null @@ -1,84 +0,0 @@ -import { createPassThroughPropsTest } from '@shared/tests/utils'; -import { mount } from 'enzyme'; -import { Avatar } from '@ui5/webcomponents-react/lib/Avatar'; -import { AvatarShape } from '@ui5/webcomponents-react/lib/AvatarShape'; -import { AvatarSize } from '@ui5/webcomponents-react/lib/AvatarSize'; -import React from 'react'; -import sinon from 'sinon'; - -const sampleAvatar = - 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAoAAAAKACAYAAAAMzckjAABft0lEQVR42u39+ZNm133feX7Oucuz516ZVYUq1IaN2LgAXEValiVblqZHDrWtiXaoHe2J6Y6O+YP8U4fbGrfV7o7xyMEe2VIPZdkkKFIkARIkFmKtQqH2qqxcn/Uu58wP9z5ZmbUvuTxP5vsVwUygABYq773nOZ/7PZv5F9875wUAAIADw3IJAAAACIAAAAAgAAIAAIAACAAAAAIgAAAACIAAAAAgAAIAAIAACAAAAAIgAAAACIAAAAAgAAIAAIAACAAAAAIgAAAACIAAAAAEQAAAABAAAQAAQAAEAAAAARAAAAAEQAAAABAAAQAAQAAEAAAAARAAAAAEQAAAABAAAQAAQAAEAAAAARAAAAAEQAAAABAAAQAACIAAAAAgAAIAAIAACAAAAAIgAAAACIAAAAAgAAIAAIAACAAAAAIgAAAACIAAAAAgAAIAAIAACAAAAAIgAAAACIAAAAAEQAAAABAAAQAAsD+FXAIA485IMqb8i02/th387X/jJcclB0AABICdY+2dgc5LcmUKc05ycnJOyr0k7+W8l/Obwpu/Lcg9IEwO/2NGkjWSNUYyRtZIgZWsrIwt/7m988+mTX8+ACAAAsB9gp65LeDlTkoypzQvQp33kvNFxAqNURAaBdYoDqyqlUCVyKoSGEVhoEpkFAVGUWAVBkaRtbKBNv6/m+XeF//NXEqdV5bnSnOvNPcapF5plmuQew1Sp36aK8md8tQrz7yy8s9jyoBojVEYGIXWFmHxLj8XABAAARzosJc7KXNSmjpluZMrQ14cWFUjq4lapMl6oEYl1GQtUqseaqJa/H0tDlWNrKzZ3T+/89IgdeokmboDp7V+qvVeprVuqvYg02o3V2eQqTNwSnO3EQ7DwBaB1BaVREIhAAIggP0Z9sovpgw6qZPSxCl1Ts55hYFRPQp0ZLKimUakmVasQ61Y0/VIU43okf97vvzi9OTzAP3wz2+2/l7WSLXYqhbHUlOSqnf9/690Uq32Ut1YS7S4nmipk2qpnag9yJXlXtYWlck4LEKhteWf3zHPEAABEMC4hb5NgS9xToPEKcuKX2/EgQ5PxTo6XdWx6Zpmm7FmmtEDg5jzW4dSN7YwuC2cDefwBTv48/mNL4Vh2PRlOBz+eaYaRYg9MVff8v9fbqdabCe6uNzT5eWBltuJVvu5vJPCQKpEthiytlQIARAAAYx46JOkLJN6iVOSOVkrNSuBzhyq68RsXcfn6pqfiO8drDatsN1ceTOSAjM6P+vmhSLS3cPm5krk8OcZTj2cbkaabkZ69nBj49+/vpbowmJX55e6urKcaLWfyTspDq0qoVUY3kqb5EEAT/w59i++d85zGQA8bujzXkpzp37ilDuvahzo8GRFp+frOnWocc/Al/s7g95BcHswvFewvb6W6NyNjs5e7+rq6kD9JFdgjapxMY/QGCqDAAiAAHYx9MlLSRn6nPNq1kKdPFTXc4ebOnGorsptqWY4hHvQwt7jhEJ7l+uT5l7nb3T1wdW2PrvRVbuXyRIGATwBhoABPDj0laEk81K7myl1Xs1qqJeOTeilY02dvG2Om1RU+IbDnqM2hDtyb+Lll81DycPh8MBIUWD0zOGGnimHjD9b7OvXF9f06fWOVjqpImtUq4YKza2wDQAEQACPHfy8pH7q1Euc4sjo1EJdrxyf0LMLTW3eTs/7W2mGwLcNoXBTINy86MQY6eRcVSfnqvKSPrna0a8urOr8Yl9rqVMltqpFVAUBEAABPKLASlkurSWZ8tzr8ERV336upRePTage27uHPgLfzoXBjS9br7sx0rOHG3r2cEO9JNe7F9f17oV1XV3rKzBGjUqoMCj2WgSALZ8rzAEEsBH8jFGSe3X6mcLQ6Mx8Q6+fmtTx2dqt8DH8wly+PXeve3Fxqae3zq3p42ttZZlXoxoqDoxyz8c9gAIVQOCgvwWqOL4syXOt9p3qlUBffWZKXz89pWb11kfEcB8+M9yXBSNx74b3YvOcwWMzNR2bqanTn9VPzq7o3QvrWupkalStKkFQHKvH5QMO9ucHFUDg4AqM1M+dun2nZjXQ66en9PqpKUWbJvB5z/DuuPG3VQXT3Outcyt68+yK1ge56rFVNbQbW/EAIAACOCDBL8mldj9Tqxboq6en9NXT0xtn6m6eY4YxD4Kb7qPz0pvnVvTTT5e13svVrIaKAxEEAQIggP3MmmJBwHo/Uy22ev30tL75zG3Bj7l9+y8Ill82B8Gffrqsn3y6rF7i1KqGCizbxwAHCXMAgYPwpld+aQ8yOS+9fnpS33lhbmPDZleGAyp++/v+D4OgNdI3npnWa6em9P0PFvXzz1YlI7UqoeTF/ECAAAhg3AXGqJ/l6gxynZmv63dentdsM5J0q+JnCX4HLgh6X2ww/TsvHdJrJ6b0V+/f0MdXO2rEgapRwIphYL9/HjAEDOzTxl1uBLzWzzRZj/Q7L87quSPN4h96yTPUe+B5ScZr40H46Gpbf/3eTS13U01Uw42zngHsP1QAgX3IGqmbOKW501dPT+q3Xzy0Mbw7XNVL+MNGRbB8Jp473NSzh5v66/dv6M2zq4oCq3psmRsIEAABjHSHXg7vLXczLbRi/d6XF3RksiKpmOdnmeeHezw3m18OfvvFQ3rxqQn9xS+u6dp6QjUQ2I/tniFgYH+wRuqlToPU6WtnpvT3Xpwre3WGe/Hwbh8W/s/vL+onZ1dUKauBbBkD7A9UAIF9Ev5We5kmKpH+yVePbBzdxnAvHrkqUH4ZPju/9eKcnj3c0P/xi+ta7qWaqoUMCQP7od/gEgBj3FmbYmh3qZ3q2cN1/Y+/c2LLub0M9+JJnq2hYzM1/T//3gk9f7ippXa6sW0QgPFFBRAY4w46SZ16mdPvvHJIXzs9JYmj27D9hs/UH75+WE/PVfVX7y6qElhVYsu8QGBMUQEExrHhGqndd7JW+m+/9dSt8CfCH3bmZWOY8147OaV/9hvHFQRG7X7GHpIAARDAboW/lW6mQ61I//3fPaFjM7WNzpm+GDsWAjf99dHpiv6H33pa862KlruEQIAACGDHe+Gb7UQvHGnqn/+d46rFQTEfiyuDXeS8VI0C/Xd/57hePNrSzXbCQwiMGeYAAuPCSyvdVN98dlZ/78XZ4pc8x7hhDyoHm1YJ/6PXFjRVD/TDj5c1XQtljOEsYYAACOBJGUnOe632Mv2Dlw/pdeb7YRSey3JeoJH0m1+YU7MW6f9857omqqECQiBAAATwZOEv917r/Vx/8OXDevl4a8s/A/b6+Rx67eSkqqHV//cX19SsBoRAgAAI4HE719Q7dXtO//hrh/Xc4aY8wQ8jykt66VhLcWj1Z29eUS22iqwlBAIjikUgwCiHv4HTP/76EcIfxuKZ9ZKePdzQH339iHqJU+oczyxAAATwsHLv1e05/dFXj+jZhQbhD2MVAk8fuhUCc+95dgECIIAHceWcvz/86mGdIfxhjEPgf/36Ea33c+UcFwIQAAHc31ov03/1pQU9f4RhX4x3CHz2cEN/8JUFrfUyOS4LQAAEcJfGaKSVTqrffnFOrxxvEf6wL0LgS0+19DsvH9JaN2XPSoAACOD28Hezk+n101P6+jPTGx0oMO4hUJK+dnpKXz8zpZttjo0DCIAANsLfai/T84fr+gevHOKCYF/67ZcO6YWjda1ydjBAAAQOOmOkzsBpthnrn3ztqKTiiC1gPxk+0v/4q0c1N1FRZ5Bzig1AAAQObvhLMy9jpH/6jVvhj44R++5Z3/Ri80+/cVTWGiXlsw+AAAgcKN5LnSTTf/3Vw2pUQ4nwh33+wuO8VK8E+idfPaJuklHtBgiAwAFreEZa7qT6zguzOjlXL4bICH84AM+9l3R8tqa/+8KcVjqsDAYIgMABYYy03s91er6ubz87I7IfDtTzX37/5rPTOrNQ13o/V0ADAAiAwH7v/NLMKw7NrUUfXBYcMMNn/g9fP6pKaNXPOC4OIAAC+zkAGqk9KE76iAJTLPrgsuAAvgh5L8Wh0f/1KwvqDDJ5GgJAAAT2o8BIK91MXz4xeeuMXzo9HOCXIS/p1KG6Xjs5yf6AAAEQ2J8NrZs6TdQj/d4X57kgwCa/++q8ZhqheomjIg4QAIH9wxmpN8j1X32pOOmDoV9g6/6Av/+lw+pnOUPBAAEQ2B8CI633Mn3xxKSenq0XHR+dHLClLRyfqepLT09qrZuxKhggAALjL8m8alGgf/hqWf3jkgBbDNvE7746r0YcKMloJQABEBjnBmak9UGmv/finALLql/gboZDwdZIv/XSnNYHLAgBCIDAuHZqRuoMnI5N1/Ty8dbGrwG4e3uRpJePtXR8tqb2wBECAQIgMH68pDRz+t0v3lr4AeA+baZsI7/7yrwy5+Qc1wQgAAJjxBip3cv00rGWFiYqkqf6BzxMu5GX5idivXyspfVBRrsBCIDA+HBOstbot1+elcTCD+BhDdvKb794SGFgqAICBEBgPARGWutn+srJSdXjsFj4QRUDeCjGFEPBtdjqKycntdZnWxiAAAiMgSSXqpHV33l+tuzRuCbAo6XA4tt3np9VPbJKci4JQAAERlhgpPYg0+unporhK7Z9AR4r/zkvhdbotVNTag+oAgIEQGCEJblUj6y++ex00ZHRaQGPFwLLtvPNZ6dVi6kCAgRAYEQNq39fPjml0FL9A54oAKqoAgbW6LUTVAEBAiAwojInxaHVN85MbnRgAJ4gBJaN6OvPTqsSWaVUAQECIDBKgvLIt5eeaiqOAlb+AtsRAFWsCI4Do5eeaqqdZArotQACIDAqsvIc02+cmeZiADvgG89My5qi0g6AAAjsfSOyUi/JdPJQXVONSBLVP2C7DNvSZC3Smfm6ukkmS88FEACBvea9lGReXzs9JUnKOfYD2FbDNvXVU1NKM8+52gABENj7BjRInQ5NVHRyri5JrFQEttmwTT09V9f8REWD1NF5AQRAYO8YI/VSp1ePtyQV21YA2H7DtvXq8Qn1Usc0C4AACOydYusXoy8dZ+sXYEdftsrvr55oqRJaFoMABEBgjxqPlbppplOHGqrElq1fgJ0MgKaYb1sNA506VFdnwGIQgAAI7EWH5KUs8/ricPiXSwLsqGEb++LxljLHYhCAAAjsgUHuNFELdWahIYnFH8BOG7ax0wsNTdZCpTmvXQABENjNjshK3cTpmTL8UYkAdsdwMcizh5vqJo6TQQACILC7nZD3Xi8dm+BiALtoWGh/6ammvPesvAcIgMDuNZo0d5qqRTo2Uy06JYZ/gd0JgGVbe2qmpqlapJQ9AQECILArHVA5/Ht6vtj4meFfYHcNq35nFhrqZk6GngwgAAI7zXvJOa/njzaLzohLAuzuS1j5/YUjDTlWAwMEQGA3ZLnUqoY6UR79Zhn+BfYkAT49V9dENVSSc0kAAiCwkw3GSr0007GZmoyKaiD5D9j9/Des+h2frWmQsCk0QAAEdrjjSZ3f2P6F4V9gbwzb3pn5hlLneREDCIDAzsmdFBmrU4dqNCBgBDqvU4dqikIr9oQGCIDAzjQWIyWZ02wrVrMaSmL7F2CvDNteoxpqthlrkDnm4wIEQGBnOpx+5jb2/mMDWmBvDdvg0zNVDTLHCxlAAAR2Ru68Th4q9//jcgB7atgGTx6qK+eNDCAAAjsT/qRqZHV8pkLjAUaoAzs+XVM1skqZBwgQAIFtbSjl/L/peqxazPw/YBQM22Altpqux0qZBwgQAIHt7mgGmdORqaL6x8kDwGgYtsWjUxUlzAMECIDAdsu917GZYvsXRpqA0TBsi8fmasp5MwMIgMC2hj8nBcbo6BTz/4BR7MSOTlYVyrAfIEAABLY3ANbiQLOtuPgFhpmAkTAc8p1pRqpXAmUEQIAACGxLI7HFApC5Znyr0+GyACNntlUuBKFnAwiAwJMqzv91mp8sAmDONCNgpAzb5PxErNQ5XtAAAiCwPZz3WpiociGAEbYwUZVjIQhAAAS2g/eS9UaHJmIaDTDCHdmhiVjWG7ZpAgiAwJPL8mKj2dkmC0CAkbSxECRWJbbKci4JQAAEnrCB5M6pXgkUBYb8B4xu/lMUGDUrgXLn6NwAAiDwZC0kc17TtYhrAYyw4ajvZD1S5jy9G0AABB5fsQLYa6ZRBEBWAAOjyZVtc6YZKXWeSj1AAASejPfSTLkBNJ0KMLova5I014xZBAIQAIEn57zXdFkBpF8BRvRFrfw+3YjYCgYgAAJPJndSZIxatZAGA4xBZ9aqRooCzgQGCIDAE3BeiiKr1nARCGPAwGgq22arFioKrBwBECAAAo/bOJx3igOrClvAAOOQ/xQFRpXQyomtYAACIPCYPUrupHol4FoAY6RRCYohYHo4gAAIPE4AdM6rVQZAppUDo23YRhtxIMeeTQABEHjM/KfMedWrxQIQR38CjLRhG21UQ2WevQABAiDwmLykRmw3AiGA0X5pk6RGJaRiDxAAgScIgL7oTACMj0bVshk0QAAEniQAejWqBEBgrAJgJZQnAQIEQOCxA6CkajkETHcCjH57laRaZGmvAAEQePzOxBqjahDQWIAx6tAqUaDAGEIgQAAEHp1zUmClSsTyD2CcVAIra8VpIAABEHjMBmKM4pBmAoyTKDSyhhc3gAAIPAZXBsDA0pEA4yQMigBIARAgAAKPlQCtkaJhBZAcCIy2so1GYTEETAIECIDA4/UnxiikAgiMlcAUFUAWgQAEQOCReTltzn7EQGDEX9i2vLxJlAABAiDwyB2Jl2So/gFjabgNDJ0cQAAEHo2XQvIfMJ6dm+E4OIAACDwiKoDAeAsM6Q8gAAKP20DoQ4Cx5OndAAIg8NidCJcAGN/OjQYMEACBx2ogtBAAAAEQOFg8u0gAY8lJ7N0EEACBx5MzhASM58sbbRcgAAKP3HlouBKYXgQYyzbsaLsAARB4HIYqAjC2AdAPTwMBQAAEHrbzkGRklVFFAMZS5ryMOAwOIAACj8hI8v7WIDBREBj9F7ch54uXOAAEQODROxQv5VQBgbGSO8/8XYAACDx+63BeyrJyEIn+BBjxN7biW5o7OU8PBxAAgcdsHM57JVQAgbGS5V7OeTo4gAAIPB7n/a0KIICxkGRejiX8AAEQeKzGYSXnpITdoIGxkuZOznGUI0AABB6DkZR7ryTNJbGdBDDqhm10kHnlVAABAiDwJCGwm7qNvwYw2u1VknpJJkObBQiAwGN3KMaon+RcCGCM9JNchmNAAAIg8NgBUFI3YfAXGCe9lDYLEACBJwmARmr3M0lsAwiMumEbbQ8yzgEGCIDA43cm1ki9cgiYxgKMR4fW7TsFhpc2gAAIPG4DMVbdMgBSUQBG27CNdtNMlgYLEACBx+KlwEo95gACY6U7cLKWEiBAAAQeg/NSYK06g4yLAYyRXpIpKM/yBkAABB6ZsVKae/XLzaDZWxYYTcOmOUhzJbmXpXsDCIDAkzSQzDl1B+wFCIxDAuymTmnuOQYOIAACT9BArJTlXu1BMQ+Q2YDAaGv3cmW5IwACBEDg8Znyy0onvfX3AEbO8OVstZtKhrYKEACBJ20kxmilWwRApgACo22ll8oS/wACIPAkvKRAZVWBBgOMfGe20k1l2AEGIAACT9xIAqv18jg49pYFRtOwba73MoVMAAQIgMATcVJopbVeyrUAxsBaL1NoxYotgAAIPFH+U2Cs+qlTVu4qy9ASMFqGbTL3Xr00V2At+Q8gAAJP2EislOROa91MJEBgdBPgWjdTkrEHIEAABLZBUJ4GslIOA1NZAEbLsE2udFNluVNAzwYQAIFtaSjGaGk9kcT+YsCoGbbJpU4iw0otgAAIbF8AlG62iwDICDAwWoZt8uZ6Kkv+AwiAwHZ1LqE1WinnAAZ0MMBIGbbJlW6q0Bpe0gACILANXBEA2QoGGG1rvSIAMlEXIAAC25H/FFir9iBXmrMVDDBKhm0xc17tPlvAAARAYBuFVkoyp+VOKhIgMHoJcLmTapCxAhggAALbyFgpd35jIQgVBmA0DNvizXai3LEHIEAABLa7sVijG2sJFwIYQTfWE1m2gAEIgMB28ipWGi6WFUAaDjBandjiWqLAMjsDIAAC28lJUWC13BlIkig0AKNh2BaXO6kiJgACBEBgm/OfQmu13suVOVYCA6Ng2AZz57XWTxVaK8cEXYAACGynMJD6idPN8kg4EiAwGgnwZjtVP3UK6dEAAiCw3YyRnPG6vsZKYGAUDNvg9dWBnPcy9GgAARDYkQZjjK6s9LkQwAi5utZnBTBAAAR2hpcUWbuxEpgzgYG9NWyDN9YSRdYyKwMgAALbzzkpCqXlNnsBAqNkuZ0oCsUCEIAACOyM0Fp1E6fV8kg4T8kB2BPDtrfeS9UZOIUcAQIQAIGdElgpzZ2urbMQBNhLw7Z3bTVR4jgDGCAAAjvdaKzRpaUeFwIYAZeWewosE3IBAiCwg4YLQa6uFieCsBAE2BvDtndlZaDIGhaAAARAYOcUC0Hsrc2gAeypm+1EUWhYAAIQAIGdFVqpM8g3toNhIQiwu4ZtbqmdqpPkLAABCIDAzguslHuv6+UwMIUHYHdtLABZGyjLPQtAAAIgsFsh0OhCuRCEaYDA3rhwsyfLAhCAAAjsBu+lOLS6slxUAOl/gF1+ARsuAFnuqxJyAghAAAR2gfPFQpClTqp+mm+EQgC78AJWfh+kXje7qSJrWQACEACB3RFaqZ/musY8QGDXX8Ak6dpqT/00VxhwTQACILBLjCRrjM4v9rkYwB74/GZfVkaGKRgAARDYLV5SFFhdWi4WgrAhNLA7hm3t4nJPUcAG0AABENhFzkmV0Or6erLRAdERATv/4jV0Yy1RHAbM/wMIgMDuCgOpO8h0eXguMAkQ2JUEeHl5oPYgV8T8P4AACOy2Yu6R0Wc3iwBIIQLYWcM2dn6xu6kNAiAAArvIS4oDq88XmQcI7IZhGzu/2FXM/D+AAAjsheE8wGurA+Xl3hR0SMDOvXBJxTYwV9cGqjD/DyAAAnslDKRemutSeSoICRDY2QR4aamvXsL+fwABENhDxkjGGH12o5iTREEC2BnDtvXZYleG/f8AAiCwl4bzAM+XAZB5gMDOGLatzxe7igPO/wUIgMAeck6qRlbX1gbqJZwLDOzIi1bZpvpJrqtrA8Ux5/8CBEBgjwVWSnKnzxbZDgbYkRet8vtniz0NUqeIngsgAAJ7zUsKrdHHVzs0KmAHO6qPr3cUWrZ/AQiAwChwUjW2ulieCMLkdGB7DdvUxcWeqrGlzA4QAIGRyH+KAqu1bqarq8V2MMwDBLbHsC1dX0u02s8UWUv+AwiAwIg0JCPJSJ+Uw8B0UMD2vWBJ0sfXOvJesvRaAAEQGBXeS5XI6pNrbAcDbKdhW/rkaluVkO1fAAIgMEKcL46Fu7420Gov3QiFAJ7sxUqS2v1M11cTVSO2fwEIgMCICayUe6+PrzAMDGzLi1X5/cOrbWXeK6DHAgiAwKgZngryUTkPkGFg4Alfqso29NGVDqd/AARAYDS5cjuYK6t9TgUBnvSFanj6R5rr8kpfFU7/AAiAwKgKjTRI3cZiEPor4DFfqMrvn1zrFqd/UFEHCIDAqPJGikOjX19Zl8QwMPDYnVPZdj64tK44NPK0JYAACIwq56RqFOrizZ6SlGFg4LFepLxkJKW51+fLPVWjkOFfgAAIjLbISv3U6cOrDAMDj/UiVX7/8HJb/cQpoqcCCIDAqBsOA793cU0Sw8DAoxq2mfcurTH8CxAAgfHgnFSLQ11c7qs7yIpQyDAw8HAvUGVb6SaZLiz3VYsZ/gUIgMCYCE0xf+m9S+0iFHJJgId7gSq///piW2nmFVL9AwiAwLjwKs4Gfv9yEQAZBgYezsbw7+W2KoFl+BcgAALjw3mpFlpdWenrxnpShEKGgYH7vziVbWSxnejySl81Nn8GCIDA2DWusnX96nyxGIT8BzwgAJbff/X52pY2BIAACIyN3En12OrDK8UwsGUoC7h/hzTc/PlyW3WqfwABEBhXlcBqtZfq46udIhRSBgTu/sJUto1Pr3W02k2L+X9cFoAACIwjb6QoNPrl+VVJLAYB7tkZlW3jF5+vKmTvP4AACIyz4Z6A52721GFPQODuL0rl0W/dQabPbvRU5+g3gAAIjLvQSFnu9fPPWAwC3DUAlt9//tma0twrpGcCCIDAuHNealSs3r1QrmxkaAvY2hGVbeKdS2tqxFaOtySAAAiMO69iMchSN9VH5YpgFoMA2tIWPrra0VI7VSVk8QdAAAT2UwgMA/307IokFoMAQ8O28ObZFVXCgMUfAAEQ2D+Gw8AXlzkZBNh4MSrbwM12ogtLvWL4l8UfAAEQ2G+NzUr6yafLXAxgk7/9dFlenPwBEACBfSj3UqMS6oMrbfUSJ2OoAuLg8l4yRhqkTh9cbqtVCZVT/QMIgMB+FFopzbx+Vs4FJP/hwAbA8vtPz64oydj6BSAAAvtY7qVmJdQvP1+VfLH9BSEQBzH8Dbd+efv8qhqVkJXxAAEQ2N/iQGr3Mv3s3ErRGdLx4SAmQElvnV3R+iBTJeCSAARAYJ9zXqpXg41hYDaGxkFjymf+p2dXVI8DXoIAAiCw/3lJ1dBqpZvqV5+vboRC4KC8AEnSOxfWtdxNVQutWPsBEACBgxECvVSPA/3tx0UApAqIA9PplM/6jz9ZpvoHEACBg8VJqkVWi52B3r24XvwaHSH2+3NfPuPvXlzX4vpAtYjqH0AABA6YYRXwRx8XG0NTBcS+73DKZ/xHH1P9AwiAwAG1UQVcH2zMBaRDxH5+4ZGkX35O9Q8gAAIHPQR6qVEJ9DcfFVVAQxUQ+9Tw2f7RJzfViAOmPAAEQODgGq4IXu6lt04HoWPEfnvOy2f6Z2dXtLyeqhpZNkAHCIDAwZZ7qVUJ9eOPl+TK81HpHLGfXnKMKaY8/PiTZbVqnPoBEAABSJLiwKgzcPrBB4tFp0kHif0SAMtn+YcfLKrTzxUHzHMACIAAJBVVwIlaqDfPraozyIozggmB2Afhzxqpm2T66dlVTVD9AwiAAG5rjFZyzut77xZVQOokGHfDZ/iv3r0p57xCehyAAAhgK++lVi3UB5fburw6kKgCYsyfZxnp6upA719cV5PqH0AABHBvcWj1l7+8LoltYTC+hs/uX75zQ1FkqWgDBEAA91KcDmJ1Zbmvn59jc2iM73MsSb/4fFWXb/bUiC3PMUAABHA/rlwQ8v0PbyrNPdvCYLzCn4rqX5p7/Zf3b6pVDdn0GSAAAngYcWCUZE7/4e1yKJhLgjExfFb/8pfXlWROccjTCxAAATyU4bYw719a02eLXUkMBWP0DZ/Rz2929c6FNTZ9BgiAAB6V8VItDvSXb99aEEJfipENf7q18OMvfnldtUogywMLEAABPBonqR5ZLXcz/dV7NzZCITCqLyyS9J/evaGlTqZaZOW4LAABEMCjy7002Qj1s7OrurzSY29AjKTNe/797OyqJuss/AAIgACeiPFSNbT67pvXir9nKBijFP50a+j3u29dUSWyVKoBAiCA7ehg67HVai/TX5QbRAOj5i9/db0Y+o0tLygAARDAdsi9NFEP9Yvzq/r4WkdGDAVjBF5OfLHty9lrHf38M4Z+AQIggG1nvNSshPrzX1xTP82LoWA6W+xl+DNSP8313V9cU7MSMvQLEAABbHuHK6kSGmW515/97GoRCtljF3v1QlI+e//uZ1eV5V6V0DD0CxAAAeyE3EutaqDzN7p644OljWAI7PbLiCT94INFnb/RU6sasOEzQAAEsJOclyYbkd748KbO3egWR2/R+WIXnz8j6dxiVz/8cFnTDeb9AQRAALvTcI3UqIb6929dVWeQsT8gdoX3xbPXHeT67ptX1aiGskxDAAiAAHaH81IcGnkn/W8/viyJ/QGxw+FPt+b9/du/vazcecWhofoHEAAB7GqH7KVGxerGeqLvvlUuCuGyYIcMn63vvnVVN9YGalQCqs4AARDAXnBemqqHevfiut74kEUh2KGXjfL7Dz9c0nsX1zXFfn8AARDA3ofA6UakH3x4U+9eXC82ieayYBvDn5H064vr+v6HNzXViAh/AAEQwCgwkiZrof787Wu6cLPPymBsW/ozki7c7Ov/ePuaJmsh0wwAAiCAEeqnFVijemT1v//kkhbXE8mISg0emytLf0vtRP/7Ty6pFlkFls2eAQIggNEKgV6KQqvAGP3pjy6qM8hkCYF4zPBnjdQZZPo3f3NRgTGKQsuiD4AACGBUQ2A1tsqc9Cc/uKR+msuyRyAe8RmyRuqluf7kB5eUuuKZ4hkCCIAARrwDb8RW/STVv/7hJWXOF3sE0oHjIZ4dY6Qk8/rXb1xSP0nVIPwBBEAA48H54qSQ1W6if/WDC0qyIgQyHIz7PTPD8Pcnb1zQWi9Ro8p2LwABEMDYdeitaqiVTqI/eeOC0ixnTiDu+axYI6VZrj9544JWu4lahD+AAAhgvEPgajfRv/zBRbVZGIJ7hL/2INP//IMLWu2mhD+AAAhgv4TAziDXv/r+Ba100mJhCJfmwPMqwt9KJ9W/+v4FtQdOrWpA+AMIgAD2SwhsxlZZXszvurw84MQQwp+MpKvLA/3JGxeU5V7N2BL+AAIggP0kL7eIkZH+zQ8v6MMr7Y1THejzD1bwUxn+PrzS1r/+4QXJFM9GzoMAEAAB7MPO30uV0KpeDfRnb17R336yvBEG2OrjYNz/Yej/20+W9WdvXlG9GqjCJs8AARDA/g8BgTGarEX66/cW9edvXytCIItD9rXhNi+S9OdvX9Nfv7eoyVqkwBjCH3AAhVwC4ACGwPL7TDPSOxfWdbOd6o++ekT1SrAxNwz77G3fSO1Brj/72RVdWu5rphnJeYb/gQP7mcAlAA4u56Xpeqjrq339T//5vD5f7N6aF0gyGP+gv+kenlvs6l/+5/O6ttrXdJ1tXgACIIADHwKb1VAy0v/648v6wQdLkhgS3g/3dTjk+19+vaT/7ceXJVPca+4rAIaAAch7KQ6soqrVGx8u6cLNrv7gtcNqVcONf24YFx6be2lMOeTbz/Tv37qqizf7mqyFnAkNYIP5F987x8cBgA3WSOuDTKEx+rsvzunLJyYJgWMW/iTpF+dX9dfvL8p7r2aFqh+AragAAnv9FlbuyDwq/bPzUrMSKnNef/H2dX1yraPf/+K8GhWqgaMe/IyROoNM//GX1/XhlY4m66FCa0Yq/JnyC5VIYI/bIhVAYG8Mj2PrJbnCwCgKRm8vNmuktV6mIDD6znOz+tqZqTtCB/Y++A397OyKfvDhTeW510Rt9Kp+xkhp7pTlXrU4kBHzTIG9QgUQ2KPg1x5kSnPphSMN3WxnWu2lqsejFQKdl1q1UJmTvvf+Df360rp+++U5HZup3ZpPZtg2ZteDX/llGP4uLfX0n95f1MWlvlq1SHGskTvVwxipmzhN1iLNNkN9cKWjKJAalZAgCOxFm6QCCOxu8OsMMqW514nZur79/Iyenq2pPcj1L//zeTkjVUf0VAZrpO7AaZA7vfxUS7/98qzqcbgRFA1BcFeCn/fFvZCKQPWf3r2h9y6tKwqsGpXRPMvXGKmfOVkv/T9+64SalUCf3+zphx8u6fzNrqLAEAQBAiCwz4KflbyT2kmmLJdOzdX0reeK4LfZzXaiP3njggJrRvZormGIXS+Hhb9yYlLffn5WUVAkEiqCOxf8Nlf8Muf1xgc39fPzq8pzr2YtHNnj/IyRBplT7qR//p1jmm3GW/755zd7+tFHSzq32FMYSM04lLGSc9x3gAAIjKHASlleVPy8pNPzdX39zPSW4Lcxh6sMTleWB/rTH19UHBhFI3w+qzFFB73Wz9SMA71+ekpfPTOl0G4KgmKO4BMHv9uuY+a83jy7op+dXVF7kKtZDRVajfRzkmZOSe71x986piNTlY1n/fb5i5/f7Oknny7r7PViM/JGJVQYSDlBECAAAqPOSjLWKMm8OkmmwBg9e7iubz07q/mJ+M7gdxeXl3v607+5rEo02iFQKs4UTvJc7b5Ts1IEwa+cnFIlMg/1s+LewW/zNRukXj8/v6I3Px0GP6s4CJSP8MMxDH+D1OuPf+OYjk7fCn/3+1mvryX60cc39fHVrnLv1YhDxaGRd15kQYAACIxW8CurMIPUqZM41WOrl55q6RvPTGuiFj50GBr2jxeXevq3PxqPEHgrCDq1B7mqkdVLTzX1zWdnNjaSlsp5giIM3i/0ed2a3ydJ6/1MP/54We9dWlc/LUJ2HNiRDn7D8JdkTknq9U+/dVTHZmoPPGP69rax1sv0t5+UP3viVIutKpHdqD4DIAACexd8rJQ5qZdkSjKv+VZFXzwxoVePt1SJgocOfndzeXmg//XHFxUEZmQXhtwZBKUk10b189Shmr5yYlKnFxpb/r3cl9XSAx4GvZdced02O3uto59/tqrPbvaUubIKFozeyt57hb9B5pTnXv/0m2Xl7xGvydbqZ65fXVjX2+fXdGN9oDg0qsXF0DfDwwABENg1tlzkMMidukmxsvHpuZpePz2lZzYFnSeZBzesllxfS/RvfnRRxkv12I5FALhrMJ6o6IUjTb3ydEuTtehAh8F7hb7VXqp3Pl/XB1faur4+UByUQcdofO57udWLN9I/+9YxHZqIH1j5u991ur39fHKtozfPrujzxZ6cKdpEJbDyYvUwQAAEdir4lcO8vYFTP8vVqoZ6/khTr5+a0kzzVqjZrqHOYSVkqZPqT//mopI8VyMeryO9Ng+N9xKnMDA6NlPVc4cbeu5oU61KeNdwtJ8C4f1+pvVBpo8vt/XR1Y4uLPXLDZLLoc4xCzXWFJXfOAj0x79xTDONaFvmf95taHypnerNcyv68Epb6/1M1TBQrcLwMEAABLYxwBhJaSZ1k0zOSUenq/riiZZePjapwN4Z2LaTK/d86ya5/pcfXtBqNxvJEx4eeB0lmbIq2E9yJalXHBkdna7q9Hxdzyw07tge5PbwNA7bywy3a7lfiL3ZTvTpta7OXu/o0nJ/41pU46BY0es0dosdhifGTNZD/bNvH1c9Djae3e0O05uvae6kdy+u6pfn13V5uS9rpXocKgqLe0EYBAiAwCOHFeekXuLUT3PVKoFeONLUl05O6shkZUuHJO1stWrY6aW507/98WVdXu5rqh6O7ZDXMFRvhMHcK5A0OxHr+ExNJw/VdGy6qnolvOf1cJvu1V4Ew81BT7p/xbI7yHRxua/PbvR0Yamvm2sD5ZLiYFPoG+OwYo203M10bLqq/+abRzeONNzpNnF7u7uyOtDbn63qgytt9Qa5qlGgWmw39uEkCwIEQOCewWQ4XNlPnIyRjs5U9cqxlr5wdGLL1ia5vzUXcFcCx6YO9c/evKpfX1rTdDMuk8h4X3OjopKTZE79zMk5r0pkNduIdXiyoqPTFR2bqWnmLhXCe4VDc1tYs4/457rX7/EwoWapnejS8kCXlnu6ujLQzU6iQepkbbGYJw6tArtPKlRGWm4nevGpCf3h64fveFZ3I4g7v3U+5SD1+vXlNb1zcV2Xl/ryXqqyghggAAIb4aP84n1RXesnTrmX5pqxnj1c18vHJjTXiu9bddhNmzvWv35/UT/5ZFmtWqjAmrFYIfzA+2GKn28YjAaZU1KuJg1Do1oUaKIWaWEi1qHJWHPNWJO1SBP1aNuHGh8meax0U632Ui22E91YS3RtNdFaL1UvzZVlXkFgFIdWldBuBF3v98diBWOk3Hmt9zJ945lp/daLc7se/u7WPm5vn4vrid69uKaPr3a12E4UmCIMRkERBkVlEARA4AAFv9tCn/NerWqoMwsNvXKspadmth7RttvVvgdVPIZ/jncurOs/vn1NcWzHZpuYxwmEUlEhzJ2U5U5J7uS85L1XFFhFYXF0XrMaqlkJNVEL1KiEqsehGuWGyVFoFFmjIDSyxijYdD99eY+d98pzrzT3SjOvJM/V6Tt1k0ydQaa1Xq72IFO7nxUbHGdeae5kjJE1UhxYhUFR3RvODd0vge/28NfPnJLE6fe/tKBXjrfueDb3uo3cXhWUpEtLPb1zcV2fXutovZ/JGrMlDFIZBAEQ2G+Bb/jFS0kZ+jLnNVULdWK+oRePNHVqvr7l/zMumxZfXu7p//Ozq+qnxark/b4Vhi2D1fD0POfK//nirNnMFVXcYuWo3xgiN8PQZ01xX6UtCdCXv5/PvXIV4XL4HzIyMqYIFKEtAp41RVVvo7I3fG72eYiwpticuhoF+sdfPayj07WR/vPebQWxJJ273tX7V9o6f72jlV6m0BZhMA7KG0plEARAYHxDn7FFkNsY3nVFpe/kfF0vPdXSqUP1OzoLafy2Hxmkuf7dT6/o/M2+ZhrhRqd3IEO+7qxCPWo4sw/4fQ5iODCSvJFWOplOzFb1T7721JY5sePgXu373I2u3ru0rs+ud7XezxTYW5VBa1hAAgIgMF6hL3XqZk7eeU02Ip2YreuFIw2dmm9sqQaMa+jbyCKbttr43js39LNzK2pWgrE4Pg5j0kmUZ/q2B7m+enpKf//lQ3c8e+Pmbu3eeenc9Y4+uNLR+ZtdrXZSGWtUD62iiDAIAiAwcqFvYyHHMPTlXlONSKfm63rxaFNPz+2PSt/9OrPhz/Lh1Y7+4u1rSnN3IIaEscPtqxzyjQKr3//Sgp473LjjmdsP7edunwefLXb1weW2Prve1XInlQluhUEWkIAACOxVx3T76l3nNVWPdHqhoRePNnV8tnbXD/lx2Ez4sTuy4sfTei/Td39+VZ8vdTVRjYstR2jleJSOwRSLbtb6iZ6ebegffXlBrVo4Mgs9dqr96B5h8PzNnj643NbZax2tdNMtw8QsIAEBENiF0Ge8lObFqRy585qohTo939CLxyZ0Yrb6UG/2+9nmYbm//WRZ3//wpkJj1ahYqoF4uHZmpM7AKfNOv/n8rL7xzPQdz9ZB4O8ZBvt6/+Kazl7vaK1XzBmsx6GioJgnSRgEARDYjs5Ixby+vDyVY5DmalZDnZyv6QtHW3pmobF1w94DGPru1nENf/6ra4n+4hfXdHVtoIlqqMCKIIh7Br/cFUe6HZ6s6P/y5QXNT8R3PFMHtU3d/rniJX1yraNfX17XZ9d7avczVcrTRwJOHwEBEHjMzmjzvL7UyVrp2HRNrx6f0AtHmwo3bfJF6LtXr6WN8bo3PljSjz5eUhBYNakG4i7hrz1wynOnbz07o++8MHPHM4R7f95kudcHl9v61YU1XbzZk5NUj27NF6QqCAIg8ABBWe3rJpnSzGu6GenFoxN65XhL043ojg/h/Tynb7s6q2FHdX090f/vV9f1+WJPrVqoODDKaf0Hu70ZKcm91nqZnp6r6R++Oq9DLap+D/t+dbc5g8udVO9cWNf7l9e03E4VhcUQ8fCzDSAAAls6IqMk9+okmayXjs/V9NrJKT13pHHn2zeh7/F6q/KivXluVW98eFODzGmiEsqwSOTgffCXW5qsDTJVQqvffH5WXzk1ecezgkcLg7cH5o+udPTWZyu6sNiTM1IjHr540eBAAATBT0meqz1wqkdWX3iqqa+emtZ081a1b1xO5Rj5TmpTB9VPc/3Ve4t67+K6Ais1K6HkmbO031kV4a49yJQ76aVjLf3OS3OqRsEdzwgev53dfvrIcjvVz84t69eX2uqmTs1KcUQhQRAEQBzI4DfIc633nSargb50YlJfOz2tODJ3DSzYmSB4eXmg//T+DX1+s6dGHKgWBXLeiw+FffZBL8kao16aq5PkOjlb02+9eEhHpyu0tV1qa5KUpF4/Pbust8+varWfq1W1qhAEQQDEQQl+SebUTjK1KqG+dmZar5+e2nhbZkHHLnVMKrbUGQ71fXC5rf/ywaKW1lM1qoGqYbFQhA+H/RD8pH7m1ElyzdUr+s4LM/rCU82NB8EzpWJXguDmzzXnpTfPruinny5rfZCpGYeKQ0sQBAEQ+/BBK1fCrfUzNSuBvnZmWl+9PfjREe15heIX51f1o4+WtNbNVa9aVcsj5RgaHi+2bHP9zKnTd5qsB/rWczP68onJe9577M6L1+a5gs5LPyuDYHuQa6IabuyAABAAMfYVCJnidAprjb5yclK/+cKsgjL5EfxGLwh6ST/9dEVvfbaslXauesWqFll5sYfgyAe/si31UqfuINdUM9brJyf1tTNTBL8RDoK58/r+Bzf1889W5ZxXq1bMyaW5gQCIsRQYo3455+i5ww39/VfmNVkLN958DcFvpIOgJP383Ip+cm5Fy+1U1ThQjX3NRjP4lVWjXurUT3LNNiO9fmpKr50i+I16EPSbTlhZ7WX63jvX9dHVjhpxoGrE/EAQADFOD5WKeUVr3UytaqC//8r8xiHyzDkav05Jkt672NbPzi7r8nJfUVTsaxZy2sHehj4Vp+Rkw30zU6+nZqt6/eS0XjrW3Pj3eNkajza3eU7uR1c7+t4717XezzVRD2WoBoIAiFEXlPOOukmuLz09qd99dX7LPD8qEOPl9vNfP73e1dvn13TuRkdp5lWLrSpUBXc3+JXVvkHq1EucotDo1KGGvnJiQqfm6/e8dxiDIHjb/MD/81fX9fbnq6rHxcIsNm4HARCj2TGZ4hzRehzo97+8oNOH6gS/fdgxScVinrc/W9GvL7d1s50qska1OFQUFBVewuD2hz7jpdRJvUGm1HnNNiN94WhTXzo5pYlqeM97hfFub+dudPUffnFN3STXRC1kHi4IgBihh0jF8MRKL9Wzhxr6R68fURyWizzE0NN+DoKS9PG1jt75fF3nb3bVS3PFQaBabIshYhEGnyj0qRji7SVOSZqrVgl0Yq6uV4+39MxC44H3BmPc1jZ9diaZ13ffvKKPb3Q0VYs2PnMBAiD27gEyUpoVR7h9+7lZfef54hB5hp/2fxC8/bSDJPX64Gpb71xY09WVvgapUyUKVAmtwmGBijmD9w58G1+kLJMGmdMgzVWJrA5PVfXKsQm9cKS5ZbN0TsnZ/zZ/lr7x4ZJ++NFNNeJQUWjYLgYEQOyNwEi9zCnNvP7wtcN6plzoQSXi4IXB27fy6Q6cPri8rg+vtnV1daB+kiuwRpXQKgqtgrI6eJAD4TDwGUm5k9LMaZA55c6rGgc6PFnR84ebeuFoS/WK3Xq9CX0Hro0N7/cnVzv6929dVRQa1ZgXCAIgdv3BMcWwlDHSH3/rKc1PVLgoB72TKqsVwW3BZJB7nb/R1UdXO7pws6v1XnEObRhIlcgqsrZY2LDPA+HmwOeclDqnQeqU5VJgpVYt1NOzdT17uKETh+qq3HYhc39rnz8cbNfXBvq3P7qk3Eu12FIJBAEQuxf+ugOnamT0z37jmCbqEVU/3FGxcLozDErSUjvRJ9e7urTU15WVfhkIvcLAKA6twrCYP7hlntMYBcPNQ7nDnyFzUpY5JZlTlnsF1miiFurwVFXHZqo6M9/QTDO64/fK/a1TPYBh2zJGWuul+l/+5qL6iVe9QggEARC7Ev6Kyej/9+8cVy0OmO+H+3dYKucx3SPI3FhPdHVloItLPV1eHmi1m2qQ55IzsoEUWqsoLL4PF0Zs/r3ld/+EEmt0x7D3cMFL5pzSrPju8iIMVgOrVj3QU9M1HZ+paWGqokOt+J7BmUof7mf4mdsdZPp//eCSumlOCAQBEDsc/hKnehjov/vNY6oT/vCYFQynewfCQZprqZPo6mqia6sDLbdTLXdT9dJcSeblnZexRtZIoTWy1iiwklUREDcPtW5XgB1WIJ2TnJxyJznnlTkv51X8mYxRHBnVokDTjUjTjUgLkxUdnqxqphGqEgWPfC2AB4bAJNO/+v4l9bNcdYaDQQDEToS/fuZkJf33f/dpNSoh4Q+7EgiHukmutV6mlU6q5U6qlW6q9X6mdj9XL8mU5F65K/+X+40TZ0z5m5qNL/dPe37jz+U3TmgIAqPAFv+LA6t6JVCjEqhVDTVVjzTTjDRZjzRRC1WPgyf+WYFHCYHtfqZ/+f3P5SRVQ0IgCIDYxvCXZl5J7vTPv3Ncc62Y8IcdDYTSowelzHn1k1y9tFhcMcjy8rtTlnmlzinNnHJv5L3bCHpFSLQKjFcUFotSwrBYsVyJrCphoEpkVYusqnGg8CEf/M1hTwzpYodD4OJ6oj9544LiwLJFDB5KyCXAAzsy59VJcv3xN49qrhXfcU4ssN0vHJIU3CcY6i7BKrRGzWqoZnWX2kX5ZcufZ9Of35g7fwZgu1lTtI25Vqz/29eO6E9/fFmTNqDEjAc/O1wCPOjDZaWb6XdfmdPTc/ViSIzPFexRMDSmWFkclH99+yIM72/9Ly8XhzzJ/3K/9ffcXFQZbsC85c9D28AetQ0v6em5uv7BK3Na6Wa8pOOBqADivuFvuZvpKycn9ZWTUxzrhtHuBLX1AaX6hgP3/Et67eSUrq8mevvzNU3XOTsY9+njuQS41xtlZ+B0eKKif/jFeS4IAIy4Ydb7vS/O6/BERZ2BoyoNAiAeTea8vLz+6OtHig8WT/UPAEb6xV235sr+0dePyKvYqgggAOLhHgojrfUy/d6rC2pWiyEE3iIBYAxCoCnmrzaroX7v1Xmt9ZgPCAIgHkJgpNVepi8cbemlY015seIXAMbtJd5LeulYS1842tJqL7vrsYwgAAIbBplXLbL6g68scDEAYMz9wVcWVIusBhlDwSAA4j5vjeuDTL/76rxCa5j3BwBjajgfMLRG/+DVea0PGAoGARB3+7Aw0no/07MLDT1/pLnxawCA8f1cl6QXjjT13HxD6/2Mz3UQALGVc8WZqb//pWLLF44RAoDxN/ws/70vzcsYI+e4JiAAojRc+PGNM9NqVlj1CwD7xeZVwd84M82CEBAAUX44SOpnTlP1UN9+fqZ4KPhwAID909GXn+nffn5GU/VQ/cwxvxsEQN4Opc4g12+9MCdJHBsEAPvQ8LP9N1+YU2eQM8oDAuBBfyvsJk5Hp6r6wrHmljdFAMD++ryXpJeONXV4qqpu4vi8JwDioPKS+mmu33xhtvh7qn8AsH8/88vP+N96YVb9NBcf+QRAHNC3wd7A6cRcTafm65JY+AEA+9nwM/7UfF0n5mrqDagCEgBx8N4EJfWzXN9+bmbLmyEAYB9/9pef9d9+bkb9jCogARAH66aX1b/j0zWdmKP6BwAHxfCz/sRcXcenqQISAHGw3gBVVP9+44VpSaz8BYCDZPiZ/xsvUAUkAOJA3fBB6rQwWdXpQ43i13j7A4CD0w+Un/mnD9V1ZDLWIKUKSADEvmeM1E1yfe301JY3QQDAwTH87H/99Iy6Sc7G0ARA7OvwJ2mQO03WQr1yvLXlTRAAcIA6//Kz/5XjLU3WQg1yTgchAGJfN/jOwOnV45Nb3gABAAfPsA949fikOiwGIQBi/8qcFAVGr52akiTe9gDgABv2Aa+dmlIUGGWOa0IAxP670VbqpJnOLDRUr1h5z9YvAHCgA6Ap9gWsV6zOzDfUSTNZUgEBEPuL91KWeb12ckKSxIseAGDYF7x2akJZ5jkUgACI/XaTB6nTXKuip2eLjZ8Dqn8AcOAN+4KnZ+uaa1WKLWG4LARA7A/GSr3U6aVjxcpfFn8AAIaGfcJLx1rqpU6GZEAAxP6QOSk0Rl8st36h+AcA2CgSlN+/eLyl0LAYhACI/XGDrdRLnI7NVtWshkVjJwECAIYBsOwTmtVQx2ar6iWOxSAEQIx9w/ZSkuV6+Vix+CNn+BcAcJth3/DysQklWS5DX0EAxHhLc6kWB/rC0WZxw6n+AQBuDwNl3/CFo03V4kBpzjUhAGJ8b66Vemmmp2frCgMjL+b/AQDuZCR5SWFg9PRsXT32BCQAYowbtJfS3Oulp4rqH6t/AQD3srEa+Kmm0twzDEwAxLhKc6leCfTs4UZxsyn/AQDuFQjKPuLZww3VKwwDEwAxnje2HP49PlNVYBn+BQDc33AYOLBGx2eqDAMTADGuDTnNvZ4/wubPAICHM+wrXjjSKoaBuSQEQIyX1EnVyOqZhTo3GgDwSKHg2YW6qpFVyqbQBECM0U210iBxOjJZVTUKJLH5MwDgwYZ9RRwFOjJV1YBNoQmAGKMGLCnJnc4sFIs/2PwZAPCwhn3GmfmGktwxDEwAxNg0Xlfc2GfLAMhNBgA8ajB4dqEhW/YpIABiDG5okjnNtGJNNyNJDP8CAB7esM+YbkaaacVKMkdYIABi5BuulfqZ04nZmiRW/wIAHt2w73h6tqZ+5mRICwRAjD7vvM7MF6t/yX8AgEfuR8rvz8zXlVNJIABi9KWZVI0DnZgrt39h+BcA8KjhoOw7np6rqxYHSjOuCQEQo3szrTTInBYmYoVB0XrJfwCARzXsO6LA6PBERYOM7WAIgBjpBpvmTk/PFtU/tn8BADyufNM8wJTtYAiAGF3eS15eJw9x+gcAYHsCwqlDdXl5eYoKBECMpiyX6nGgo9PV4hd4XQMAPK6yDzk6XVU9DpTlXBICIEbvRpbz/+YnKhuTd8l/AIAnzH8yRlpgHiABEKPbUNPc6dhMsf8f8/8AAE9q2Jccm2EeIAEQI2k4/29j+xcuCQBgm0LCiTnmARIAMZKyXKpGgY5OV4pf4DUNAPCkyr7kyHRF1Yh5gARAjNZNtFKSO821YoWW/f8AANua/xRao7lWrCRnHiABECPVQJPc6dhMsfqX+X8AgO2yMQ9wuqqEeYAEQIxYA3VeT5cLQAAA2G7HZ2qcC0wAxGiFPykOrRYmK9xUAMCOBIXDUxXFoVXuuCYEQIzEDUwzp8lapGY1lFTs2QQAwHYY9inNaqjJWqQ0c4QHAiBG4Q4mudPCRCxJLNEHAGy7Yd9yaKJYCEJ6IABir9/MJGVOeqo8/o3KPABguw37lqemq8ocO00QADEib2VeT00z/w8AsLNh4fh0RWJDaAIg9l6WS7Uo0KHJogLIaxkAYNuVfcuhyapqbAhNAMQe3zwrpc5psh6xATQAYKfzn0JrNFmPlDo2hCYAYk8bZJI5zZfbv1CSBwDslGEfMz9ZUZKxITQBEHvKeenoVBEAWQACANix/qb8fnSqIvaDJgBiBN7GjkxVuZkAgF0JDEcmqlv6IBAAscuyXKpGVnONYg9A6vEAgB1T9jFzrVjVyLIQhACIPblx5QKQ6XqkMGQBCABgV/KfwtBomoUgBEDsnSRzmuMEEADALhn2NXMTsZKMmecEQOzJm5jz0uEJFoAAAHbHsK85PFEsBGHkiQCIPXgL8/JamGQBCABgd0PDwmRVXl4MPhEAsdtvYV6qhFZzrYiLAQDYVXOtSBVr5Rh+IgBid29amjk140i1OJAkGerwAIAdNuxranGgVjVSmjuCBAEQu3nXktxpbiKUJErwAIBdM+xzZibCYiEISYIAiF16A5OUe+lQq5j/x47sAIDdMuxz5ltV5SwEIQBilxug81qYjLkQAIA9sTAZy1GBIABi9+ROCgOjQ62YmwgA2JPgcKgVKwyMchaCEACxO5yTKmGgaY6AAwDstrLPmW7EqkQBK4EJgNiVG1YeATdVjzZWY5H/AAC7nP9kjDRVK1cCkyYIgNh5SeY0W+7/xxFwAIDdNux7ZluREsaACYDYnTcv56UFjoADAOyRYd8zz5FwBEDs0luXJO+9Dk2wAhgAsLcOT8byniPhCIDY+bcuJ8Wh1VyTFcAAgL0ND7ONWHHIkXAEQOz4zcqcUz0O1KwWp4BwBBwAYLcN+55GNVQ9DpQ5joQjAGJH71aaSTONiGsBABgJM81IaeZJFARA7Ngbl4otYObK+X85ky4AAHtk2AfNNWOlzrMQhACIneS818JElQsBABgJC5NVOfYkIwBi53gvGZmNFcDcPADAXgeIQxOxrDfsS0sAxE7JvFQJrKbqIRcDADASpuuh4tgqIwASALEzNyrPnBq1UNUokMQKYADA3hn2QZUoUKsSKs9YCUwAxI7cqcx5zZbVP160AAB7bdgXTddDpY6VwARAbP+blqTUec22yiPgSIAAgD027ItmJyrKWAlMAMQONTTntTDJEXAAgNGyMBHLUZkgAGL7eSdZazTbYgUwAGC0QsRsqyJrjTxHwhEAsb0yJ1VCq5l6WQGkzg4A2GtlXzRTj1QJrTICIAEQ23uTcufUqgaKQkP+AwCMUv5TFBq1qoFyzgQmAGJ771KSe02XZwAzywIAMCo2VgI3IiU5K4EJgNjWN6zce800WAEMABgtwz5pplFR7lkJTADENjcwr7kWK4ABAKNprhVzJjABENupOANYmmlF3DQAwEgGiZlWJFP2WSAAYhs4L8Wh1XSNM4ABAKNpuhYqDi3TlAiA2A5GUuacqmGgeqUIgJwBDAAYmX6q7JPqlVDVMFDmHPMACYB44oZlpSyXJutU/wAAo22yHirLi74LBEA8SQCUlObu1hYwlNYBACNm2DdNNyKlORVAAiC2hfPSbLNYAcwm6wCAkeunyu+zzZg5gARAbF8A9Do0wRYwAIDRdmiCrWAIgNgWuZNCazRVYwsYAMBoh4mpWqTQGnmGqwiAeDLOFVvATNSLAMjECgDAyCn7pol6pDi0ygiABEA82c1x3qkWWUWBIf8BAEY5/ykKjGqRlfOOgEEAxJPcndTpVvUPAIARN1GLlDoSBgEQT/RGleVOE+UJIMyrBQCMqmEfNVEPlbEVDAEQT96gZhtsAQMAGG3DPmqmEVOwIADiiRuU95puMgQMABgPM42IrWAIgHgS3ktWRlN1toABAIxHoJhqRLLGUAUkAOJxOS9FkdFEjQogAGA8TFQDRaHhRBACIB5X5pyqoVU9Lm6TYUYtAGBEDfuoeiVUHFrljpnrBEA8+o2xxSkg9UrIxQAAjJVmJVTmir4MBEA8oiz3mqgFkiQq6QCAUTfsqyZqgbKcnosAiEdmVKwAblWL+X/MpQAAjLphX9WqFiuBmblEAMRjNqTpcgUwjQgAMOqGfdVkPaJwQQDE4/Lea6JengLC5QAAjHq/VX6fqofy7ANDAMTjNSJjjCbZAxAAMGahYrIeyRhD8YIAiEflnBQFRs1KwMUAAIyVZiVQFBixEwwBEI8VAK0a1XIbGCYBAgBGXdlXNaqhosASAAmAeNSbkjunRsVu5D7yHwBgTPKfjKRGpdgMmqBBAMQj3JXMSQ02gQYAjKlGuRk0SYMAiEfgnNsIgCykAgCMi2Gf1aiEcowBEwDx8IykXFKrnP9H8wEAjIthn9WshsrFFCYCIB75DapVDTYCIQAA42DYZ01UA0awCIB49ADo1aqxCTQAYMz6r/J7q8Zm0ARAPHLjMUZqlgGQmwQAGLdg0ayFMoYiBgEQD805KbRWjYhNoAEA46kRBQotewESAPFoATAwbAINABg/mzaDDjkNhACIh78hTk5xYBQFhvwHABjH/KcoMIoDI8deFgRAPFzLyZ1UZxNoAMCYq8WhcidZKhkEQDw4ADrnVYu5NQCA8VaPyzmABEACIB7Mea9axCkgAIDxNOy7anEg5xkCJgDigYwk57VRAaTZAADGzbDvKgIgBUACIB76zalZrgCm0QAAxs2w72pWQ0ayCIB46AAoqVHh1gAAxlujYtkImgCIhw6A3qsRcwwcAGBM+7FhAIw5Do4AiIduNMZItWrADQIAjHW4qMWBjKeYQQDEAzknBdaoFnIMHABgvNXiQEHIaSAEQDyUwBpVYwIgAGC8VeNAAbtAEwDxYM5JoTWqRuWtod0AAMZN2XdVI6vQUgEkAOKB7cXJKbB249gc8h8AYEzzn6yRAmvl5OjPCIC4X4PxTqpGNBMAwP5QjYy8o6BBAMR974bzUhww/w8AsD/EQXEaCImDAIj7cN6rQgUQALBPVCIjx16ABEA8OADGUVEBpL0AAMbVsA+Lw4AASADE/RgVQ8DVsLgtLJoCAIyrYR9WjaycZw4gARD3f2OSNvYApLEAAMaV2QiAASeBEADxwADopVrEbQEA7A+12DKliQCIh2osBEAAwD5RoU8jAOLBvPeqRGwDAwDYH2pRIE8JkACIBwRASVHI7D8AwP4QhYY5gARAPCj8Gd3aCJoGAwAY5z5NZZ9m6NMIgLg/Y8xGBZCbAwAY94ARhUbGMLJFAMS9ueHB2TQUAMD+EFkja8TmtgRA3Cf/yRqjiAAIANgnAmtkjSH/EQBx3xtiWQQCANg/otDIkjYIgLg354oKYGjLbWDIgQCAcVX2YaENigogJUACIO7TXgwVQADA/lEsAuE6EABxT15FBXA4BZD2AgAYV8M+zJqib2MbGAIg7tlQnAJekwAA+0xgij4OBEDchfcSC4ABAPuNKSuAdHEEQNy1hbBTOgBg//Ge8EcAxN0bR/lmlHNgNgBg3wVAv9HXgQCI2xhZOec3GggNBQAwtqGv/O68lHkvQ+QgAOIeAdBKuZMGaU4CBADsiwQ4SJ1y52VIHARA3CMASsqcU3fASikAwP7QHWTKcs8cQAIg7iWwUpp7rfZSSSyYBwCMr2EfttrPlDmvgMRBAMR9bogxWmwnXAgAwL5wY20gyx63BEDcm5cUWunKyoCbAwDYFwHj6spAoWVaOwEQ9+akSmB1ZbknSZydCAAYW8M+7PJyX5XIMq+JAIj75D9FodVyN9ON9WIYmG0BAQDjZth3XV8baLWbKQos+Y8AiPvekPKOvH9xvWhEXBIAwLgFwPL7+5fakuWYUwIgHih3Uj22evfiWnGDOB4OADBm4W8Y+N69sKZ6HCqn/EcAxINVAqvVfqaff7a69VUKAIBxSICS3vpsReu9TJWAS0IAxEPJvdSKQ/3NR0vFAdpUAQEAY5L9jCnmAP7NR8tqVkPldGAEQDy8ODTqJrn+4y+vcTEAAGPlz9++pl6SKw6Z/EcAxCPJvdSqhfrV52v61efrMqIKCAAYXV7Fkaa/PL+qdy+sqVWj+kcAxGO3plYt1H/85TWdvd4hBAIARjr8fXq9o7/41Q21aiEdFgEQTyIwRvWq1f/7p1f04eX2xmHa7A8IANjz4Ff2RUbSry+39e9+ekX1asDRbwRAbMdbVWSsGpVAf/bWFf3wo6WisRnJeV6wAAB70zc5f+u0jzc+WtJ337qiRiVQRPgbCyGXYDwaWmCMJquR3vj1ks7f6Or3v7yg6XokbWqENDkAwE73R94X+/wZIy13U/2HX1zThaW+JquRxK4VY8P8i++d416NEWuk9sDJyOsrJ6f07ednFAVF9NsoxZMEAQDbGfxu61/S3OuND5f0i3Mr8saoWbFypImxQgVwzDgvNSpWzkl/+8myfnVhVV87M63XT04p2rTc3nuCIADgyYOfMVuD35tnl/XTsyvqDpwmaqGsFeFvDFEBHGOBMUpyp/YgVz22evX4pL5yakKTteieb20AADwo9N3eb6z2Uv383Jp+dWFV3cSpWQkUB1Y5KxIJgNjLICgludRJMgXG6NShmr58YkpnFupb/r3cF6t+CIMAgNtDnyv7k80+vdbRW+dXdf5GT7n3asSh4sAQ/PYBhoD3gdxLgZWm66EyJ3222NXHVzuarId6+dikXj7W1Ewz3tKwfblpE1kQAA5o6Cu/DId4h0f2Lq4neu9iW+9dWtVqN1MUGtUroUIr5U6Ev32CCuA+ZG0R8NLcqTtwMpIOT1b04rGWXnyqqUYl3BoERRgEgIMU+qSto0Hrg0wfXmrrnYvrur42kJdUj62iwBbbjjmuHQEQ4xMEJRlbNNxe6jRInaLQ6PhMVa88PannDzcUWHNHGGSIGAD2WfC7y+d77rw+uNzRuxdXdWGprzTzqkRWtcgWhQRXDAtjf2IIeB9zG1+kesWqUbHKnHRhqaez17tqVAKdmKvrxadaOrPQkDUiDALAPgx9w89y54t5fe9eWteFxa7ag1xxaFSLQ7Wq5QbPrhjqBQEQ+yEMlo3ZSGpWizMas1z68Epb719aV6sa6tR8XS8da+nkXH1L8GOYGADGIPBtfNka+qRibvh7F9d17npX6/1MgTWqx6FmGlYyhL6DiCHgA87a4gMjyaV+ksl5r4lapOePNPTC0Qk9NV256xslYRAARi/0bXZxqacPLrX14dWO1vuprDGqxqHiQBuhDwRAYOvikcTJe6/JWqTT83W9cLSpk3P1u4dBMVQMALsW+u7z2fvZYlcfXG7r7LWuVvupjDEs5gABEA8ZBFUuHinDYD9xcs6rVQt14lBdXzjS1Kn5rXMGJfYZBICdDH1326fPeenT6x19eKWt8ze6Wu1lCq1RtQx91rCYAwRAPGYY1KbKYD9xyp1Xqxrq+GxNZxYaOj1fVz0O7vhQMhJDxQDwOIGv/OKlO162uwOnszc6+vRaR5/f7Kldzumrbqr0idCHB2ARCO5r80ri0FpN1O3GnMGPrrT13qV1VQKrI9NVnVmo69mFhmaa8dYVxWUgpDoIAPcJfWWVz5o7X6CX2ok+utrRJ9c7urY6KLb1skaVONR0I9qY0+f91iFi4F6oAOKxWVt8z53UT5yS3CmQNNOK9exCQ2cWGjo6Xb3j7ZWFJABw/wUczkuXlvs6e62jj691dHM9kfNSJbSqxFZB+fnLnD4QALHnYdCUYTDJynmDpjg38qmpik4t1HV6rqHpZnTH/3c4d5BACOAgBL67zeWTpOV2qnOLHZ291tWl1YE6/UxWxdBuHBahzxP6sE0YAsa22PyBVA2tarGVL/ca/OxmVx9f7yqwi5qux3p6tqpnFhp6eq6uKDB3fBCymATAvgl9mwLfcFh3OGM6c14Xlnr6+Eoxl2+pkyh3UmSlahRqphHJbFrEwT592E5UALHj7qgOZk7eeVXjQLONWCcPVXX6UFNHZ+4yXKxb8wepEAIY6bBXftkyj2/zi7KXLi/39NmNnj5b7GpxPVE3yWWtUTWkygcCIPZzGFSxxYyXlGVSkjslqZM3XvU41OHJWCcP1XV6vqFDrfiuH7AEQgCjFviCe3wY3VhPdPZ6R5/d6Or6aqJ2ksl4o7gMfGFYfI6xVQsIgDhYgbCsDg6HiwdZriTzslZqVkIdnop1fKamE3N1LUxW7vp7bMwhFMPGAHYw8JW95f0C37XVgc4vdvX5Uk/XVgZqD3I5J0WhUTUMFARFdZAqH/YacwCxpzZ/AForNaqBmuWvp87p3I2uPrrSldFNNWuB5icqenq2plPzDS1MFBXC4C6rjJ2YRwjgyQPf5s+S4efJ5l1Pr60lOne9o8+XerpeBj7vi8AXh0YT1bA4ZUm3tmnJKbtgBFABxOg+nCqGi41unUqSZF5p5mWs1IgDzbViHZuu6fhcVYcnK6pGwX0/xBk2BnDXsFd+ud/LYz/NdWVloPOLfV1a7mmpnaiT5PJOikIpDkNFmyp83m3s8gKMHCqAGOkPZL+pQhhaq7haBkInZU66vDzQ+Rs9uY+8qpHVVCPWU9NVnZit6ehMVRPVUMZsfWMnFAJ8ttwe9m5foStJa71Ml5f7On+zp0vLfa10EvVTJyujqJzDN0mFDwRAYOdtHjIOrNSoWhnZYlGJk1a7qW6sDfTWuRXFodVEJdChyaoOT8Y6NlvX/GSkShA8MBQydAzso8D3EGFvkOe6vpLq4lJPV1YHur7a13ovV+qcAlsu2ogC1StBMW95GPjE9iwgAAJ7GgitpFpkVY/txodzL3X65FpbH1yWZG6qGgWarEV6arqi47M1HZqoaK4VF8PNdwmFwzd5QiEwXmFPujU/+Pa27SUtrie6sTbQhZs9XVoeaLWXqpfkMjIKAykOrRrVQNYGGwvVnGfhBgiAwGgGQq8tk26GxyZtrDT20mov1eL6QG+dW1UQGNWiQDPNSIenKnpquqaFiVgzzbsvMCEUAuMV9qTiHN1ra4ku3Ozp2tpAK+1U3TRXnnuFQTGcG5Ub2A+reyq3ZSHwYb9iEQgOHGu0Me/PuXKD6rw4y9jlXqE1alRDzbUizU1UdWy6ooWJiqYa0T1/z82hkDmFwDYHvfLL7WHvbpbaqa6vDXRpqafFdqLF9VSdfqbMednAKA6s4qDYcHk4d09ldQ8gAAIHLRTaW6Etd1LmnNLMK3VeznlFgVUjDjTbijQ/WdHx6ZoOTVY0WQsfWJ1gj0LgEcLepr32HlRlX+2lurGa6MJyT9dXB1pcT9Tp5xthL7JGUWgU2iLwDcMkVT2AAAjcPRCWX+4bCq1VvVKsPF6YjHV4qqr5VkWzrfieFYrhSSYb/w2qhTioQa/8Msxi9j5tIffS4vpAN9YTXV3q69p6opVOou7AKXVO1hL2gEfFHEDgLtzGl1viTdvQDDuWzDldXRnowlJPLl+R3TSncK4Z61CrCIazzXhjftHdwuHmuUzMLcS+C3t3eb7vthJXknqJ0812oqsrfd1YT3SjnWi5naqX5nL5sLJnFYXaukijbLNOrMoFCIDADofCW3sTFiWH4ZzCxbVEl5f75TYRXpWoGEKea8aan6zq8FRF8614Y17h3Sau363jpGKIkQ155Ze7vcjc6/le6aS6vp7oynJPN9aTYgg3yTVInYyMrJXiwCoKbu23J22t7FHhAwiAwN4Ew9s6IGulWmhVL0PhsLMaZE7nFnv65EZ3Y15hJSo6tplmrEMTsRYmK5ppRpqsEQwxXkHvXhU9qZirt9ROdW11oBtriZbaiVb7mQapU5oXQ7iBKY5Oq0WBGuVee5vbD/vtAQRAYOxCoSRVAqtKtHVeYe6kpW6xavHdS5LzXrG1qlcCTTcjTdcjzTRjzU/Emq5HD6wYSretSCYc4glD3nB4dWOblfsEvZVOquVuqsW1RIvtRMudVMvlXL3EOVljFBopDK1Ca9WoBApscOu/ydYrAAEQ2HehcOPLLYGVotBKm/YfG84tvLJSbFJb7G3oFQ4rhrVIh1qRZlux5lqxWtVI041IUdlDP2gByvC/Q+WQkHd7yBsuxLhfyEtzr+VOqvV+WmymvJ7o5nqq1V6qQVpsp2SNkTVSGFhFQTFXr7V5rt6mkEdVDyAAAgczGN6lA4ytVRzemls4DIa5Kze1Xe0r90XFMCyPqapHoaYagWZbsWabsWabkVqVSBP1UIE191yAshEIbh9WJiDui4C3+b1jy7y8+4S83HmtdTOt91MtdcqKXifRai9Xd5ApyVyx1YoxCowUBVZhUFT0hkFv4z9PVQ8gAAJ4yFC4udfeZFgxrMne6mRdcQ5yP8t0cSnVucWevJd8WTWMA6NGJdBUrQiD0+V8w6lqpFY9VGiL3+l+w8obIfT2CiIhcSTC3e0VvM0BT7r7fc2c13o300o/1Y21RMvtRGvdTEu9VL1BriR3SvMi5BkjRdYotMUK3FrVymxakLH5RYagBxAAAexEOLxLB2utFGrrHMNh1dA5qTvItdbLlC36jSHlILCKAqNKaNWqhZqoRmrVAk03Is01K2pVAzVrmwKi7l9B3Agnm4YVdXtYJDA+MNBtDnWbr9/mrYEeFO6GAa/dy7TWz3WzPSiGbXu51vqp1nuZBlmxACPPvTQcsi1DXmit4tBu2SB9SzXvHi8oAAiAAHY7GN6jU7a22K6mYu8eDjPntLhW7LuWe8nnkje+HNYrjs6qVwK1KkERFGuRJuuhJmuRGpVAjWq4Mf9QenAl8W7BZ3PguWto3BR4RjU8+jv+4s4wt+Vnu0e17n6hbijNvTr9TJ1BrtVeqtVuprVeEezWB7m6ZQUvy73S3Ml4IxMUAT60VkEgRdaqcp+Qd6+XDQAEQAD7IRzKlp8E9q4BMfdOK12nxfVEzhcVRO+8TBksw6CoGlViq0YcqlGxmqjFmqgW4bAeW1WiQNXQqhpbVaNga6Z7hMD4oCB5t8C1XeHuQUPe5o6/eLgwN9RPc/UTp27ilOa5uolTp19U8NZ7iToDp3Y/Uz9zyp1Xlntlzsk7ydiygmeMbGCKqQLWqhJqY6PkLdmUkAcQALkEAOHwXsN5WwPinZUs54p5gd479fq52r1cuXPKfWdjHmIxN60IiYE1CgOjWmhVrQSqhEUgHO7/Vo2tapFVNQ7VrAaKAqsoNIqtURwECsO7R7uHGRLdDVnmleS5EueLYwNzp3Y/Vz/J1Eud+olTL82VZF79NNcgc+oPcvWyolqXO6/MeTnvi9W45fy7wEjWWoXl92Lofmu4I+ABIAAC2JWAKBULD2SsIquNQ5Rvj2kbYVGSd07dNFd7kJcVxbKqqGL+YFHN8zKmCI62rG4N/zqwxYbBlSBQEJTz1owp5jSG5UKFwCgMAgVWCoYhyhYnSwxXrppyFYP3bmNFdbHS2st7Kfe+OAM6z5XmRTBLM688d8p88fd5LiV5rkFWhDfnbv08w7/2XpIxZaArcurGz2OGfyYpjqxsGbrvdv1uD3aEOwAEQAAjHxS1kQ+tIknFl8Ld6nr3mo/mnFOvL3WUF/MHy8AlDb/fOR/P3zVQ+Y3/+u3//duHc83msKtbgVSmXKBhpUB2I2Te+lnv87MR6gAQAAEQFh8QHstgFajcgsTe/d/bqUUi/j4/jL/LP2elLAACIABsYxDzhCsAeCKWSwAAAEAABAAAAAEQAAAABEAAAAAQAAEAAEAABAAAAAEQAAAABEAAAAAQAAEAAEAABAAAAAEQAAAABEAAAAAQAAEAAEAABAAAIAACAACAAAgAAAACIAAAAAiAAAAAIAACAACAAAgAAAACIAAAAAiAAAAAIAACAACAAAgAAAACIAAAAAiAAAAAIAACAACAAAgAAEAABAAAAAEQAAAABEAAAAAQAAEAAEAABAAAAAEQAAAABEAAAAAQAAEAAEAABAAAAAEQAAAABEAAAAAQAAEAAEAABAAAIAACAACAAAgAAID96f8PIqCB0Bjeyr0AAAAASUVORK5CYII='; - -const testFactory = () => { - Object.values(AvatarSize).forEach((size) => { - Object.values(AvatarShape).forEach((shape) => { - it(`Avatar - size: ${size} shape: ${shape}`, () => { - const wrapper = mount(); - expect(wrapper.render()).toMatchSnapshot(); - }); - }); - }); -}; - -describe('Avatar', () => { - testFactory(); - - test('with Initials', () => { - const wrapper = mount(); - expect(wrapper.render()).toMatchSnapshot(); - }); - - test('Custom Size', () => { - const wrapper = mount( - - ); - const el = wrapper.find(Avatar).getDOMNode() as HTMLElement; - const computedStyle = getComputedStyle(el); - expect(computedStyle.fontSize).toEqual('2rem'); - expect(computedStyle.width).toEqual('5rem'); - expect(computedStyle.height).toEqual('5rem'); - expect(computedStyle.lineHeight).toEqual('5rem'); - }); - - test('Custom Size Defined but wrong size prop', () => { - const wrapper = mount(); - const el = wrapper.find(Avatar).getDOMNode() as HTMLElement; - expect(el.style.fontSize).not.toEqual('2rem'); - }); - - test('with Image', () => { - const wrapper = mount(); - const el = wrapper.find(Avatar).getDOMNode() as HTMLElement; - expect(el.style.backgroundImage).toEqual(`url(${sampleAvatar})`); - }); - - test('with Click Handler', () => { - const callback = sinon.spy(); - const wrapper = mount(); - wrapper.find(Avatar).simulate('click'); - expect(callback.called).toBe(true); - }); - - test('do not crash onClick w/o handler (#272)', () => { - expect(() => { - const wrapper = mount(); - wrapper.find(Avatar).simulate('click'); - }).not.toThrow(); - }); - - test('enter key down', () => { - const callback = sinon.spy(); - const wrapper = mount(); - wrapper.find(Avatar).simulate('keyDown', { key: 'Enter' }); - expect(callback.called).toBe(true); - }); - - test('other key down', () => { - const callback = sinon.spy(); - const wrapper = mount(); - wrapper.find(Avatar).simulate('keyDown', { key: 'ArrowLeft' }); - expect(callback.called).toBe(false); - }); - - createPassThroughPropsTest(Avatar); -}); diff --git a/packages/main/src/components/Avatar/__snapshots__/Avatar.test.tsx.snap b/packages/main/src/components/Avatar/__snapshots__/Avatar.test.tsx.snap deleted file mode 100644 index a9ad49fadf1..00000000000 --- a/packages/main/src/components/Avatar/__snapshots__/Avatar.test.tsx.snap +++ /dev/null @@ -1,94 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Avatar Avatar - size: Custom shape: Circle 1`] = ` - -`; - -exports[`Avatar Avatar - size: Custom shape: Square 1`] = ` - -`; - -exports[`Avatar Avatar - size: L shape: Circle 1`] = ` - -`; - -exports[`Avatar Avatar - size: L shape: Square 1`] = ` - -`; - -exports[`Avatar Avatar - size: M shape: Circle 1`] = ` - -`; - -exports[`Avatar Avatar - size: M shape: Square 1`] = ` - -`; - -exports[`Avatar Avatar - size: S shape: Circle 1`] = ` - -`; - -exports[`Avatar Avatar - size: S shape: Square 1`] = ` - -`; - -exports[`Avatar Avatar - size: XL shape: Circle 1`] = ` - -`; - -exports[`Avatar Avatar - size: XL shape: Square 1`] = ` - -`; - -exports[`Avatar Avatar - size: XS shape: Circle 1`] = ` - -`; - -exports[`Avatar Avatar - size: XS shape: Square 1`] = ` - -`; - -exports[`Avatar with Initials 1`] = ` - - JD - -`; diff --git a/packages/main/src/components/Avatar/demo.stories.tsx b/packages/main/src/components/Avatar/demo.stories.tsx deleted file mode 100644 index 602ff069308..00000000000 --- a/packages/main/src/components/Avatar/demo.stories.tsx +++ /dev/null @@ -1,59 +0,0 @@ -import { action } from '@storybook/addon-actions'; -import { select, text } from '@storybook/addon-knobs'; -import '@ui5/webcomponents-icons/dist/icons/employee'; -import { Avatar } from '@ui5/webcomponents-react/lib/Avatar'; -import { AvatarShape } from '@ui5/webcomponents-react/lib/AvatarShape'; -import { AvatarSize } from '@ui5/webcomponents-react/lib/AvatarSize'; -import { Icon } from '@ui5/webcomponents-react/lib/Icon'; -import React from 'react'; - -const sampleAvatar = - 'data:image/png;base64,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'; - -export const withInitials = () => ( - -); -withInitials.story = { - name: 'with Initials' -}; - -export const withIcon = () => ( - - - -); -withIcon.story = { - name: 'with Icon' -}; - -export const withImage = () => ( - -); -withImage.story = { - name: 'with Image' -}; - -export default { - title: 'Components / Avatar', - component: Avatar -}; diff --git a/packages/main/src/components/Avatar/index.tsx b/packages/main/src/components/Avatar/index.tsx deleted file mode 100644 index 07a76b67c52..00000000000 --- a/packages/main/src/components/Avatar/index.tsx +++ /dev/null @@ -1,117 +0,0 @@ -import { createComponentStyles } from '@ui5/webcomponents-react-base/lib/createComponentStyles'; -import { usePassThroughHtmlProps } from '@ui5/webcomponents-react-base/lib/usePassThroughHtmlProps'; -import { enrichEventWithDetails } from '@ui5/webcomponents-react-base/lib/Utils'; -import { AvatarShape } from '@ui5/webcomponents-react/lib/AvatarShape'; -import { AvatarSize } from '@ui5/webcomponents-react/lib/AvatarSize'; -import React, { CSSProperties, FC, forwardRef, Ref, useCallback, useMemo } from 'react'; -import { CommonProps } from '../../interfaces/CommonProps'; -import styles from './Avatar.jss'; - -export interface AvatarPropTypes extends CommonProps { - size?: AvatarSize; - shape?: AvatarShape; - initials?: string; - image?: string; - onClick?: (event: CustomEvent<{}>) => void; - children?: JSX.Element; - customDisplaySize?: CSSProperties['width']; - customFontSize?: CSSProperties['width']; -} - -const useStyles = createComponentStyles(styles, { name: 'Avatar' }); - -/** - * import { Avatar } from '@ui5/webcomponents-react/lib/Avatar'; - */ -const Avatar: FC = forwardRef((props: AvatarPropTypes, ref: Ref) => { - const { - initials, - size, - shape, - image, - onClick, - customFontSize, - customDisplaySize, - children, - className, - style, - tooltip, - slot - } = props; - const classes = useStyles({ customDisplaySize, customFontSize }); - - const cssClasses = [classes.avatar, classes[`size${size}`]]; - - if (shape === AvatarShape.Circle) { - cssClasses.push(classes.circle); - } - - const inlineStyle = useMemo(() => { - const internalStyle: CSSProperties = {}; - if (image) { - internalStyle.backgroundImage = `url(${image})`; - } - - if (onClick) { - internalStyle.cursor = 'pointer'; - } - - if (style) { - Object.assign(internalStyle, style); - } - - return internalStyle; - }, [image, onClick, style]); - - if (className) { - cssClasses.push(className); - } - - const handleKeyDown = useCallback( - (e) => { - if (e.key === 'Enter') { - onClick?.(enrichEventWithDetails(e)); - } - }, - [onClick] - ); - - const handleOnClick = useCallback( - (e) => { - onClick?.(enrichEventWithDetails(e)); - }, - [onClick] - ); - - const passThroughProps = usePassThroughHtmlProps(props, ['onClick']); - - return ( - - {initials ? initials : children} - - ); -}); - -Avatar.defaultProps = { - size: AvatarSize.S, - shape: AvatarShape.Circle, - initials: null, - image: null, - onClick: null, - customDisplaySize: '3rem', - customFontSize: '1.125rem' -}; - -Avatar.displayName = 'Avatar'; - -export { Avatar }; diff --git a/packages/main/src/components/Breadcrumbs/__snapshots__/Breadcrumbs.test.tsx.snap b/packages/main/src/components/Breadcrumbs/__snapshots__/Breadcrumbs.test.tsx.snap index 95aed61df7a..e4cd93f39dd 100644 --- a/packages/main/src/components/Breadcrumbs/__snapshots__/Breadcrumbs.test.tsx.snap +++ b/packages/main/src/components/Breadcrumbs/__snapshots__/Breadcrumbs.test.tsx.snap @@ -4,6 +4,8 @@ exports[`Breadcrumbs separatorStyle: 'BackSlash' 1`] = `
Link 1 @@ -15,6 +17,8 @@ exports[`Breadcrumbs separatorStyle: 'BackSlash' 1`] = ` Link 2 @@ -26,6 +30,8 @@ exports[`Breadcrumbs separatorStyle: 'BackSlash' 1`] = ` Link 3 @@ -36,6 +42,8 @@ exports[`Breadcrumbs separatorStyle: 'DoubleBackSlash' 1`] = `
Link 1 @@ -47,6 +55,8 @@ exports[`Breadcrumbs separatorStyle: 'DoubleBackSlash' 1`] = ` Link 2 @@ -58,6 +68,8 @@ exports[`Breadcrumbs separatorStyle: 'DoubleBackSlash' 1`] = ` Link 3 @@ -68,6 +80,8 @@ exports[`Breadcrumbs separatorStyle: 'DoubleGreaterThan' 1`] = `
Link 1 @@ -79,6 +93,8 @@ exports[`Breadcrumbs separatorStyle: 'DoubleGreaterThan' 1`] = ` Link 2 @@ -90,6 +106,8 @@ exports[`Breadcrumbs separatorStyle: 'DoubleGreaterThan' 1`] = ` Link 3 @@ -100,6 +118,8 @@ exports[`Breadcrumbs separatorStyle: 'DoubleSlash' 1`] = `
Link 1 @@ -111,6 +131,8 @@ exports[`Breadcrumbs separatorStyle: 'DoubleSlash' 1`] = ` Link 2 @@ -122,6 +144,8 @@ exports[`Breadcrumbs separatorStyle: 'DoubleSlash' 1`] = ` Link 3 @@ -132,6 +156,8 @@ exports[`Breadcrumbs separatorStyle: 'GreaterThan' 1`] = `
Link 1 @@ -143,6 +169,8 @@ exports[`Breadcrumbs separatorStyle: 'GreaterThan' 1`] = ` Link 2 @@ -154,6 +182,8 @@ exports[`Breadcrumbs separatorStyle: 'GreaterThan' 1`] = ` Link 3 @@ -164,6 +194,8 @@ exports[`Breadcrumbs separatorStyle: 'Slash' 1`] = `
Link 1 @@ -175,6 +207,8 @@ exports[`Breadcrumbs separatorStyle: 'Slash' 1`] = ` Link 2 @@ -186,6 +220,8 @@ exports[`Breadcrumbs separatorStyle: 'Slash' 1`] = ` Link 3 @@ -196,6 +232,8 @@ exports[`Breadcrumbs with currentLocationText 1`] = `
Link 1 @@ -207,6 +245,8 @@ exports[`Breadcrumbs with currentLocationText 1`] = ` Link 2 @@ -218,6 +258,8 @@ exports[`Breadcrumbs with currentLocationText 1`] = ` Link 3 diff --git a/packages/main/src/components/Carousel/Carousel.jss.ts b/packages/main/src/components/Carousel/Carousel.jss.ts deleted file mode 100644 index c0444ab33c0..00000000000 --- a/packages/main/src/components/Carousel/Carousel.jss.ts +++ /dev/null @@ -1,73 +0,0 @@ -import { ThemingParameters } from '@ui5/webcomponents-react-base/lib/ThemingParameters'; - -const styles = { - carousel: { - position: 'relative', - overflow: 'hidden', - boxSizing: 'border-box', - border: '1px solid transparent', - touchAction: 'pan-y', - minWidth: '15.5rem', - fontFamily: ThemingParameters.sapFontFamily, - backgroundColor: ThemingParameters.sapBackgroundColor, - '&:focus': { - outline: 'none', - '&:before': { - border: '1px solid #000000', - position: 'absolute', - content: '" "', - top: '0', - right: '0', - bottom: '0', - left: '0', - zIndex: '2', - pointerEvents: 'none' - }, - '&:after': { - border: '1px dotted #ffffff', - position: 'absolute', - content: '" "', - top: '0', - right: '0', - bottom: '0', - left: '0', - zIndex: '2', - pointerEvents: 'none' - } - } - }, - carouselInner: { - height: '100%', - position: 'relative', - whiteSpace: 'nowrap', - textAlign: 'start', - fontSize: '0', - transition: 'transform 0.5s cubic-bezier(0.46, 0, 0.44, 1)' - }, - carouselItem: { - width: '100%', - height: '100%', - overflow: 'hidden', - display: 'inline-block', - verticalAlign: 'top', - whiteSpace: 'normal', - fontSize: '1rem', - visibility: 'hidden' - }, - carouselArrowPlacementContent: { - '&:hover': { - '& [data-value="paginationArrow"]': { - opacity: 1, - '& ui5-icon': { - transform: 'rotate(0deg)' - } - } - }, - '& $carouselItem': { - padding: '0 4rem', - width: 'calc(100% - 8rem)' - } - } -}; - -export default styles; diff --git a/packages/main/src/components/Carousel/Carousel.test.tsx b/packages/main/src/components/Carousel/Carousel.test.tsx deleted file mode 100644 index 7fce648c002..00000000000 --- a/packages/main/src/components/Carousel/Carousel.test.tsx +++ /dev/null @@ -1,172 +0,0 @@ -import { createPassThroughPropsTest, getEventFromCallback } from '@shared/tests/utils'; -import { mount } from 'enzyme'; -import { Carousel } from '@ui5/webcomponents-react/lib/Carousel'; -import { CarouselArrowsPlacement } from '@ui5/webcomponents-react/lib/CarouselArrowsPlacement'; -import { Icon } from '@ui5/webcomponents-react/lib/Icon'; -import { PlacementType } from '@ui5/webcomponents-react/lib/PlacementType'; -import React, { cloneElement } from 'react'; -import * as sinon from 'sinon'; - -const renderCarousel = (props) => { - return ( - -

Carousel 1

-

Carousel 2

-

Carousel 3

-

Carousel 4

-

Carousel 5

-

Carousel 6

-

Carousel 7

-
- ); -}; - -describe('Carousel', () => { - test('Renders without crashing', () => { - const wrapper = mount(renderCarousel({ activePage: 0 })); - expect(wrapper.render()).toMatchSnapshot(); - }); - - test('Should render a text indicator', () => { - const wrapper = mount( - -

Carousel 1

-

Carousel 2

-

Carousel 3

-

Carousel 4

-

Carousel 5

-

Carousel 6

-

Carousel 7

-

Carousel 8

-

Carousel 9

-

Carousel 10

-
- ); - expect(wrapper.render()).toMatchSnapshot(); - }); - - test('CarouselArrowsPlacement: Content', () => { - const wrapper = mount(renderCarousel({ arrowsPlacement: CarouselArrowsPlacement.Content })); - expect(wrapper.render()).toMatchSnapshot(); - }); - - test('CarouselArrowsPlacement: PageIndicator', () => { - const wrapper = mount(renderCarousel({ arrowsPlacement: CarouselArrowsPlacement.PageIndicator })); - expect(wrapper.render()).toMatchSnapshot(); - }); - - test('Page Indicator Placement: Top', () => { - const wrapper = mount( - renderCarousel({ - arrowsPlacement: CarouselArrowsPlacement.PageIndicator, - pageIndicatorPlacement: PlacementType.Top - }) - ); - expect(wrapper.render()).toMatchSnapshot(); - wrapper.setProps({ - activePage: 1 - }); - wrapper.update(); - expect(wrapper.render()).toMatchSnapshot(); - }); - - test('Update activePage via prop', () => { - const wrapper = mount( - renderCarousel({ - activePage: 0 - }) - ); - expect(wrapper.render()).toMatchSnapshot(); - }); - - test('Navigation to next page', () => { - const callback = sinon.spy(); - const wrapper = mount(renderCarousel({ activePage: 0, onPageChanged: callback })); - wrapper - .find(Icon) - .last() - .simulate('click'); - expect(getEventFromCallback(callback).detail.selectedIndex).toEqual(1); - }); - - test('Navigation to previous page', () => { - const callback = sinon.spy(); - const wrapper = mount(renderCarousel({ activePage: 1, onPageChanged: callback })); - wrapper - .find(Icon) - .first() - .simulate('click'); - expect(getEventFromCallback(callback).detail.selectedIndex).toEqual(0); - }); - - test('Navigation to previous page - w/o Loop', () => { - const callback = sinon.spy(); - const wrapper = mount(renderCarousel({ activePage: 0, onPageChanged: callback })); - wrapper - .find(Icon) - .first() - .simulate('click'); - expect(callback.called).toEqual(false); - }); - - test('Navigation to previous page - w/ Loop', () => { - const callback = sinon.spy(); - const wrapper = mount(renderCarousel({ activePage: 0, loop: true, onPageChanged: callback })); - wrapper - .find(Icon) - .first() - .simulate('click'); - expect(getEventFromCallback(callback).detail.selectedIndex).toEqual(6); - }); - - test('Navigation to next page - w/o Loop', () => { - const callback = sinon.spy(); - const wrapper = mount(renderCarousel({ activePage: 6, onPageChanged: callback })); - wrapper - .find(Icon) - .last() - .simulate('click'); - expect(callback.called).toEqual(false); - }); - - test('Navigation to next page - w/ Loop', () => { - const callback = sinon.spy(); - const wrapper = mount(renderCarousel({ activePage: 6, loop: true, onPageChanged: callback })); - wrapper - .find(Icon) - .last() - .simulate('click'); - expect(getEventFromCallback(callback).detail.selectedIndex).toEqual(0); - }); - - test('Carousel with 1 child', () => { - const wrapper = mount( - -

Carousel 1

-
- ); - expect(wrapper.render().find('[data-value="paginationArrow"]')).toHaveLength(0); - }); - - test('Navigation to next page with Keyboard', () => { - const callback = sinon.spy(); - const wrapper = mount(renderCarousel({ activePage: 0, onPageChanged: callback })); - wrapper - .find('div[role="list"]') - .last() - .simulate('keydown', { key: 'ArrowRight' }); - expect(getEventFromCallback(callback).detail.selectedIndex).toEqual(1); - }); - - test('Navigation to previous page with Keyboard', () => { - const callback = sinon.spy(); - const wrapper = mount(renderCarousel({ activePage: 1, onPageChanged: callback })); - wrapper - .find('div[role="list"]') - .first() - .simulate('keydown', { key: 'ArrowLeft' }); - expect(getEventFromCallback(callback).detail.selectedIndex).toEqual(0); - }); - - createPassThroughPropsTest(Carousel); -}); diff --git a/packages/main/src/components/Carousel/CarouselPagination.jss.ts b/packages/main/src/components/Carousel/CarouselPagination.jss.ts deleted file mode 100644 index 9ef525114c4..00000000000 --- a/packages/main/src/components/Carousel/CarouselPagination.jss.ts +++ /dev/null @@ -1,103 +0,0 @@ -import { ThemingParameters } from '@ui5/webcomponents-react-base/lib/ThemingParameters'; -import { ZIndex } from '../../enums/ZIndex'; - -const styles = { - pagination: { - display: 'flex', - width: 'calc(100% - 2rem)', - justifyContent: 'center', - alignItems: 'center', - height: '3.5rem', - padding: '0 1rem', - backgroundColor: ThemingParameters.sapPageFooter_Background - }, - paginationTop: { - borderBottom: `1px solid ${ThemingParameters.sapPageFooter_BorderColor}` - }, - paginationBottom: { - borderTop: `1px solid ${ThemingParameters.sapPageFooter_BorderColor}` - }, - paginationIndicator: { - padding: '0rem 1rem', - height: '2rem', - maxWidth: 'calc(100% - 6.5rem)', - display: 'flex', - justifyContent: 'center', - alignItems: 'center', - width: '9rem' - }, - paginationIcon: { - textIndent: '2rem', - lineHeight: '0', - textDecoration: 'none', - overflow: 'hidden', - display: 'inline-block', - margin: '0 0.375rem', - width: '0.25rem', - height: '0.25rem', - transition: 'background-color 0.1s ease-in', - borderRadius: '50%', - alignSelf: 'center', - boxSizing: 'border-box', - backgroundColor: ThemingParameters.sapContent_NonInteractiveIconColor - }, - paginationIconActive: { - margin: '0 0.25rem', - width: '0.5rem', - height: '0.5rem', - backgroundColor: ThemingParameters.sapSelectedColor - }, - paginationArrow: { - boxShadow: 'none', - border: `1px solid ${ThemingParameters.sapButton_BorderColor}`, - backgroundColor: ThemingParameters.sapButton_Background, - color: ThemingParameters.sapButton_BorderColor, - height: '2rem', - width: '2rem', - borderRadius: '50%', - display: 'flex', - justifyContent: 'center', - alignItems: 'center', - cursor: 'pointer', - '&:active': { - border: `1px solid ${ThemingParameters.sapButton_Emphasized_Active_BorderColor}`, - backgroundColor: ThemingParameters.sapButton_Emphasized_Active_Background, - color: ThemingParameters.sapButton_Emphasized_TextColor - } - }, - '@global html[dir="rtl"] div[data-value="paginationArrow"] ui5-icon': { - transform: 'rotate(180deg)' - }, - paginationArrowContent: { - '& $paginationArrow': { - boxShadow: ThemingParameters.sapContent_Shadow1, - '&:first-child': { - position: 'absolute', - top: 'calc(50% - 2.75rem)', - left: '0.5rem', - opacity: 0, - zIndex: ZIndex.InputModal - }, - '&:last-child': { - position: 'absolute', - top: 'calc(50% - 2.75rem)', - right: '0.5rem', - opacity: 0, - zIndex: ZIndex.InputModal - } - } - }, - paginationArrowContentNoBar: { - composes: ['$paginationArrowContent'], - '& $paginationArrow': { - '&:first-child': { - top: 'calc(50% - 1rem)' - }, - '&:last-child': { - top: 'calc(50% - 1rem)' - } - } - } -}; - -export default styles; diff --git a/packages/main/src/components/Carousel/CarouselPagination.tsx b/packages/main/src/components/Carousel/CarouselPagination.tsx deleted file mode 100644 index 4dacbe225da..00000000000 --- a/packages/main/src/components/Carousel/CarouselPagination.tsx +++ /dev/null @@ -1,117 +0,0 @@ -import '@ui5/webcomponents-icons/dist/icons/slim-arrow-left'; -import '@ui5/webcomponents-icons/dist/icons/slim-arrow-right'; -import { StyleClassHelper } from '@ui5/webcomponents-react-base/lib/StyleClassHelper'; -import { CarouselArrowsPlacement } from '@ui5/webcomponents-react/lib/CarouselArrowsPlacement'; -import { Icon } from '@ui5/webcomponents-react/lib/Icon'; -import { Label } from '@ui5/webcomponents-react/lib/Label'; -import { PlacementType } from '@ui5/webcomponents-react/lib/PlacementType'; -import React, { Children, FC, useMemo } from 'react'; -import { createComponentStyles } from '@ui5/webcomponents-react-base/lib/createComponentStyles'; -import styles from './CarouselPagination.jss'; - -const useStyles = createComponentStyles(styles, { name: 'CarouselPagination' }); - -export interface CarouselPaginationPropTypes { - /** - * Defines where the carousel's arrows are placed. - * Default is CarouselArrowsPlacement.Content used to place the arrows on the sides of the carousel. - * Alternatively CarouselArrowsPlacement.PageIndicator can be used to place the arrows on the sides of - * the page indicator. - */ - arrowsPlacement?: CarouselArrowsPlacement; - /** - * Show or hide carousel's page indicator. - */ - showPageIndicator?: boolean; - /** - * Defines where the carousel's page indicator is displayed. - * Possible values are PlacementType.Top, PlacementType.Bottom. - * Other values are ignored and the default value will be applied. - * The default value is PlacementType.Bottom. - */ - pageIndicatorPlacement?: PlacementType.Top | PlacementType.Bottom; - - /** - * Index of the active page to be displayed - */ - activePage?: number; - - goToPreviousPage?: (e: any) => void; - goToNextPage?: (e: any) => void; -} - -const TEXT_INDICATOR_THRESHOLD = 8; -const CarouselPagination: FC = (props) => { - const classes = useStyles(); - - const { - arrowsPlacement, - children, - showPageIndicator, - pageIndicatorPlacement, - activePage, - goToPreviousPage, - goToNextPage - } = props; - - const numberOfChildren = React.Children.count(children); - const showTextIndicator = numberOfChildren >= TEXT_INDICATOR_THRESHOLD; - - const shouldRenderPaginationBar = useMemo(() => { - return showPageIndicator || arrowsPlacement === CarouselArrowsPlacement.PageIndicator; - }, [showPageIndicator, arrowsPlacement]); - - if (!shouldRenderPaginationBar) { - return ( -
-
- -
-
- -
-
- ); - } - - const paginationClasses = StyleClassHelper.of(classes.pagination); - if (arrowsPlacement === CarouselArrowsPlacement.Content) { - paginationClasses.put(classes.paginationArrowContent); - } - if (pageIndicatorPlacement === PlacementType.Top) { - paginationClasses.put(classes.paginationTop); - } - if (pageIndicatorPlacement === PlacementType.Bottom) { - paginationClasses.put(classes.paginationBottom); - } - - return ( -
-
- -
- -
- {showPageIndicator && showTextIndicator && } - - {showPageIndicator && - !showTextIndicator && - Children.map(children, (item, index) => ( - - {index + 1} - - ))} -
- -
- -
-
- ); -}; - -export { CarouselPagination }; diff --git a/packages/main/src/components/Carousel/__snapshots__/Carousel.test.tsx.snap b/packages/main/src/components/Carousel/__snapshots__/Carousel.test.tsx.snap deleted file mode 100644 index 4fc328f8606..00000000000 --- a/packages/main/src/components/Carousel/__snapshots__/Carousel.test.tsx.snap +++ /dev/null @@ -1,1059 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Carousel CarouselArrowsPlacement: Content 1`] = ` - -`; - -exports[`Carousel CarouselArrowsPlacement: PageIndicator 1`] = ` - -`; - -exports[`Carousel Page Indicator Placement: Top 1`] = ` - -`; - -exports[`Carousel Page Indicator Placement: Top 2`] = ` - -`; - -exports[`Carousel Renders without crashing 1`] = ` - -`; - -exports[`Carousel Should render a text indicator 1`] = ` - -`; - -exports[`Carousel Update activePage via prop 1`] = ` - -`; diff --git a/packages/main/src/components/Carousel/demo.stories.tsx b/packages/main/src/components/Carousel/demo.stories.tsx deleted file mode 100644 index 3c3f22ee32d..00000000000 --- a/packages/main/src/components/Carousel/demo.stories.tsx +++ /dev/null @@ -1,73 +0,0 @@ -import { action } from '@storybook/addon-actions'; -import { boolean, number, select } from '@storybook/addon-knobs'; -import { Carousel } from '@ui5/webcomponents-react/lib/Carousel'; -import { CarouselArrowsPlacement } from '@ui5/webcomponents-react/lib/CarouselArrowsPlacement'; -import { Label } from '@ui5/webcomponents-react/lib/Label'; -import { PlacementType } from '@ui5/webcomponents-react/lib/PlacementType'; -import React from 'react'; - -export const renderCarousel = () => { - return ( - - -
-

This is a larger content

-
-

This is a larger content

-
- - - - -
- ); -}; -renderCarousel.story = { - name: 'Default' -}; - -const renderCarouselWithOneChild = () => { - return ( - - - - ); -}; -renderCarouselWithOneChild.story = { - name: 'with One Child' -}; - -export default { - title: 'Components / Carousel', - component: Carousel -}; diff --git a/packages/main/src/components/Carousel/index.tsx b/packages/main/src/components/Carousel/index.tsx deleted file mode 100644 index c2fd588a8df..00000000000 --- a/packages/main/src/components/Carousel/index.tsx +++ /dev/null @@ -1,234 +0,0 @@ -import { createComponentStyles } from '@ui5/webcomponents-react-base/lib/createComponentStyles'; -import { StyleClassHelper } from '@ui5/webcomponents-react-base/lib/StyleClassHelper'; -import { usePassThroughHtmlProps } from '@ui5/webcomponents-react-base/lib/usePassThroughHtmlProps'; -import { enrichEventWithDetails } from '@ui5/webcomponents-react-base/lib/Utils'; -import { CarouselArrowsPlacement } from '@ui5/webcomponents-react/lib/CarouselArrowsPlacement'; -import { PlacementType } from '@ui5/webcomponents-react/lib/PlacementType'; -import React, { - Children, - CSSProperties, - FC, - forwardRef, - ReactNode, - ReactNodeArray, - Ref, - useCallback, - useEffect, - useState -} from 'react'; -import { CommonProps } from '../../interfaces/CommonProps'; -import styles from './Carousel.jss'; -import { CarouselPagination, CarouselPaginationPropTypes } from './CarouselPagination'; - -export interface CarouselPropTypes - extends Omit, - CommonProps { - /** - * The content which the carousel displays. - */ - children: ReactNode | ReactNodeArray; - /** - * This event is fired after a carousel swipe has been completed - */ - onPageChanged?: (event: CustomEvent<{ selectedIndex: number }>) => void; - /** - * The height of the carousel. Note that when a percentage value is used, the height of the surrounding container - * must be defined. - */ - height?: CSSProperties['height']; - /** - * The width of the carousel. Note that when a percentage value is used, the height of the surrounding container - * must be defined. - */ - width?: CSSProperties['width']; - /** - * Defines whether the carousel should loop, i.e show the first page after the last page is reached and vice versa. - */ - loop?: boolean; -} - -const useStyles = createComponentStyles(styles, { name: 'Carousel' }); - -/** - * import { Carousel } from '@ui5/webcomponents-react/lib/Carousel'; - */ -const Carousel: FC = forwardRef((props: CarouselPropTypes, ref: Ref) => { - const { - children, - height, - width, - pageIndicatorPlacement, - className, - style, - arrowsPlacement, - tooltip, - showPageIndicator, - loop, - onPageChanged - } = props; - - const [currentlyActivePage, setCurrentlyActivePage] = useState(props.activePage); - - useEffect(() => { - setCurrentlyActivePage(props.activePage); - }, [props.activePage, setCurrentlyActivePage]); - - const outerStyle = { width, height }; - if (style) { - Object.assign(outerStyle, style); - } - - const classes = useStyles(); - const classNameString = StyleClassHelper.of(classes.carousel); - - if (className) { - classNameString.put(className); - } - - const carouselItemClasses = StyleClassHelper.of(classes.carouselItem); - if (arrowsPlacement === CarouselArrowsPlacement.Content) { - classNameString.put(classes.carouselArrowPlacementContent); - } - - const selectPageAtIndex = useCallback( - (index, event) => { - setCurrentlyActivePage(index); - onPageChanged(enrichEventWithDetails(event, { selectedIndex: index })); - }, - [onPageChanged, setCurrentlyActivePage] - ); - - const childElementCount = Children.count(children); - const goToNextPage = useCallback( - (e, skipManualInversion = false) => { - if ( - document.dir === 'rtl' && - arrowsPlacement === CarouselArrowsPlacement.Content && - e.type === 'click' && - !skipManualInversion - ) { - return goToPreviousPage(e, true); - } - if (loop === false && currentlyActivePage === childElementCount - 1) { - return; - } - const nextPage = currentlyActivePage === childElementCount - 1 ? 0 : currentlyActivePage + 1; - selectPageAtIndex(nextPage, e); - }, - [loop, currentlyActivePage, selectPageAtIndex, childElementCount, arrowsPlacement] - ); - - const goToPreviousPage = useCallback( - (e, skipManualInversion = false) => { - if ( - document.dir === 'rtl' && - arrowsPlacement === CarouselArrowsPlacement.Content && - e.type === 'click' && - !skipManualInversion - ) { - return goToNextPage(e, true); - } - if (loop === false && currentlyActivePage === 0) { - return; - } - const previousPage = currentlyActivePage === 0 ? childElementCount - 1 : currentlyActivePage - 1; - selectPageAtIndex(previousPage, e); - }, - [loop, childElementCount, currentlyActivePage, selectPageAtIndex, arrowsPlacement, goToNextPage] - ); - - const onKeyDown = useCallback( - (e) => { - if (e.key === 'ArrowRight') { - if (document.dir === 'rtl') { - goToPreviousPage(e); - } else { - goToNextPage(e); - } - } - if (e.key === 'ArrowLeft') { - if (document.dir === 'rtl') { - goToNextPage(e); - } else { - goToPreviousPage(e); - } - } - }, - [goToPreviousPage, goToNextPage] - ); - - const translateXPrefix = document.dir === 'rtl' ? '' : '-'; - - const passThroughProps = usePassThroughHtmlProps(props, ['onPageChanged']); - - return ( -
- {childElementCount > 1 && pageIndicatorPlacement === PlacementType.Top && ( - - {children} - - )} -
- {Children.map(children, (item, index) => ( -
- {item} -
- ))} -
- {childElementCount > 1 && pageIndicatorPlacement === PlacementType.Bottom && ( - - )} -
- ); -}); - -Carousel.displayName = 'Carousel'; -Carousel.defaultProps = { - activePage: 0, - arrowsPlacement: CarouselArrowsPlacement.Content, - onPageChanged: () => {}, - height: '100%', - width: '100%', - showPageIndicator: true, - loop: false, - pageIndicatorPlacement: PlacementType.Bottom -}; - -export { Carousel }; diff --git a/packages/main/src/components/FilterBar/__snapshots__/FilterBar.test.tsx.snap b/packages/main/src/components/FilterBar/__snapshots__/FilterBar.test.tsx.snap index 95282e21af3..790f864e1da 100644 --- a/packages/main/src/components/FilterBar/__snapshots__/FilterBar.test.tsx.snap +++ b/packages/main/src/components/FilterBar/__snapshots__/FilterBar.test.tsx.snap @@ -28,12 +28,14 @@ exports[`FilterBar Hide Filter Bar 1`] = ` Cancel @@ -47,7 +49,6 @@ exports[`FilterBar Hide Filter Bar 1`] = ` > @@ -69,6 +69,7 @@ exports[`FilterBar Hide Filter Bar 1`] = ` > Hide Filter Bar @@ -89,6 +90,7 @@ exports[`FilterBar Hide Filter Bar 1`] = ` Classification @@ -119,6 +121,8 @@ exports[`FilterBar Hide Filter Bar 1`] = `
@@ -177,12 +181,14 @@ exports[`FilterBar Render without crashing 1`] = ` Cancel @@ -196,7 +202,6 @@ exports[`FilterBar Render without crashing 1`] = ` > @@ -218,6 +222,7 @@ exports[`FilterBar Render without crashing 1`] = ` > Hide Filter Bar @@ -250,6 +256,7 @@ exports[`FilterBar Render without crashing 1`] = ` Classification @@ -280,6 +287,8 @@ exports[`FilterBar Render without crashing 1`] = `
@@ -316,12 +325,14 @@ exports[`FilterBar Select Filter Item 1`] = ` Cancel @@ -335,7 +346,6 @@ exports[`FilterBar Select Filter Item 1`] = ` > @@ -357,6 +366,7 @@ exports[`FilterBar Select Filter Item 1`] = ` > Hide Filter Bar @@ -377,6 +387,7 @@ exports[`FilterBar Select Filter Item 1`] = ` Classification @@ -427,6 +438,7 @@ exports[`FilterBar Select Filter Item 1`] = ` Classification Text 1 Text 2 diff --git a/packages/main/src/components/Form/__snapshots__/Form.test.tsx.snap b/packages/main/src/components/Form/__snapshots__/Form.test.tsx.snap index 78b8fb20ffd..658e79423cc 100644 --- a/packages/main/src/components/Form/__snapshots__/Form.test.tsx.snap +++ b/packages/main/src/components/Form/__snapshots__/Form.test.tsx.snap @@ -30,6 +30,8 @@ exports[`Create a Form accepts both label and labelText 1`] = ` style="width: 66%;" > { .first() .instance() as any; - component.fireEvent('click'); + component.click(); expect(getEventFromCallback(callback).detail.action).toEqual(MessageBoxActions.OK); }); diff --git a/packages/main/src/components/MessageBox/__snapshots__/MessageBox.test.tsx.snap b/packages/main/src/components/MessageBox/__snapshots__/MessageBox.test.tsx.snap index 3f70429c72c..de7040ec1c8 100644 --- a/packages/main/src/components/MessageBox/__snapshots__/MessageBox.test.tsx.snap +++ b/packages/main/src/components/MessageBox/__snapshots__/MessageBox.test.tsx.snap @@ -15,6 +15,7 @@ exports[`MessageBox Confirm - Cancel 1`] = ` class="MessageBox-icon-0" >
@@ -31,6 +32,7 @@ exports[`MessageBox Confirm - Cancel 1`] = ` OK @@ -38,6 +40,7 @@ exports[`MessageBox Confirm - Cancel 1`] = ` Cancel @@ -66,6 +69,7 @@ exports[`MessageBox Confirm - OK 1`] = ` class="MessageBox-icon-0" >
@@ -82,6 +86,7 @@ exports[`MessageBox Confirm - OK 1`] = ` OK @@ -89,6 +94,7 @@ exports[`MessageBox Confirm - OK 1`] = ` Cancel @@ -117,6 +123,7 @@ exports[`MessageBox Error 1`] = ` class="MessageBox-icon-0" >
@@ -133,6 +140,7 @@ exports[`MessageBox Error 1`] = ` Close @@ -161,6 +169,7 @@ exports[`MessageBox Information 1`] = ` class="MessageBox-icon-0" >
@@ -177,6 +186,7 @@ exports[`MessageBox Information 1`] = ` OK @@ -205,6 +215,7 @@ exports[`MessageBox No Title 1`] = ` class="MessageBox-icon-0" >
@@ -221,6 +232,7 @@ exports[`MessageBox No Title 1`] = ` OK @@ -228,6 +240,7 @@ exports[`MessageBox No Title 1`] = ` Cancel @@ -255,6 +268,7 @@ exports[`MessageBox Not open 1`] = ` class="MessageBox-icon-0" > @@ -271,6 +285,7 @@ exports[`MessageBox Not open 1`] = ` OK @@ -299,6 +314,7 @@ exports[`MessageBox Show 1`] = ` class="MessageBox-icon-0" > @@ -315,6 +331,7 @@ exports[`MessageBox Show 1`] = ` Yes @@ -322,6 +339,7 @@ exports[`MessageBox Show 1`] = ` No @@ -350,6 +368,7 @@ exports[`MessageBox Success 1`] = ` class="MessageBox-icon-0" > @@ -366,6 +385,7 @@ exports[`MessageBox Success 1`] = ` OK @@ -394,6 +414,7 @@ exports[`MessageBox Success w/ custom title 1`] = ` class="MessageBox-icon-0" > @@ -410,6 +431,7 @@ exports[`MessageBox Success w/ custom title 1`] = ` OK @@ -438,6 +460,7 @@ exports[`MessageBox Warning 1`] = ` class="MessageBox-icon-0" > @@ -454,6 +477,7 @@ exports[`MessageBox Warning 1`] = ` OK diff --git a/packages/main/src/components/MessageToast/MessageToast.jss.ts b/packages/main/src/components/MessageToast/MessageToast.jss.ts deleted file mode 100644 index 62dce21718e..00000000000 --- a/packages/main/src/components/MessageToast/MessageToast.jss.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { ThemingParameters } from '@ui5/webcomponents-react-base/lib/ThemingParameters'; - -export default { - messageToast: { - padding: '0 !important', - borderRadius: '0.25rem !important', - textAlign: 'center !important', - boxShadow: ThemingParameters.sapContent_Shadow2, - cursor: 'text', - minHeight: 'auto !important', - background: `${ThemingParameters.sapList_Background} !important` - }, - messageToastContainer: { - maxWidth: '15rem !important' - }, - messageToastBody: { - fontFamily: ThemingParameters.sapFontFamily, - fontSize: ThemingParameters.sapFontSize, - fontWeight: 'normal', - textAlign: 'center', - textOverflow: 'ellipsis', - whiteSpace: 'pre-line', - wordWrap: 'break-word', - padding: '1rem !important', - color: `${ThemingParameters.sapList_TextColor} !important`, - display: 'flex', - justifyContent: 'center', - alignItems: 'center' - } -}; diff --git a/packages/main/src/components/MessageToast/MessageToast.test.tsx b/packages/main/src/components/MessageToast/MessageToast.test.tsx deleted file mode 100644 index d08d97c3dd5..00000000000 --- a/packages/main/src/components/MessageToast/MessageToast.test.tsx +++ /dev/null @@ -1,32 +0,0 @@ -import { MessageToast } from '@ui5/webcomponents-react/lib/MessageToast'; -import sinon from 'sinon'; - -describe('Message Toast', () => { - test('Show Default', () => { - const callback = sinon.spy(MessageToast, 'show'); - MessageToast.show('Default'); - expect(callback.called).toEqual(true); - callback.restore(); - }); - - test('Show Error', () => { - const callback = sinon.spy(MessageToast, 'error'); - MessageToast.error('Error'); - expect(callback.called).toEqual(true); - callback.restore(); - }); - - test('Show Warning', () => { - const callback = sinon.spy(MessageToast, 'warning'); - MessageToast.warning('Warning'); - expect(callback.called).toEqual(true); - callback.restore(); - }); - - test('Show Success', () => { - const callback = sinon.spy(MessageToast, 'success'); - MessageToast.success('Default'); - expect(callback.called).toEqual(true); - callback.restore(); - }); -}); diff --git a/packages/main/src/components/MessageToast/demo.stories.mdx b/packages/main/src/components/MessageToast/demo.stories.mdx deleted file mode 100644 index a945f3475c4..00000000000 --- a/packages/main/src/components/MessageToast/demo.stories.mdx +++ /dev/null @@ -1,94 +0,0 @@ - -import { Meta, Story, Preview } from '@storybook/addon-docs/blocks'; -import { Button } from '@ui5/webcomponents-react/lib/Button'; -import { ThemeProvider } from '@ui5/webcomponents-react/lib/ThemeProvider'; -import { MessageToast } from '@ui5/webcomponents-react/lib/MessageToast'; - - - -# MessageToast - -`import { MessageToast } from '@ui5/webcomponents-react/lib/MessageToast';` - - - -The MessageToast components provides an imperative API to open `MessageToast` programmatically from -any place of the application.

-All methods accept a `string` as first parameter (you can pass any `ReactNode` into it as well, but use at your own risk 😊).
-The optional second parameter is accepting an object of options from the underlying [react-toastify library](https://github.com/fkhadra/react-toastify). -You can check all available options on the [bottom of the page](#messagetoast-options). - -### Generic Message Toast -```js -MessageToast.show('Hello Generic Message Toast'); -``` - - -### Success Message Toast -```js -MessageToast.success('Hello Success Message Toast'); -``` - - -### Warning Message Toast -```js -MessageToast.warning('Hello Warning Message Toast'); -``` - - -### Error Message Toast -```js -MessageToast.error('Hello Error Message Toast'); -``` - - - -### MessageToast Options - -| Props | Type | Default | Description | -|----------------------|------------------------|-------------|--------------------------------------------------------------------------------------------------------------------------------------------| -| `type` | string | `default` | Kind of notification. One of "default", "success", "info", "warning", "error". You can use `toast.TYPE.SUCCESS` and so on to avoid any typo. | -| `onOpen` | callback | none | Called inside componentDidMount | -| `onClose` | callback | none | Called inside componentWillUnmount | -| `autoClose` | false or number | `5000` | Delay in ms to close the toast. If set to false, the notification need to be closed manualy | -| `closeButton` | React Element or false | - | A React Component to replace the default close button or `false` to hide the button | -| `transition` | function | - | A reference to a valid react-transition-group/Transition component | -| `closeOnClick` | bool | `true` | Dismiss toast on click | -| `hideProgressBar` | bool | `false` | Display or not the progress bar below the toast(remaining time) | -| `position` | string | `top-right` | One of top-right, top-center, top-left, bottom-right, bottom-center, bottom-left | -| `pauseOnHover` | bool | `true` | Keep the timer running or not on hover | -| `pauseOnFocusLoss` | bool | `true` | Pause the timer when the window loses focus | -| `className` | string\|object | - | Add optional classes to the container | -| `bodyClassName` | string\|object | - | Add optional classes to the toast body | -| `progressClassName` | string\|object | - | Add optional classes to the progress bar | -| `draggable` | bool | `true` | Allow toast to be draggable | -| `draggablePercent` | number | `80` | The percentage of the toast's width it takes for a drag to dismiss a toast(value between 0 and 100) | -| `role` | string | `alert` | Define the ARIA role for the toasts | -| `containerId` | string\number | - | Container id used to match toast with the same containerId | -| `toastId` | string | none | optional integer or string to manually set a toastId. If an invalid type is provided a generated toastId will be used | -| `progress` | string | none | a value between 0..1 to control the progress bar | -| `render` | string | none | string or React Element, only available when calling update | -| `delay` | string | none | a number to let you delay the toast appearance | -| `onClick` | string | none | Called when click inside Toast notification | - diff --git a/packages/main/src/components/MessageToast/index.tsx b/packages/main/src/components/MessageToast/index.tsx deleted file mode 100644 index 0da358c79a1..00000000000 --- a/packages/main/src/components/MessageToast/index.tsx +++ /dev/null @@ -1,102 +0,0 @@ -import '@ui5/webcomponents-icons/dist/icons/message-error'; -import '@ui5/webcomponents-icons/dist/icons/message-warning'; -import '@ui5/webcomponents-icons/dist/icons/sys-enter'; -import { ThemingParameters } from '@ui5/webcomponents-react-base/lib/ThemingParameters'; -import { Icon } from '@ui5/webcomponents-react/lib/Icon'; -import { ValueState } from '@ui5/webcomponents-react/lib/ValueState'; -import React from 'react'; -import { createPortal } from 'react-dom'; -import { createComponentStyles } from '@ui5/webcomponents-react-base/lib/createComponentStyles'; -import { toast, ToastContainer, ToastContent, ToastOptions } from 'react-toastify'; -import 'react-toastify/dist/ReactToastify.min.css'; -import styles from './MessageToast.jss'; - -const coloredStyles = { - base: { - width: '1.375rem', - minWidth: '1.375rem', - height: '1.375rem', - minHeight: '1.375rem' - }, - Success: { - color: ThemingParameters.sapPositiveElementColor - }, - Error: { - color: ThemingParameters.sapNegativeElementColor - }, - Warning: { - color: ThemingParameters.sapCriticalElementColor - } -}; - -const useIconStyles = createComponentStyles(coloredStyles, { - name: 'MessageToastIcon' -}); - -const ColoredIcon = ({ name, state }) => { - const classes = useIconStyles(); - return ; -}; - -const useMessageToastStyles = createComponentStyles(styles, { - name: 'MessageToast' -}); - -const MessageToast = () => { - const classes = useMessageToastStyles(); - - return createPortal( - , - document.body - ); -}; - -MessageToast.show = (text: ToastContent, options?: ToastOptions) => { - toast(text, options); -}; - -MessageToast.error = (text, options?: ToastOptions) => { - const toastContent = ( - <> - - {text} - - ); - - MessageToast.show(toastContent, options); -}; - -MessageToast.success = (text, options?: ToastOptions) => { - const toastContent = ( - <> - - {text} - - ); - - MessageToast.show(toastContent, options); -}; - -MessageToast.warning = (text, options?: ToastOptions) => { - const toastContent = ( - <> - - {text} - - ); - - MessageToast.show(toastContent, options); -}; - -MessageToast.displayName = 'MessageToast'; - -export { MessageToast }; diff --git a/packages/main/src/components/Notification/__snapshots__/Notification.test.tsx.snap b/packages/main/src/components/Notification/__snapshots__/Notification.test.tsx.snap index 3709b2c610d..5b5939b924a 100644 --- a/packages/main/src/components/Notification/__snapshots__/Notification.test.tsx.snap +++ b/packages/main/src/components/Notification/__snapshots__/Notification.test.tsx.snap @@ -57,6 +57,7 @@ exports[`Notification Default 1`] = ` > Show More @@ -129,6 +130,7 @@ exports[`Notification Long Title and Description 1`] = ` > Show More @@ -201,6 +203,7 @@ exports[`Notification Long Title and Description w/o truncation 1`] = ` > Show Less @@ -230,6 +233,7 @@ exports[`Notification w/ Props 1`] = ` class="Notification-semanticIcon-0" > @@ -255,12 +259,15 @@ exports[`Notification w/ Props 1`] = `
- - ME - +
Show More Accept Reject @@ -355,10 +365,14 @@ exports[`Notification w/ custom Avatar 1`] = `
-
Show More diff --git a/packages/main/src/components/NotificationGroup/__snapshots__/NotificationGroup.test.tsx.snap b/packages/main/src/components/NotificationGroup/__snapshots__/NotificationGroup.test.tsx.snap index b7147b5cc98..85828563839 100644 --- a/packages/main/src/components/NotificationGroup/__snapshots__/NotificationGroup.test.tsx.snap +++ b/packages/main/src/components/NotificationGroup/__snapshots__/NotificationGroup.test.tsx.snap @@ -59,6 +59,7 @@ exports[`NotificationGroup Collapsed 1`] = ` > Show More @@ -68,6 +69,7 @@ exports[`NotificationGroup Collapsed 1`] = ` Expand Group @@ -135,6 +137,7 @@ Array [ > Show More @@ -144,6 +147,7 @@ Array [ Collapse Group @@ -167,6 +171,7 @@ Array [ class="Notification-semanticIcon-0" > @@ -192,12 +197,15 @@ Array [
- - ME - +
Show More Accept Reject @@ -289,10 +300,14 @@ Array [
-
Show More @@ -390,6 +406,7 @@ Array [ > Show Less @@ -421,6 +438,7 @@ Array [ class="Notification-semanticIcon-0" > @@ -446,12 +464,15 @@ Array [
- - ME - +
Show More Accept Reject @@ -511,6 +535,7 @@ Array [ Collapse Group @@ -577,6 +602,7 @@ Array [ > Show More @@ -641,6 +667,7 @@ Array [ > Show More @@ -705,6 +732,7 @@ Array [ > Show More @@ -776,6 +804,7 @@ Array [ > Show More @@ -785,6 +814,7 @@ Array [ Collapse Group @@ -808,6 +838,7 @@ Array [ class="Notification-semanticIcon-0" > @@ -833,12 +864,15 @@ Array [
- - ME - +
Show More Accept Reject @@ -930,10 +967,14 @@ Array [
-
Show More @@ -1031,6 +1073,7 @@ Array [ > Show Less @@ -1101,6 +1144,7 @@ exports[`NotificationGroup w/o children 1`] = ` > Show More @@ -1170,6 +1214,7 @@ exports[`NotificationGroup w/o children 2`] = ` > Show More diff --git a/packages/main/src/components/ObjectPage/ObjectPageAnchorBar.tsx b/packages/main/src/components/ObjectPage/ObjectPageAnchorBar.tsx index fe173b04d1a..04e7e41fea8 100644 --- a/packages/main/src/components/ObjectPage/ObjectPageAnchorBar.tsx +++ b/packages/main/src/components/ObjectPage/ObjectPageAnchorBar.tsx @@ -37,6 +37,7 @@ const anchorBarStyles = { position: 'absolute', '--_ui5_button_compact_height': '1.375rem', '--_ui5_button_base_height': '1.375rem', + '--_ui5_button_base_min_width': '1.375rem', '--_ui5_button_base_min_compact_width': '1.375rem', top: `-0.6875rem`, marginLeft: `-0.6875rem`, @@ -121,7 +122,7 @@ const ObjectPageAnchorBar = forwardRef((props: Props, ref: RefObject { - const { sectionId, index } = event.detail.item.dataset; + const { sectionId, index } = event.detail.tab.dataset; // eslint-disable-next-line eqeqeq const section = safeGetChildrenArray(sections).find((el) => el.props.id == sectionId); handleOnSectionSelected( @@ -156,7 +157,7 @@ const ObjectPageAnchorBar = forwardRef((props: Props, ref: RefObject - + {safeGetChildrenArray(sections).map((section, index) => { return ( = (props: Obj useEffect(() => { if (subSectionsAvailable) { - const element = ref.current.parentElement.shadowRoot.querySelector( - `.ui5-tc__headerList li[aria-posinset="${index + 1}"] .ui5-tc__headerItemContent` - ); + try { + const element = ref.current.parentElement.shadowRoot.querySelector( + `.ui5-tc__headerList li[aria-posinset="${index + 1}"] .ui5-tc__headerItemContent` + ); - if (element && !element.querySelector('ui5-icon')) { - const icon = document.createElement('ui5-icon'); - (icon as any).name = 'slim-arrow-down'; - icon.style.verticalAlign = 'text-bottom'; - icon.style.pointerEvents = 'all'; - icon.addEventListener('click', (e) => { - e.stopImmediatePropagation(); - e.preventDefault(); - e.stopPropagation(); - onShowSubSectionPopover(e, section); - }); - element.appendChild(icon); + if (element && !element.querySelector('ui5-icon')) { + const icon = document.createElement('ui5-icon'); + (icon as any).name = 'slim-arrow-down'; + icon.style.verticalAlign = 'text-bottom'; + icon.style.pointerEvents = 'all'; + icon.addEventListener('click', (e) => { + e.stopImmediatePropagation(); + e.preventDefault(); + e.stopPropagation(); + onShowSubSectionPopover(e, section); + }); + element.appendChild(icon); + } + } catch (e) { + // empty catch block, mainly required for tests } } }, [subSectionsAvailable, ref, onShowSubSectionPopover, section]); diff --git a/packages/main/src/components/ObjectPage/__snapshots__/ObjectPage.test.tsx.snap b/packages/main/src/components/ObjectPage/__snapshots__/ObjectPage.test.tsx.snap index 7b6d2936bc2..69681608078 100644 --- a/packages/main/src/components/ObjectPage/__snapshots__/ObjectPage.test.tsx.snap +++ b/packages/main/src/components/ObjectPage/__snapshots__/ObjectPage.test.tsx.snap @@ -16,6 +16,7 @@ exports[`ObjectPage IconTabBar Mode 1`] = ` > Action @@ -64,6 +65,7 @@ exports[`ObjectPage IconTabBar Mode 1`] = ` www.myurl.com @@ -94,35 +96,46 @@ exports[`ObjectPage IconTabBar Mode 1`] = ` collapsed="true" fixed="true" show-overflow="true" + tab-layout="Standard" > @@ -135,6 +148,7 @@ exports[`ObjectPage IconTabBar Mode 1`] = ` /> Path1 @@ -329,6 +350,7 @@ exports[`ObjectPage Key Infos 1`] = ` Path2 @@ -341,6 +363,7 @@ exports[`ObjectPage Key Infos 1`] = `
Action @@ -968,6 +1014,7 @@ exports[`ObjectPage Only Sections 1`] = ` www.myurl.com @@ -998,29 +1045,37 @@ exports[`ObjectPage Only Sections 1`] = ` collapsed="true" fixed="true" show-overflow="true" + tab-layout="Standard" > Action @@ -1298,6 +1360,7 @@ exports[`ObjectPage With Subsections 1`] = ` www.myurl.com @@ -1328,35 +1391,46 @@ exports[`ObjectPage With Subsections 1`] = ` collapsed="true" fixed="true" show-overflow="true" + tab-layout="Standard" > @@ -1369,6 +1443,7 @@ exports[`ObjectPage With Subsections 1`] = ` /> @@ -23,6 +24,7 @@ exports[`ObjectStatus ObjectStatus: state: Information 1`] = ` class="ObjectStatus-icon-0 ObjectStatus-iconInformation-0" > @@ -38,6 +40,7 @@ exports[`ObjectStatus ObjectStatus: state: None 1`] = ` class="ObjectStatus-icon-0 ObjectStatus-iconNone-0" > @@ -53,6 +56,7 @@ exports[`ObjectStatus ObjectStatus: state: Success 1`] = ` class="ObjectStatus-icon-0 ObjectStatus-iconSuccess-0" > @@ -68,6 +72,7 @@ exports[`ObjectStatus ObjectStatus: state: Warning 1`] = ` class="ObjectStatus-icon-0 ObjectStatus-iconWarning-0" > @@ -83,6 +88,7 @@ exports[`ObjectStatus Render without Crashing 1`] = ` class="ObjectStatus-icon-0 ObjectStatus-iconError-0" > @@ -103,6 +109,7 @@ exports[`ObjectStatus Text Deprecation 1`] = ` class="ObjectStatus-icon-0 ObjectStatus-iconError-0" > diff --git a/packages/main/src/components/SegmentedButton/SegmentedButton.test.tsx b/packages/main/src/components/SegmentedButton/SegmentedButton.test.tsx deleted file mode 100644 index d8916b3f851..00000000000 --- a/packages/main/src/components/SegmentedButton/SegmentedButton.test.tsx +++ /dev/null @@ -1,45 +0,0 @@ -import { createPassThroughPropsTest, getEventFromCallback } from '@shared/tests/utils'; -import { mount } from 'enzyme'; -import { SegmentedButton } from '@ui5/webcomponents-react/lib/SegmentedButton'; -import { SegmentedButtonItem } from '@ui5/webcomponents-react/lib/SegmentedButtonItem'; -import React, { cloneElement } from 'react'; -import sinon from 'sinon'; - -describe('SegmentedButton', () => { - test('Selection', () => { - const callback = sinon.spy(); - const wrapper = mount( - // @ts-ignore - - Test - Test - - ); - wrapper - .find('li') - .last() - .simulate('click'); - wrapper.update(); - expect(getEventFromCallback(callback).detail.selectedKey).toEqual('btn-2'); - }); - - test('Update Selection via API', () => { - const callback = sinon.spy(); - - const wrapper = mount( - - Test - Test - - ); - expect(wrapper.render()).toMatchSnapshot(); - wrapper.setProps({ - selectedKey: 'btn-2' - }); - wrapper.update(); - expect(wrapper.render()).toMatchSnapshot(); - expect(callback.called).toBe(false); - }); - - createPassThroughPropsTest(SegmentedButton); -}); diff --git a/packages/main/src/components/SegmentedButton/__snapshots__/SegmentedButton.test.tsx.snap b/packages/main/src/components/SegmentedButton/__snapshots__/SegmentedButton.test.tsx.snap deleted file mode 100644 index a07a468c4f5..00000000000 --- a/packages/main/src/components/SegmentedButton/__snapshots__/SegmentedButton.test.tsx.snap +++ /dev/null @@ -1,47 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`SegmentedButton Update Selection via API 1`] = ` -
    -
  • - Test -
  • -
  • - Test -
  • -
-`; - -exports[`SegmentedButton Update Selection via API 2`] = ` -
    -
  • - Test -
  • -
  • - Test -
  • -
-`; diff --git a/packages/main/src/components/SegmentedButton/demo.stories.tsx b/packages/main/src/components/SegmentedButton/demo.stories.tsx deleted file mode 100644 index f2156eb287d..00000000000 --- a/packages/main/src/components/SegmentedButton/demo.stories.tsx +++ /dev/null @@ -1,35 +0,0 @@ -import { action } from '@storybook/addon-actions'; -import { boolean, number } from '@storybook/addon-knobs'; -import { Icon } from '@ui5/webcomponents-react/lib/Icon'; -import { SegmentedButton } from '@ui5/webcomponents-react/lib/SegmentedButton'; -import { SegmentedButtonItem } from '@ui5/webcomponents-react/lib/SegmentedButtonItem'; -import React from 'react'; - -export const renderStory = () => { - return ( - - } /> - }> - Button 2 - - - Button 3 - - - ); -}; -renderStory.story = { - name: 'Default' -}; - -export default { - title: 'Components / SegmentedButton', - component: SegmentedButton, - parameters: { - subcomponents: { SegmentedButtonItem } - } -}; diff --git a/packages/main/src/components/SegmentedButton/index.tsx b/packages/main/src/components/SegmentedButton/index.tsx deleted file mode 100644 index 8f9de1d92ef..00000000000 --- a/packages/main/src/components/SegmentedButton/index.tsx +++ /dev/null @@ -1,151 +0,0 @@ -import { CssSizeVariables } from '@ui5/webcomponents-react-base/lib/CssSizeVariables'; -import { enrichEventWithDetails } from '@ui5/webcomponents-react-base/lib/Utils'; -import { StyleClassHelper } from '@ui5/webcomponents-react-base/lib/StyleClassHelper'; -import { useConsolidatedRef } from '@ui5/webcomponents-react-base/lib/useConsolidatedRef'; -import { usePassThroughHtmlProps } from '@ui5/webcomponents-react-base/lib/usePassThroughHtmlProps'; -import React, { - Children, - cloneElement, - FC, - forwardRef, - ReactNode, - Ref, - RefObject, - useCallback, - useEffect, - useState -} from 'react'; -import { createComponentStyles } from '@ui5/webcomponents-react-base/lib/createComponentStyles'; -import { CommonProps } from '../../interfaces/CommonProps'; - -export type SelectedKey = string | number; - -export interface SegmentedButtonPropTypes extends CommonProps { - disabled?: boolean; - selectedKey?: SelectedKey; - children: ReactNode | ReactNode[]; - onItemSelected?: (event: CustomEvent<{ selectedKey: string | number }>) => void; -} - -const styles = { - segmentedButton: { - verticalAlign: 'top', - position: 'relative', - margin: '0', - padding: CssSizeVariables.sapWcrSegmentedButtonPadding, - border: 'none', - whiteSpace: 'nowrap', - display: 'inline-block', - boxSizing: 'border-box', - maxWidth: '100%', - height: CssSizeVariables.sapWcrSegmentedButtonHeight, - '&:focus': { - outline: 'none' - } - } -}; - -const useStyles = createComponentStyles(styles, { name: 'SegmentedButton' }); - -/** - * import { SegmentedButton } from '@ui5/webcomponents-react/lib/SegmentedButton'; - */ -const SegmentedButton: FC = forwardRef( - (props: SegmentedButtonPropTypes, ref: Ref) => { - const { children, disabled, className, style, tooltip, slot, onItemSelected, selectedKey } = props; - - const listRef: RefObject = useConsolidatedRef(ref); - - const [internalSelectedKey, setSelectedKey] = useState(() => { - if (selectedKey) return selectedKey; - const firstChild: any = Children.toArray(children)[0]; - return firstChild?.props?.id ?? null; - }); - - useEffect(() => { - if (selectedKey) { - setSelectedKey(selectedKey); - } - }, [selectedKey, setSelectedKey]); - - const classes = useStyles(); - - const segmentedBtnClasses = StyleClassHelper.of(classes.segmentedButton); - if (className) { - segmentedBtnClasses.put(className); - } - - const handleSegmentedButtonItemSelected = useCallback( - (originalOnclick) => (e) => { - const newSelectedKey = e.detail.selectedKey; - if (newSelectedKey !== internalSelectedKey) { - setSelectedKey(newSelectedKey); - if (typeof onItemSelected === 'function') { - onItemSelected(enrichEventWithDetails(e, e.detail)); - } - } - if (typeof originalOnclick === 'function') { - originalOnclick(e); - } - }, - [internalSelectedKey, setSelectedKey, onItemSelected] - ); - - useEffect(() => { - requestAnimationFrame(() => { - if (!listRef.current) return; - let maxWidth = 0; - for (let i = 0; i < listRef.current.childElementCount; i++) { - const item = listRef.current.children.item(i) as HTMLLIElement; - if (item.offsetWidth && item.offsetWidth > maxWidth) { - maxWidth = item.offsetWidth; - } - } - if (maxWidth < listRef.current.offsetWidth) { - for (let i = 0; i < listRef.current.childElementCount; i++) { - const item = listRef.current.children.item(i) as HTMLLIElement; - if (item.getAttribute('data-has-own-width') === 'false') { - item.style.width = `${maxWidth}px`; - } - } - } - }); - }, [children, listRef]); - - const passThroughProps = usePassThroughHtmlProps(props, ['onItemSelected']); - - return ( -
    - {Children.toArray(children) - .filter(Boolean) - .map((item: any) => - cloneElement(item, { - key: item.props.id, - selected: internalSelectedKey === item.props.id, - disabled: disabled === true ? disabled : item.props.disabled, - onClick: handleSegmentedButtonItemSelected(item.props.onClick) - }) - )} -
- ); - } -); - -SegmentedButton.displayName = 'SegmentedButton'; - -SegmentedButton.defaultProps = { - disabled: false, - selectedKey: '', - onItemSelected: null -}; - -export { SegmentedButton }; diff --git a/packages/main/src/components/SegmentedButtonItem/SegmentedButtonItem.jss.ts b/packages/main/src/components/SegmentedButtonItem/SegmentedButtonItem.jss.ts deleted file mode 100644 index 327f887f813..00000000000 --- a/packages/main/src/components/SegmentedButtonItem/SegmentedButtonItem.jss.ts +++ /dev/null @@ -1,74 +0,0 @@ -import { CssSizeVariables } from '@ui5/webcomponents-react-base/lib/CssSizeVariables'; -import { ThemingParameters } from '@ui5/webcomponents-react-base/lib/ThemingParameters'; - -const styles = { - segmentedButtonItem: { - fontFamily: ThemingParameters.sapFontFamily, - listStyle: 'none', - overflow: 'hidden', - WebkitTapHighlightColor: 'rgba(255, 255, 255, 0)', - textAlign: 'center', - alignContent: 'center', - alignItems: 'center', - cursor: 'pointer', - verticalAlign: 'text-bottom', - boxSizing: 'border-box', - display: 'inline-block', - fontSize: '0.875rem', - '&:focus': { - outline: `1px dotted ${ThemingParameters.sapContent_FocusColor}` - }, - height: CssSizeVariables.sapWcrSegmentedButtonItemHeight, - lineHeight: CssSizeVariables.sapWcrSegmentedButtonItemLineHeight, - textShadow: 'none', - '&:not($iconOnly)': { paddingLeft: '0.625rem', paddingRight: '0.625rem', textOverflow: 'ellipsis' }, - '&:first-child': { - borderTopLeftRadius: '0.25rem', - borderBottomLeftRadius: '0.25rem' - }, - '&:last-child': { - borderTopRightRadius: '0.25rem', - borderBottomRightRadius: '0.25rem', - borderRightColor: ThemingParameters.sapButton_BorderColor - }, - color: ThemingParameters.sapButton_TextColor, - border: `1px solid ${ThemingParameters.sapButton_BorderColor}`, - borderRightColor: 'transparent', - backgroundColor: ThemingParameters.sapButton_Background - }, - selected: { - background: ThemingParameters.sapButton_Selected_Background, - color: ThemingParameters.sapButton_Selected_TextColor, - borderColor: ThemingParameters.sapButton_Selected_BorderColor, - // TODO: replace with ThemingParameters.sapContent_ContrastIconColor after ui5-webcomponents upgrade to rc.6 - '--sapContent_NonInteractiveIconColor': 'var(--sapUiContentContrastIconColor)', - '$:active': { - background: ThemingParameters.sapButton_Active_Background, - color: ThemingParameters.sapButton_Active_TextColor - } - }, - focusableItem: { - '&:not($selected):hover': { - background: ThemingParameters.sapButton_Hover_Background - } - }, - disabled: { textShadow: 'none', cursor: 'default', opacity: '0.4' }, - iconOnly: { paddingLeft: '0.625rem', paddingRight: '0.625rem' }, - icon: { - fontSize: '1rem', - textAlign: 'center', - alignContent: 'center', - display: 'inline-block', - '&:focus': { - outline: 'none' - }, - '& > *': { - verticalAlign: 'middle' - } - }, - withText: { - marginRight: '0.5rem' - } -}; - -export default styles; diff --git a/packages/main/src/components/SegmentedButtonItem/SegmentedButtonItem.test.tsx b/packages/main/src/components/SegmentedButtonItem/SegmentedButtonItem.test.tsx deleted file mode 100644 index d8ed657c8f6..00000000000 --- a/packages/main/src/components/SegmentedButtonItem/SegmentedButtonItem.test.tsx +++ /dev/null @@ -1,50 +0,0 @@ -import { createPassThroughPropsTest, getEventFromCallback } from '@shared/tests/utils'; -import { mount } from 'enzyme'; -import { Icon } from '@ui5/webcomponents-react/lib/Icon'; -import { SegmentedButtonItem } from '@ui5/webcomponents-react/lib/SegmentedButtonItem'; -import React from 'react'; -import sinon from 'sinon'; - -describe('SegmentedButtonItem', () => { - test('Basic SegmentedButtonItem', () => { - const wrapper = mount( - }> - My Item - - ); - expect(wrapper.render()).toMatchSnapshot(); - }); - - test('Selected SegmentedButtonItem', () => { - const wrapper = mount( - // @ts-ignore - } selected> - My Item - - ); - expect(wrapper.render()).toMatchSnapshot(); - }); - - test('SegmentedButtonItem Icon Only', () => { - const wrapper = mount(} />); - expect(wrapper.render()).toMatchSnapshot(); - }); - - test('SegmentedButtonItem Disabled', () => { - const callback = sinon.spy(); - const wrapper = mount(} disabled onClick={callback} />); - wrapper.simulate('click'); - expect(wrapper.render()).toMatchSnapshot(); - expect(callback.called).toEqual(false); - }); - - test('SegmentedButtonItem onClick', () => { - const callback = sinon.spy(); - const wrapper = mount(} onClick={callback} />); - wrapper.simulate('click'); - expect(wrapper.render()).toMatchSnapshot(); - expect(getEventFromCallback(callback).detail.selectedKey).toEqual(1); - }); - - createPassThroughPropsTest(SegmentedButtonItem); -}); diff --git a/packages/main/src/components/SegmentedButtonItem/__snapshots__/SegmentedButtonItem.test.tsx.snap b/packages/main/src/components/SegmentedButtonItem/__snapshots__/SegmentedButtonItem.test.tsx.snap deleted file mode 100644 index dccffeed0fd..00000000000 --- a/packages/main/src/components/SegmentedButtonItem/__snapshots__/SegmentedButtonItem.test.tsx.snap +++ /dev/null @@ -1,83 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`SegmentedButtonItem Basic SegmentedButtonItem 1`] = ` -
  • -
    - -
    - My Item -
  • -`; - -exports[`SegmentedButtonItem SegmentedButtonItem Disabled 1`] = ` -
  • -
    - -
    -
  • -`; - -exports[`SegmentedButtonItem SegmentedButtonItem Icon Only 1`] = ` -
  • -
    - -
    -
  • -`; - -exports[`SegmentedButtonItem SegmentedButtonItem onClick 1`] = ` -
  • -
    - -
    -
  • -`; - -exports[`SegmentedButtonItem Selected SegmentedButtonItem 1`] = ` -
  • -
    - -
    - My Item -
  • -`; diff --git a/packages/main/src/components/SegmentedButtonItem/index.tsx b/packages/main/src/components/SegmentedButtonItem/index.tsx deleted file mode 100644 index e4fd75b0489..00000000000 --- a/packages/main/src/components/SegmentedButtonItem/index.tsx +++ /dev/null @@ -1,97 +0,0 @@ -import { enrichEventWithDetails } from '@ui5/webcomponents-react-base/lib/Utils'; -import { StyleClassHelper } from '@ui5/webcomponents-react-base/lib/StyleClassHelper'; -import { usePassThroughHtmlProps } from '@ui5/webcomponents-react-base/lib/usePassThroughHtmlProps'; -import React, { CSSProperties, FC, forwardRef, Ref, useCallback, useMemo } from 'react'; -import { createComponentStyles } from '@ui5/webcomponents-react-base/lib/createComponentStyles'; -import { CommonProps } from '../../interfaces/CommonProps'; -import styles from './SegmentedButtonItem.jss'; - -export interface SegmentedButtonItemPropTypes extends CommonProps { - icon?: JSX.Element; - id: string | number; - disabled?: boolean; - children?: string; - width?: CSSProperties['width']; - onClick?: (e: CustomEvent<{ selectedKey: string | number }>) => void; -} - -const useStyles = createComponentStyles(styles, { name: 'SegmentedButtonItem' }); - -/** - * import { SegmentedButtonItem } from '@ui5/webcomponents-react/lib/SegmentedButtonItem'; - */ -const SegmentedButtonItem: FC = forwardRef( - (props: SegmentedButtonItemPropTypes, ref: Ref) => { - const { disabled, children, icon, className, style, tooltip, onClick, id, width } = props; - - const classes = useStyles(); - - const iconClasses = StyleClassHelper.of(classes.icon); - const segmentedButtonItemClasses = StyleClassHelper.of(classes.segmentedButtonItem); - - if (children && children !== '') { - iconClasses.put(classes.withText); - } else { - segmentedButtonItemClasses.put(classes.iconOnly); - } - - if (disabled) { - segmentedButtonItemClasses.put(classes.disabled); - } else { - segmentedButtonItemClasses.put(classes.focusableItem); - } - - if (props['selected']) { - segmentedButtonItemClasses.put(classes.selected); - } - - if (className) { - segmentedButtonItemClasses.put(className); - } - - const handleOnClick = useCallback( - (e) => { - if (!disabled && typeof onClick === 'function') { - onClick(enrichEventWithDetails(e, { selectedKey: id })); - } - }, - [onClick, disabled, id] - ); - - const inlineStyles = useMemo(() => { - if (width === undefined || width === null) { - return style; - } - - return { - ...style, - width - }; - }, [style, width]); - - const passThroughProps = usePassThroughHtmlProps(props, ['onClick']); - - return ( -
  • - {icon &&
    {icon}
    } - {children} -
  • - ); - } -); - -SegmentedButtonItem.displayName = 'SegmentedButtonItem'; - -SegmentedButtonItem.defaultProps = { - disabled: false -}; - -export { SegmentedButtonItem }; diff --git a/packages/main/src/components/SideNavigation/__snapshots__/SideNavigation.test.tsx.snap b/packages/main/src/components/SideNavigation/__snapshots__/SideNavigation.test.tsx.snap index 19c67e0282a..629c0c90cc1 100644 --- a/packages/main/src/components/SideNavigation/__snapshots__/SideNavigation.test.tsx.snap +++ b/packages/main/src/components/SideNavigation/__snapshots__/SideNavigation.test.tsx.snap @@ -19,6 +19,7 @@ exports[`SideNavigation Collapsed 1`] = ` type="Active" > @@ -31,6 +32,7 @@ exports[`SideNavigation Collapsed 1`] = ` type="Active" > @@ -43,6 +45,7 @@ exports[`SideNavigation Collapsed 1`] = ` type="Active" > @@ -57,6 +60,7 @@ exports[`SideNavigation Collapsed 1`] = ` > @@ -73,6 +77,7 @@ exports[`SideNavigation Collapsed 1`] = ` type="Active" > @@ -99,6 +104,7 @@ exports[`SideNavigation Collapsed 1`] = ` type="Active" > @@ -111,6 +117,7 @@ exports[`SideNavigation Collapsed 1`] = ` type="Active" > @@ -138,6 +145,7 @@ exports[`SideNavigation Condensed 1`] = ` type="Active" > @@ -150,6 +158,7 @@ exports[`SideNavigation Condensed 1`] = ` type="Active" > @@ -162,6 +171,7 @@ exports[`SideNavigation Condensed 1`] = ` type="Active" > @@ -176,6 +186,7 @@ exports[`SideNavigation Condensed 1`] = ` > @@ -192,6 +203,7 @@ exports[`SideNavigation Condensed 1`] = ` type="Active" > @@ -218,6 +230,7 @@ exports[`SideNavigation Condensed 1`] = ` type="Active" > @@ -230,6 +243,7 @@ exports[`SideNavigation Condensed 1`] = ` type="Active" > @@ -258,6 +272,7 @@ exports[`SideNavigation Expanded 1`] = ` type="Active" > @@ -275,6 +290,7 @@ exports[`SideNavigation Expanded 1`] = ` type="Active" > @@ -292,6 +308,7 @@ exports[`SideNavigation Expanded 1`] = ` type="Active" > @@ -309,6 +326,7 @@ exports[`SideNavigation Expanded 1`] = ` type="Active" > @@ -321,6 +339,7 @@ exports[`SideNavigation Expanded 1`] = ` class="SideNavigationListItem-expandArrow-0" > @@ -387,6 +406,7 @@ exports[`SideNavigation Expanded 1`] = ` type="Active" > @@ -418,6 +438,7 @@ exports[`SideNavigation Expanded 1`] = ` type="Active" > @@ -435,6 +456,7 @@ exports[`SideNavigation Expanded 1`] = ` type="Active" > @@ -514,6 +536,7 @@ exports[`SideNavigation Expanded without Icons 1`] = ` class="SideNavigationListItem-expandArrow-0" > diff --git a/packages/main/src/components/SideNavigationListItem/__snapshots__/SideNavigationListItem.test.tsx.snap b/packages/main/src/components/SideNavigationListItem/__snapshots__/SideNavigationListItem.test.tsx.snap index e25e0e905e9..483ef336cca 100644 --- a/packages/main/src/components/SideNavigationListItem/__snapshots__/SideNavigationListItem.test.tsx.snap +++ b/packages/main/src/components/SideNavigationListItem/__snapshots__/SideNavigationListItem.test.tsx.snap @@ -9,6 +9,7 @@ exports[`SideNavigationListItem Basic 1`] = ` type="Active" > @@ -25,6 +26,7 @@ exports[`SideNavigationListItem custom class name and style 1`] = ` type="Active" > diff --git a/packages/main/src/components/ThemeProvider/ThemingSupport.ts b/packages/main/src/components/ThemeProvider/ThemingSupport.ts new file mode 100644 index 00000000000..5c18b13547e --- /dev/null +++ b/packages/main/src/components/ThemeProvider/ThemingSupport.ts @@ -0,0 +1,12 @@ +import { root as sap_belize } from '@sap-theming/theming-base-content/content/Base/baseLib/sap_belize/variables.json'; +import { root as sap_belize_hcb } from '@sap-theming/theming-base-content/content/Base/baseLib/sap_belize_hcb/variables.json'; +import { root as sap_belize_hcw } from '@sap-theming/theming-base-content/content/Base/baseLib/sap_belize_hcw/variables.json'; +import { root as sap_fiori_3 } from '@sap-theming/theming-base-content/content/Base/baseLib/sap_fiori_3/variables.json'; +import { root as sap_fiori_3_dark } from '@sap-theming/theming-base-content/content/Base/baseLib/sap_fiori_3_dark/variables.json'; + +const themeMap = window['@ui5/webcomponents-react-theming'] || (window['@ui5/webcomponents-react-theming'] = new Map()); +themeMap.set('sap_fiori_3', sap_fiori_3); +themeMap.set('sap_fiori_3_dark', sap_fiori_3_dark); +themeMap.set('sap_belize', sap_belize); +themeMap.set('sap_belize_hcb', sap_belize_hcb); +themeMap.set('sap_belize_hcw', sap_belize_hcw); diff --git a/packages/main/src/components/ThemeProvider/index.tsx b/packages/main/src/components/ThemeProvider/index.tsx index 3b3499824ff..1279dcbf02d 100644 --- a/packages/main/src/components/ThemeProvider/index.tsx +++ b/packages/main/src/components/ThemeProvider/index.tsx @@ -1,14 +1,32 @@ -import { getCompactSize } from '@ui5/webcomponents-base/dist/config/CompactSize'; +import { root as sap_fiori_3 } from '@sap-theming/theming-base-content/content/Base/baseLib/sap_fiori_3/variables.json'; import { getTheme } from '@ui5/webcomponents-base/dist/config/Theme'; import { getRTL } from '@ui5/webcomponents-base/dist/config/RTL'; import { cssVariablesStyles } from '@ui5/webcomponents-react-base/lib/CssSizeVariables'; import { ThemingParameters } from '@ui5/webcomponents-react-base/lib/ThemingParameters'; import { ContentDensity } from '@ui5/webcomponents-react/lib/ContentDensity'; -import { MessageToast } from '@ui5/webcomponents-react/lib/MessageToast'; -import React, { FC, Fragment, ReactNode, useEffect, useMemo } from 'react'; +import { Themes } from '@ui5/webcomponents-react/lib/Themes'; +import React, { FC, ReactNode, useEffect, useMemo } from 'react'; import { ThemeProvider as ReactJssThemeProvider } from 'react-jss'; import { JSSTheme } from '../../interfaces/JSSTheme'; +const themeMap = window['@ui5/webcomponents-react-theming'] || (window['@ui5/webcomponents-react-theming'] = new Map()); +themeMap.set('sap_fiori_3', sap_fiori_3); + +const insertThemeDesignerParameters = (parameters = {}) => { + let element = document.querySelector('head #ui5wcr-theming-parameters'); + if (!element) { + element = document.createElement('style'); + element.id = 'ui5wcr-theming-parameters'; + document.head.insertBefore(element, document.head.firstChild); + } + element.innerHTML = ` +:root { + ${Object.entries(parameters) + .map(([key, value]) => `--${key}:${value};`) + .join('\n')} +}`; +}; + declare global { interface Window { CSSVarsPonyfill: { @@ -20,11 +38,7 @@ declare global { const cssVarsPonyfillNeeded = () => !!window.CSSVarsPonyfill; export interface ThemeProviderProps { - /* - * If true, the Theme Provider will also inject the root node for message toasts. - * Required in case you want to use them. - */ - withToastContainer?: boolean; + theme: Themes; children: ReactNode; } @@ -40,9 +54,14 @@ if (!document.querySelector('style[data-ui5-webcomponents-react-sizes]')) { * import { ThemeProvider } from '@ui5/webcomponents-react/lib/ThemeProvider'; */ const ThemeProvider: FC = (props: ThemeProviderProps) => { - const { withToastContainer = false, children } = props; - const theme = getTheme(); - const isCompactSize = getCompactSize(); + const { children, theme = getTheme() } = props; + const isCompactSize = document.body.classList.contains('ui5-content-density-compact'); + + useEffect(() => { + if (themeMap) { + insertThemeDesignerParameters(themeMap.get(theme)); + } + }, [theme]); const themeContext: JSSTheme = useMemo(() => { return { @@ -53,14 +72,6 @@ const ThemeProvider: FC = (props: ThemeProviderProps) => { }; }, [theme, isCompactSize]); - useEffect(() => { - if (isCompactSize) { - document.body.classList.add('ui5-content-density-compact'); - } else { - document.body.classList.remove('ui5-content-density-compact'); - } - }, [isCompactSize]); - useEffect(() => { if (cssVarsPonyfillNeeded()) { window.CSSVarsPonyfill.cssVars({ @@ -75,14 +86,7 @@ const ThemeProvider: FC = (props: ThemeProviderProps) => { } }, []); - return ( - - - {children} - {withToastContainer && } - - - ); + return {children}; }; ThemeProvider.displayName = 'ThemeProvider'; diff --git a/packages/main/src/components/VariantManagement/__snapshots__/VariantManagement.test.tsx.snap b/packages/main/src/components/VariantManagement/__snapshots__/VariantManagement.test.tsx.snap index 62492a5de20..b860208e125 100644 --- a/packages/main/src/components/VariantManagement/__snapshots__/VariantManagement.test.tsx.snap +++ b/packages/main/src/components/VariantManagement/__snapshots__/VariantManagement.test.tsx.snap @@ -23,12 +23,14 @@ Array [ Cancel @@ -42,7 +44,6 @@ Array [ > diff --git a/packages/main/src/components/VariantManagement/index.tsx b/packages/main/src/components/VariantManagement/index.tsx index 444ff7a29d9..9b2ba3664ca 100644 --- a/packages/main/src/components/VariantManagement/index.tsx +++ b/packages/main/src/components/VariantManagement/index.tsx @@ -1,5 +1,5 @@ import '@ui5/webcomponents-icons/dist/icons/navigation-down-arrow'; -import { enrichEventWithDetails } from "@ui5/webcomponents-react-base/lib/Utils"; +import { enrichEventWithDetails } from '@ui5/webcomponents-react-base/lib/Utils'; import { ThemingParameters } from '@ui5/webcomponents-react-base/lib/ThemingParameters'; import { usePassThroughHtmlProps } from '@ui5/webcomponents-react-base/lib/usePassThroughHtmlProps'; import { Button } from '@ui5/webcomponents-react/lib/Button'; @@ -27,7 +27,7 @@ export interface VariantManagementPropTypes extends CommonProps { initialSelectedKey?: string; closeOnItemSelect?: boolean; variantItems: VariantItem[]; - onSelect?: (event: CustomEvent<{item: HTMLElement; selectedItem: VariantItem}>) => void; + onSelect?: (event: CustomEvent<{ item: HTMLElement; selectedItem: VariantItem }>) => void; level?: TitleLevel; disabled?: boolean; } @@ -143,7 +143,7 @@ const VariantManagement: FC = forwardRef( const newSelectedKey = event.detail.item.dataset.key; const selectedItem = getItemByKey(newSelectedKey) || variantItems[0]; setSelectedKey(newSelectedKey); - onSelect(enrichEventWithDetails(event, { ...event.details, selectedItem})); + onSelect(enrichEventWithDetails(event, { ...event.details, selectedItem })); if (closeOnItemSelect) { handleCancelButtonClick(); } @@ -165,6 +165,7 @@ const VariantManagement: FC = forwardRef( style={style} tooltip={tooltip} {...passThroughProps} + // @ts-ignore onAfterOpen={handleAfterOpen} > diff --git a/packages/main/src/enums/AvatarBackgroundColor.ts b/packages/main/src/enums/AvatarBackgroundColor.ts new file mode 100644 index 00000000000..6596641dcb1 --- /dev/null +++ b/packages/main/src/enums/AvatarBackgroundColor.ts @@ -0,0 +1,13 @@ +export enum AvatarBackgroundColor { + Accent1 = 'Accent1', + Accent2 = 'Accent2', + Accent3 = 'Accent3', + Accent4 = 'Accent4', + Accent5 = 'Accent5', + Accent6 = 'Accent6', + Accent7 = 'Accent7', + Accent8 = 'Accent8', + Accent9 = 'Accent9', + Accent10 = 'Accent10', + Placeholder = 'Placeholder' +} diff --git a/packages/main/src/enums/AvatarFitType.ts b/packages/main/src/enums/AvatarFitType.ts new file mode 100644 index 00000000000..dfbdb433dd6 --- /dev/null +++ b/packages/main/src/enums/AvatarFitType.ts @@ -0,0 +1,4 @@ +export enum AvatarFitType { + Cover = 'Cover', + Contain = 'Contain' +} diff --git a/packages/main/src/enums/AvatarSize.ts b/packages/main/src/enums/AvatarSize.ts index d27765b96b0..aa48083e759 100644 --- a/packages/main/src/enums/AvatarSize.ts +++ b/packages/main/src/enums/AvatarSize.ts @@ -1,8 +1,7 @@ export enum AvatarSize { - XL = 'XL', - L = 'L', - M = 'M', - S = 'S', XS = 'XS', - Custom = 'Custom' + S = 'S', + M = 'M', + L = 'L', + XL = 'XL' } diff --git a/packages/main/src/enums/ButtonDesign.ts b/packages/main/src/enums/ButtonDesign.ts index fb6a27e1de5..2cd9b6d3e82 100644 --- a/packages/main/src/enums/ButtonDesign.ts +++ b/packages/main/src/enums/ButtonDesign.ts @@ -1,7 +1,7 @@ export enum ButtonDesign { Default = 'Default', + Positive = 'Positive', + Negative = 'Negative', Transparent = 'Transparent', - Accept = 'Positive', - Reject = 'Negative', Emphasized = 'Emphasized' } diff --git a/packages/main/src/enums/CarouselArrowsPlacement.ts b/packages/main/src/enums/CarouselArrowsPlacement.ts index 998983a1522..f5316bc984b 100644 --- a/packages/main/src/enums/CarouselArrowsPlacement.ts +++ b/packages/main/src/enums/CarouselArrowsPlacement.ts @@ -1,4 +1,4 @@ export enum CarouselArrowsPlacement { - PageIndicator = 'PageIndicator', + Navigation = 'Navigation', Content = 'Content' } diff --git a/packages/main/src/enums/InputType.ts b/packages/main/src/enums/InputType.ts index 61e666f946f..1949a9162d4 100644 --- a/packages/main/src/enums/InputType.ts +++ b/packages/main/src/enums/InputType.ts @@ -1,8 +1,8 @@ export enum InputType { + Text = 'Text', Email = 'Email', Number = 'Number', Password = 'Password', Tel = 'Tel', - Text = 'Text', - Url = 'Url' + URL = 'URL' } diff --git a/packages/main/src/enums/ListItemTypes.ts b/packages/main/src/enums/ListItemTypes.ts index 560872fde3e..dbc016feba3 100644 --- a/packages/main/src/enums/ListItemTypes.ts +++ b/packages/main/src/enums/ListItemTypes.ts @@ -1,4 +1,5 @@ export enum ListItemTypes { Inactive = 'Inactive', - Active = 'Active' + Active = 'Active', + Detail = 'Detail' } diff --git a/packages/main/src/enums/PopoverPlacementType.ts b/packages/main/src/enums/PopoverPlacementType.ts new file mode 100644 index 00000000000..fe76cbd76f7 --- /dev/null +++ b/packages/main/src/enums/PopoverPlacementType.ts @@ -0,0 +1,6 @@ +export enum PopoverPlacementType { + Left = 'Left', + Right = 'Right', + Top = 'Top', + Bottom = 'Bottom' +} diff --git a/packages/main/src/enums/TabLayout.ts b/packages/main/src/enums/TabLayout.ts new file mode 100644 index 00000000000..696840a68c6 --- /dev/null +++ b/packages/main/src/enums/TabLayout.ts @@ -0,0 +1,4 @@ +export enum TabLayout { + Inline = 'Inline', + Standard = 'Standard' +} diff --git a/packages/main/src/enums/Themes.ts b/packages/main/src/enums/Themes.ts index 8c360def333..6c9d8ff0ea4 100644 --- a/packages/main/src/enums/Themes.ts +++ b/packages/main/src/enums/Themes.ts @@ -1,4 +1,7 @@ export enum Themes { sap_fiori_3 = 'sap_fiori_3', - sap_fiori_3_dark = 'sap_fiori_3_dark' + sap_fiori_3_dark = 'sap_fiori_3_dark', + sap_belize = 'sap_belize', + sap_belize_hcb = 'sap_belize_hcb', + sap_belize_hcw = 'sap_belize_hcw' } diff --git a/packages/main/src/enums/ToastPlacement.ts b/packages/main/src/enums/ToastPlacement.ts new file mode 100644 index 00000000000..30e821bca38 --- /dev/null +++ b/packages/main/src/enums/ToastPlacement.ts @@ -0,0 +1,11 @@ +export enum ToastPlacement { + TopStart = 'TopStart', + TopCenter = 'TopCenter', + TopEnd = 'TopEnd', + MiddleStart = 'MiddleStart', + MiddleCenter = 'MiddleCenter', + MiddleEnd = 'MiddleEnd', + BottomStart = 'BottomStart', + BottomCenter = 'BottomCenter', + BottomEnd = 'BottomEnd' +} diff --git a/packages/main/src/enums/ZIndex.ts b/packages/main/src/enums/ZIndex.ts index 14d5890d422..6a51e97217a 100644 --- a/packages/main/src/enums/ZIndex.ts +++ b/packages/main/src/enums/ZIndex.ts @@ -3,6 +3,5 @@ export enum ZIndex { Dialog = 1000, MessageBox = 1100, ResponsivePopover = 1200, - InputModal = 1300, - MessageToast = 9999 + InputModal = 1300 } diff --git a/packages/main/src/index.ts b/packages/main/src/index.ts index 5419f997b6f..cadb4b23b76 100644 --- a/packages/main/src/index.ts +++ b/packages/main/src/index.ts @@ -8,10 +8,13 @@ import { AnalyticalCardHeader } from './lib/AnalyticalCardHeader'; import { AnalyticalTable } from './lib/AnalyticalTable'; import { AnalyticalTableScrollMode } from './lib/AnalyticalTableScrollMode'; import { Avatar } from './lib/Avatar'; +import { AvatarBackgroundColor } from './lib/AvatarBackgroundColor'; +import { AvatarFitType } from './lib/AvatarFitType'; import { AvatarShape } from './lib/AvatarShape'; import { AvatarSize } from './lib/AvatarSize'; import { Badge } from './lib/Badge'; import { Bar } from './lib/Bar'; +import { BarDesign } from './lib/BarDesign'; import { Breadcrumbs } from './lib/Breadcrumbs'; import { BreadcrumbsSeparatorStyle } from './lib/BreadcrumbsSeparatorStyle'; import { BusyIndicator } from './lib/BusyIndicator'; @@ -24,12 +27,15 @@ import { Card } from './lib/Card'; import { Carousel } from './lib/Carousel'; import { CarouselArrowsPlacement } from './lib/CarouselArrowsPlacement'; import { CheckBox } from './lib/CheckBox'; +import { ComboBox } from './lib/ComboBox'; +import { ComboBoxItem } from './lib/ComboBoxItem'; import { ContentDensity } from './lib/ContentDensity'; import { CurrentViewportRangeContext } from './lib/CurrentViewportRangeContext'; import { CustomListItem } from './lib/CustomListItem'; import { DatePicker } from './lib/DatePicker'; import { DeviationIndicator } from './lib/DeviationIndicator'; import { Dialog } from './lib/Dialog'; +import { FileUploader } from './lib/FileUploader'; import { FilterBar } from './lib/FilterBar'; import { FilterItem } from './lib/FilterItem'; import { FilterType } from './lib/FilterType'; @@ -61,8 +67,8 @@ import { MessageBoxActions } from './lib/MessageBoxActions'; import { MessageBoxTypes } from './lib/MessageBoxTypes'; import { MessageStrip } from './lib/MessageStrip'; import { MessageStripType } from './lib/MessageStripType'; -import { MessageToast } from './lib/MessageToast'; import { MultiComboBox } from './lib/MultiComboBox'; +import { MultiComboBoxItem } from './lib/MultiComboBoxItem'; import { Notification } from './lib/Notification'; import { NotificationGroup } from './lib/NotificationGroup'; import { ObjectPage } from './lib/ObjectPage'; @@ -78,14 +84,15 @@ import { PanelAccessibleRoles } from './lib/PanelAccessibleRoles'; import { PlacementType } from './lib/PlacementType'; import { Popover } from './lib/Popover'; import { PopoverHorizontalAlign } from './lib/PopoverHorizontalAlign'; +import { PopoverPlacementType } from './lib/PopoverPlacementType'; import { PopoverVerticalAlign } from './lib/PopoverVerticalAlign'; import { Priority } from './lib/Priority'; import { ProductSwitch } from './lib/ProductSwitch'; import { ProductSwitchItem } from './lib/ProductSwitchItem'; import { ProgressIndicator } from './lib/ProgressIndicator'; import { RadioButton } from './lib/RadioButton'; +import { ResponsivePopover } from './lib/ResponsivePopover'; import { SegmentedButton } from './lib/SegmentedButton'; -import { SegmentedButtonItem } from './lib/SegmentedButtonItem'; import { Select } from './lib/Select'; import { SemanticColor } from './lib/SemanticColor'; import { ShellBar } from './lib/ShellBar'; @@ -96,9 +103,11 @@ import { SideNavigationOpenState } from './lib/SideNavigationOpenState'; import { Size } from './lib/Size'; import { Spinner } from './lib/Spinner'; import { StandardListItem } from './lib/StandardListItem'; +import { SuggestionItem } from './lib/SuggestionItem'; import { Switch } from './lib/Switch'; import { Tab } from './lib/Tab'; import { TabContainer } from './lib/TabContainer'; +import { TabLayout } from './lib/TabLayout'; import { TabSeparator } from './lib/TabSeparator'; import { Table } from './lib/Table'; import { TableCell } from './lib/TableCell'; @@ -112,10 +121,13 @@ import { TextAlign } from './lib/TextAlign'; import { TextArea } from './lib/TextArea'; import { ThemeProvider } from './lib/ThemeProvider'; import { Themes } from './lib/Themes'; +import { TimePicker } from './lib/TimePicker'; import { Timeline } from './lib/Timeline'; import { TimelineItem } from './lib/TimelineItem'; import { Title } from './lib/Title'; import { TitleLevel } from './lib/TitleLevel'; +import { Toast } from './lib/Toast'; +import { ToastPlacement } from './lib/ToastPlacement'; import { ToggleButton } from './lib/ToggleButton'; import { Token } from './lib/Token'; import { Tokenizer } from './lib/Tokenizer'; @@ -130,10 +142,13 @@ export { AnalyticalTable, AnalyticalTableScrollMode, Avatar, + AvatarBackgroundColor, + AvatarFitType, AvatarShape, AvatarSize, Badge, Bar, + BarDesign, Breadcrumbs, BreadcrumbsSeparatorStyle, BusyIndicator, @@ -146,12 +161,15 @@ export { Carousel, CarouselArrowsPlacement, CheckBox, + ComboBox, + ComboBoxItem, ContentDensity, CurrentViewportRangeContext, CustomListItem, DatePicker, DeviationIndicator, Dialog, + FileUploader, FilterBar, FilterItem, FilterType, @@ -183,8 +201,8 @@ export { MessageBoxTypes, MessageStrip, MessageStripType, - MessageToast, MultiComboBox, + MultiComboBoxItem, Notification, NotificationGroup, ObjectPage, @@ -200,14 +218,15 @@ export { PlacementType, Popover, PopoverHorizontalAlign, + PopoverPlacementType, PopoverVerticalAlign, Priority, ProductSwitch, ProductSwitchItem, ProgressIndicator, RadioButton, + ResponsivePopover, SegmentedButton, - SegmentedButtonItem, Select, SemanticColor, ShellBar, @@ -218,9 +237,11 @@ export { Size, Spinner, StandardListItem, + SuggestionItem, Switch, Tab, TabContainer, + TabLayout, TabSeparator, Table, TableCell, @@ -234,10 +255,13 @@ export { TextArea, ThemeProvider, Themes, + TimePicker, Timeline, TimelineItem, Title, TitleLevel, + Toast, + ToastPlacement, ToggleButton, Token, Tokenizer, diff --git a/packages/main/src/interfaces/UI5WebComponentsReactPopoverPropTypes.ts b/packages/main/src/interfaces/UI5WebComponentsReactPopoverPropTypes.ts new file mode 100644 index 00000000000..43627b2d487 --- /dev/null +++ b/packages/main/src/interfaces/UI5WebComponentsReactPopoverPropTypes.ts @@ -0,0 +1,8 @@ +import { CSSProperties, ReactNode } from 'react'; + +export interface UI5WebComponentsReactPopoverPropTypes { + openByStyle?: CSSProperties; + openBy?: ReactNode; + open?: boolean; + propagateOpenByClickEvent?: boolean; +} diff --git a/packages/main/src/interfaces/Ui5ResponsivePopoverDomRef.ts b/packages/main/src/interfaces/Ui5ResponsivePopoverDomRef.ts new file mode 100644 index 00000000000..283b8999ac2 --- /dev/null +++ b/packages/main/src/interfaces/Ui5ResponsivePopoverDomRef.ts @@ -0,0 +1,6 @@ +import { Ui5DomRef } from './Ui5DomRef'; + +export interface Ui5ResponsivePopoverDomRef extends Ui5DomRef { + open: (p: HTMLElement) => void; + close: () => void; +} diff --git a/packages/main/src/interfaces/Ui5WebComponentMetadata.ts b/packages/main/src/interfaces/Ui5WebComponentMetadata.ts index 84cff2e9dfa..7fcb36e7523 100644 --- a/packages/main/src/interfaces/Ui5WebComponentMetadata.ts +++ b/packages/main/src/interfaces/Ui5WebComponentMetadata.ts @@ -4,7 +4,7 @@ import { Ui5Property } from './Ui5Property'; export interface Ui5WebComponentMetadata { properties?: DynamicObjectList; getProperties?: () => DynamicObjectList; - getPropsList?: () => string[]; + getPropertiesList?: () => string[]; events?: DynamicObjectList; getSlots?: () => DynamicObjectList; getEvents?: () => DynamicObjectList; diff --git a/packages/main/src/internal/WithWebComponent.test.tsx b/packages/main/src/internal/WithWebComponent.test.tsx index ab41f5be0ad..1bae3d90fea 100644 --- a/packages/main/src/internal/WithWebComponent.test.tsx +++ b/packages/main/src/internal/WithWebComponent.test.tsx @@ -1,12 +1,11 @@ import { mount } from 'enzyme'; -import UI5Button from '@ui5/webcomponents/dist/Button'; +import { Button } from '@ui5/webcomponents-react/lib/Button'; import React, { cloneElement, FC } from 'react'; import { spy } from 'sinon'; import { withWebComponent } from './withWebComponent'; describe('withWebComponent', () => { test('Unmount Event Handlers correctly after prop update', () => { - const Button: FC = withWebComponent(UI5Button); const callback = spy(); // eslint-disable-next-line react/jsx-no-bind const wrapper = mount(
    } + placementType={select('placementType', PlacementType, PlacementType.Right)} + verticalAlign={select('verticalAlign', PopoverVerticalAlign, PopoverVerticalAlign.Center)} footer={
    (
    } + header={null} + onAfterClose={action('onAfterClose')} + onAfterOpen={action('onAfterOpen')} + onBeforeClose={action('onBeforeClose')} + onBeforeOpen={action('onBeforeOpen')} openBy={} > -
    Header
    -
    Content
    -
    Footer
    + Some Content ); -defaultStory.story = { - name: 'Default' +generatedDefaultStory.story = { + name: 'Generated default story' }; diff --git a/packages/main/src/webComponents/Popover/Popover.test.tsx b/packages/main/src/webComponents/Popover/Popover.test.tsx index f025a2b551f..0a47c30b1ac 100644 --- a/packages/main/src/webComponents/Popover/Popover.test.tsx +++ b/packages/main/src/webComponents/Popover/Popover.test.tsx @@ -1,5 +1,5 @@ -import { mount } from 'enzyme'; import { Popover } from '@ui5/webcomponents-react/lib/Popover'; +import { mount } from 'enzyme'; import React from 'react'; describe('Popover', () => { diff --git a/packages/main/src/webComponents/Popover/__snapshots__/Popover.test.tsx.snap b/packages/main/src/webComponents/Popover/__snapshots__/Popover.test.tsx.snap index 6f40eb81732..6a1d3ab8573 100644 --- a/packages/main/src/webComponents/Popover/__snapshots__/Popover.test.tsx.snap +++ b/packages/main/src/webComponents/Popover/__snapshots__/Popover.test.tsx.snap @@ -3,6 +3,7 @@ exports[`Popover Basic Test (generated) 1`] = ` diff --git a/packages/main/src/webComponents/Popover/index.tsx b/packages/main/src/webComponents/Popover/index.tsx index 72c54ff366a..52055ffd6dc 100644 --- a/packages/main/src/webComponents/Popover/index.tsx +++ b/packages/main/src/webComponents/Popover/index.tsx @@ -1,34 +1,75 @@ -import { enrichEventWithDetails } from '@ui5/webcomponents-react-base/lib/Utils'; import { useConsolidatedRef } from '@ui5/webcomponents-react-base/lib/useConsolidatedRef'; import { PlacementType } from '@ui5/webcomponents-react/lib/PlacementType'; import { PopoverHorizontalAlign } from '@ui5/webcomponents-react/lib/PopoverHorizontalAlign'; import { PopoverVerticalAlign } from '@ui5/webcomponents-react/lib/PopoverVerticalAlign'; import { withWebComponent } from '@ui5/webcomponents-react/lib/withWebComponent'; import UI5Popover from '@ui5/webcomponents/dist/Popover'; -import React, { CSSProperties, FC, ReactNode, RefObject, useCallback, useEffect, useMemo, useRef } from 'react'; +import React, { FC, ReactNode, RefObject, useCallback, useEffect, useMemo, useRef } from 'react'; import { Ui5PopoverDomRef } from '../../interfaces/Ui5PopoverDomRef'; +import { UI5WebComponentsReactPopoverPropTypes } from '../../interfaces/UI5WebComponentsReactPopoverPropTypes'; import { WithWebComponentPropTypes } from '../../internal/withWebComponent'; export interface PopoverPropTypes extends WithWebComponentPropTypes { - initialFocus?: string; // @generated - headerText?: string; // @generated - placementType?: PlacementType; // @generated - horizontalAlign?: PopoverHorizontalAlign; // @generated - verticalAlign?: PopoverVerticalAlign; // @generated - modal?: boolean; // @generated - noArrow?: boolean; // @generated - allowTargetOverlap?: boolean; // @generated - onBeforeOpen?: (event: CustomEvent) => void; // @generated - onAfterOpen?: (event: CustomEvent) => void; // @generated - onBeforeClose?: (event: CustomEvent) => void; // @generated - onAfterClose?: (event: CustomEvent) => void; // @generated - header?: ReactNode; // @generated - footer?: ReactNode; // @generated - content?: ReactNode | ReactNode[]; - openByStyle?: CSSProperties; - openBy?: ReactNode; - open?: boolean; - propagateOpenByClickEvent?: boolean; + /** + * Determines if there is no enough space, the ui5-popover can be placed over the target. + */ + allowTargetOverlap?: boolean; + /** + * Defines the header text.

    Note: If header slot is provided, the headerText is ignored. + */ + headerText?: string; + /** + * Determines the horizontal alignment of the ui5-popover.

    Available options are:
    • Center
    • Left
    • Right
    • Stretch
    + */ + horizontalAlign?: PopoverHorizontalAlign; + /** + * Defines the ID of the HTML Element, which will get the initial focus. + */ + initialFocus?: string; + /** + * Defines whether the ui5-popover should close when clicking/tapping outside of the popover. If enabled, it blocks any interaction with the background. + */ + modal?: boolean; + /** + * Determines whether the ui5-popover arrow is hidden. + */ + noArrow?: boolean; + /** + * Determines on which side the ui5-popover is placed at.

    Available options are:
    • Left
    • Right
    • Top
    • Bottom
    + */ + placementType?: PlacementType; + /** + * Determines the vertical alignment of the ui5-popover.

    Available options are:
    • Center
    • Top
    • Bottom
    • Stretch
    + */ + verticalAlign?: PopoverVerticalAlign; + /** + * Defines the header HTML Element. + */ + header?: ReactNode | ReactNode[]; + /** + * Defines the footer HTML Element. + */ + footer?: ReactNode | ReactNode[]; + /** + * Defines the content of the Web Component. + */ + children?: ReactNode | ReactNode[]; + /** + * Fired after the component is closed. + */ + onAfterClose?: (event: CustomEvent<{}>) => void; + /** + * Fired after the component is opened. + */ + onAfterOpen?: (event: CustomEvent<{}>) => void; + /** + * Fired before the component is closed. + */ + onBeforeClose?: (event: CustomEvent<{ escPressed: boolean }>) => void; + /** + * Fired before the component is opened. + */ + onBeforeOpen?: (event: CustomEvent<{}>) => void; } const InternalPopover = withWebComponent(UI5Popover); @@ -38,8 +79,8 @@ const InternalPopover = withWebComponent(UI5Popover); *
    * UI5 Web Components Playground */ -export const Popover: FC = React.forwardRef( - (props: PopoverPropTypes, givenRef: RefObject) => { +const Popover: FC = React.forwardRef( + (props: PopoverPropTypes & UI5WebComponentsReactPopoverPropTypes, givenRef: RefObject) => { const { propagateOpenByClickEvent, openBy, openByStyle, open, ...rest } = props; const openByRef: RefObject = useRef(null); @@ -48,7 +89,9 @@ export const Popover: FC = React.forwardRef( const handleOpenPopover = useCallback( (e) => { - internalPopoverRef.current.openBy && internalPopoverRef.current.openBy(openByRef.current); + if (internalPopoverRef.current) { + internalPopoverRef.current.openBy(openByRef.current); + } if (e && !propagateOpenByClickEvent) { e.stopPropagation(); } @@ -57,7 +100,9 @@ export const Popover: FC = React.forwardRef( ); const closePopover = useCallback(() => { - internalPopoverRef.current.close && internalPopoverRef.current.close(); + if (internalPopoverRef.current) { + internalPopoverRef.current.close(); + } }, [internalPopoverRef]); useEffect(() => { @@ -89,11 +134,16 @@ export const Popover: FC = React.forwardRef( ); Popover.defaultProps = { - initialFocus: null, // @generated - headerText: null, // @generated - placementType: PlacementType.Right, // @generated - horizontalAlign: PopoverHorizontalAlign.Center, // @generated - verticalAlign: PopoverVerticalAlign.Center, // @generated + allowTargetOverlap: false, + horizontalAlign: PopoverHorizontalAlign.Center, + initialFocus: '', + modal: false, + noArrow: false, + placementType: PlacementType.Right, + verticalAlign: PopoverVerticalAlign.Center, propagateOpenByClickEvent: true }; + Popover.displayName = 'Popover'; + +export { Popover }; diff --git a/packages/main/src/webComponents/ProductSwitch/ProductSwitch.stories.tsx b/packages/main/src/webComponents/ProductSwitch/ProductSwitch.stories.tsx new file mode 100644 index 00000000000..33bd483893d --- /dev/null +++ b/packages/main/src/webComponents/ProductSwitch/ProductSwitch.stories.tsx @@ -0,0 +1,28 @@ +import '@ui5/webcomponents-icons/dist/icons/business-objects-experience'; +import '@ui5/webcomponents-icons/dist/icons/contacts'; +import '@ui5/webcomponents-icons/dist/icons/flight'; +import '@ui5/webcomponents-icons/dist/icons/home'; +import { ProductSwitch } from '@ui5/webcomponents-react/lib/ProductSwitch'; +import { ProductSwitchItem } from '@ui5/webcomponents-react/lib/ProductSwitchItem'; +import React from 'react'; + +export default { + title: 'UI5 Web Components / ProductSwitch', + component: ProductSwitch, + parameters: { + subcomponents: { ProductSwitchItem } + } +}; + +export const generatedDefaultStory = () => ( + + + + + + +); + +generatedDefaultStory.story = { + name: 'Generated default story' +}; diff --git a/packages/main/src/webComponents/ProductSwitch/ProductSwitch.test.tsx b/packages/main/src/webComponents/ProductSwitch/ProductSwitch.test.tsx index 8f2e8b691a7..2e3266cc589 100644 --- a/packages/main/src/webComponents/ProductSwitch/ProductSwitch.test.tsx +++ b/packages/main/src/webComponents/ProductSwitch/ProductSwitch.test.tsx @@ -1,5 +1,5 @@ -import { mount } from 'enzyme'; import { ProductSwitch } from '@ui5/webcomponents-react/lib/ProductSwitch'; +import { mount } from 'enzyme'; import React from 'react'; describe('ProductSwitch', () => { diff --git a/packages/main/src/webComponents/ProductSwitch/demo.stories.tsx b/packages/main/src/webComponents/ProductSwitch/demo.stories.tsx deleted file mode 100644 index 41795526b03..00000000000 --- a/packages/main/src/webComponents/ProductSwitch/demo.stories.tsx +++ /dev/null @@ -1,41 +0,0 @@ -import { text } from '@storybook/addon-knobs'; -import { ProductSwitch } from '@ui5/webcomponents-react/lib/ProductSwitch'; -import { ProductSwitchItem } from '@ui5/webcomponents-react/lib/ProductSwitchItem'; -import React from 'react'; - -export default { - title: 'UI5 Web Components / ProductSwitch', - component: ProductSwitch, - parameters: { - subcomponents: { ProductSwitchItem } - } -}; - -export const generatedDefaultStory = () => ( - - - - - -); - -generatedDefaultStory.story = { - name: 'Generated Default Story' -}; diff --git a/packages/main/src/webComponents/ProductSwitch/index.tsx b/packages/main/src/webComponents/ProductSwitch/index.tsx index 6a460b2dd4b..ab1b1caf87a 100644 --- a/packages/main/src/webComponents/ProductSwitch/index.tsx +++ b/packages/main/src/webComponents/ProductSwitch/index.tsx @@ -4,7 +4,10 @@ import React, { FC, ReactNode } from 'react'; import { WithWebComponentPropTypes } from '../../internal/withWebComponent'; export interface ProductSwitchPropTypes extends WithWebComponentPropTypes { - children?: ReactNode | ReactNode[]; // @generated + /** + * Defines the items of the ui5-product-switch. + */ + children?: ReactNode | ReactNode[]; } /** @@ -16,4 +19,6 @@ const ProductSwitch: FC = withWebComponent { diff --git a/packages/main/src/webComponents/ProductSwitchItem/__snapshots__/ProductSwitchItem.test.tsx.snap b/packages/main/src/webComponents/ProductSwitchItem/__snapshots__/ProductSwitchItem.test.tsx.snap index 82c12becd0e..af75260d02a 100644 --- a/packages/main/src/webComponents/ProductSwitchItem/__snapshots__/ProductSwitchItem.test.tsx.snap +++ b/packages/main/src/webComponents/ProductSwitchItem/__snapshots__/ProductSwitchItem.test.tsx.snap @@ -2,6 +2,10 @@ exports[`ProductSwitchItem Basic Test (generated) 1`] = ` `; diff --git a/packages/main/src/webComponents/ProductSwitchItem/index.tsx b/packages/main/src/webComponents/ProductSwitchItem/index.tsx index d4932b1e157..96ca6d44aad 100644 --- a/packages/main/src/webComponents/ProductSwitchItem/index.tsx +++ b/packages/main/src/webComponents/ProductSwitchItem/index.tsx @@ -1,20 +1,41 @@ import UI5ProductSwitchItem from '@ui5/webcomponents-fiori/dist/ProductSwitchItem'; -import { enrichEventWithDetails } from '@ui5/webcomponents-react-base/lib/Utils'; import { withWebComponent } from '@ui5/webcomponents-react/lib/withWebComponent'; import React, { FC } from 'react'; import { WithWebComponentPropTypes } from '../../internal/withWebComponent'; export interface ProductSwitchItemPropTypes extends WithWebComponentPropTypes { - heading?: string; // @generated - subtitle?: string; // @generated - icon?: string; // @generated - target?: string; // @generated - targetSrc?: string; // @generated - onClick?: (event: CustomEvent) => void; // @generated + /** + * Defines the title of the ui5-product-switch-item. + */ + heading?: string; + /** + * Defines the icon to be displayed as a graphical element within the ui5-product-switch-item.

    Example:
    ui5-product-switch-item icon="palette"
    + +See all the available icons in the Icon Explorer. + */ + icon?: string; + /** + * Defines the subtitle of the ui5-product-switch-item. + */ + subtitle?: string; + /** + * Defines a target where the targetSrc content must be open.

    Available options are:
    • _self
    • _top
    • _blank
    • _parent
    • _search
    + */ + target?: string; + /** + * Defines the ui5-product-switch-item target URI. Supports standard hyperlink behavior. + */ + targetSrc?: string; + /** + * Fired when the ui5-product-switch-item is activated either with a click/tap or by using the Enter or Space key. + */ + onClick?: (event: CustomEvent<{}>) => void; } /** * import { ProductSwitchItem } from '@ui5/webcomponents-react/lib/ProductSwitchItem'; + *
    + * UI5 Web Components Playground */ const ProductSwitchItem: FC = withWebComponent( UI5ProductSwitchItem @@ -23,7 +44,11 @@ const ProductSwitchItem: FC = withWebComponent ( +export const generatedDefaultStory = () => ( ); -defaultStory.story = { - name: 'Default' +generatedDefaultStory.story = { + name: 'Generated default story' }; diff --git a/packages/main/src/webComponents/RadioButton/RadioButton.test.tsx b/packages/main/src/webComponents/RadioButton/RadioButton.test.tsx index 43e23765f37..de0bacafb81 100644 --- a/packages/main/src/webComponents/RadioButton/RadioButton.test.tsx +++ b/packages/main/src/webComponents/RadioButton/RadioButton.test.tsx @@ -1,5 +1,5 @@ -import { mount } from 'enzyme'; import { RadioButton } from '@ui5/webcomponents-react/lib/RadioButton'; +import { mount } from 'enzyme'; import React from 'react'; describe('RadioButton', () => { diff --git a/packages/main/src/webComponents/RadioButton/__snapshots__/RadioButton.test.tsx.snap b/packages/main/src/webComponents/RadioButton/__snapshots__/RadioButton.test.tsx.snap index 6a865ea25dd..f21559915b4 100644 --- a/packages/main/src/webComponents/RadioButton/__snapshots__/RadioButton.test.tsx.snap +++ b/packages/main/src/webComponents/RadioButton/__snapshots__/RadioButton.test.tsx.snap @@ -2,6 +2,8 @@ exports[`RadioButton Basic Test (generated) 1`] = ` `; diff --git a/packages/main/src/webComponents/RadioButton/index.tsx b/packages/main/src/webComponents/RadioButton/index.tsx index 8e932bf9e40..59da4838c3e 100644 --- a/packages/main/src/webComponents/RadioButton/index.tsx +++ b/packages/main/src/webComponents/RadioButton/index.tsx @@ -1,4 +1,3 @@ -import { enrichEventWithDetails } from '@ui5/webcomponents-react-base/lib/Utils'; import { ValueState } from '@ui5/webcomponents-react/lib/ValueState'; import { withWebComponent } from '@ui5/webcomponents-react/lib/withWebComponent'; import UI5RadioButton from '@ui5/webcomponents/dist/RadioButton'; @@ -6,14 +5,46 @@ import React, { FC } from 'react'; import { WithWebComponentPropTypes } from '../../internal/withWebComponent'; export interface RadioButtonPropTypes extends WithWebComponentPropTypes { - disabled?: boolean; // @generated - readonly?: boolean; // @generated - selected?: boolean; // @generated - text?: string; // @generated - valueState?: ValueState; // @generated - name?: string; // @generated - value?: string; // @generated - onSelect?: (event: CustomEvent) => void; // @generated + /** + * Determines whether the ui5-radiobutton is disabled.

    Note: A disabled ui5-radiobutton is completely noninteractive. + */ + disabled?: boolean; + /** + * Defines the name of the ui5-radiobutton. Radio buttons with the same name will form a radio button group. + *

    Note: The selection can be changed with ARROW_UP/DOWN and ARROW_LEFT/RIGHT keys between radio buttons in same group. + *

    Note: Only one radio button can be selected per group. + *

    Important: For the name property to have effect when submitting forms, you must add the following import to your project: import "@ui5/webcomponents/dist/features/InputElementsFormSupport.js"; + *

    Note: When set, a native input HTML element will be created inside the ui5-radiobutton so that it can be submitted as part of an HTML form. + */ + name?: string; + /** + * Determines whether the ui5-radiobutton is read-only.

    Note: A read-only ui5-radiobutton is not editable, but still provides visual feedback upon user interaction. + */ + readonly?: boolean; + /** + * Determines whether the ui5-radiobutton is selected or not.

    Note: The property value can be changed with user interaction, either by cliking/tapping on the ui5-radiobutton, or by using the Space or Enter key. + */ + selected?: boolean; + /** + * Defines the text of the ui5-radiobutton. + */ + text?: string; + /** + * Defines the form value of the ui5-radiobutton. When a form with a radio button group is submitted, the group's value will be the value of the currently selected radio button.
    Important: For the value property to have effect, you must add the following import to your project: import "@ui5/webcomponents/dist/features/InputElementsFormSupport.js"; + */ + value?: string; + /** + * Defines the value state of the ui5-radiobutton.

    Available options are:
    • None
    • Error
    • Warning
    + */ + valueState?: ValueState; + /** + * Defines whether the ui5-radiobutton text wraps when there is not enough space.

    Note: By default, the text truncates when there is not enough space. + */ + wrap?: boolean; + /** + * Fired when the ui5-radiobutton selected state changes. + */ + onSelect?: (event: CustomEvent<{}>) => void; } /** @@ -26,7 +57,13 @@ const RadioButton: FC = withWebComponent ( + + +
    + } + header={null} + onAfterClose={action('onAfterClose')} + onAfterOpen={action('onAfterOpen')} + onBeforeClose={action('onBeforeClose')} + onBeforeOpen={action('onBeforeOpen')} + openBy={} + > + Some Content + +); + +generatedDefaultStory.story = { + name: 'Generated default story' +}; diff --git a/packages/main/src/webComponents/ResponsivePopover/ResponsivePopover.test.tsx b/packages/main/src/webComponents/ResponsivePopover/ResponsivePopover.test.tsx new file mode 100644 index 00000000000..1748679df6e --- /dev/null +++ b/packages/main/src/webComponents/ResponsivePopover/ResponsivePopover.test.tsx @@ -0,0 +1,10 @@ +import { ResponsivePopover } from '@ui5/webcomponents-react/lib/ResponsivePopover'; +import { mount } from 'enzyme'; +import React from 'react'; + +describe('ResponsivePopover', () => { + test('Basic Test (generated)', () => { + const wrapper = mount(); + expect(wrapper.render()).toMatchSnapshot(); + }); +}); diff --git a/packages/main/src/webComponents/ResponsivePopover/__snapshots__/ResponsivePopover.test.tsx.snap b/packages/main/src/webComponents/ResponsivePopover/__snapshots__/ResponsivePopover.test.tsx.snap new file mode 100644 index 00000000000..4c85e7ee41d --- /dev/null +++ b/packages/main/src/webComponents/ResponsivePopover/__snapshots__/ResponsivePopover.test.tsx.snap @@ -0,0 +1,10 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`ResponsivePopover Basic Test (generated) 1`] = ` + +`; diff --git a/packages/main/src/webComponents/ResponsivePopover/index.tsx b/packages/main/src/webComponents/ResponsivePopover/index.tsx new file mode 100644 index 00000000000..a1cf534f479 --- /dev/null +++ b/packages/main/src/webComponents/ResponsivePopover/index.tsx @@ -0,0 +1,151 @@ +import { useConsolidatedRef } from '@ui5/webcomponents-react-base/lib/useConsolidatedRef'; +import { PlacementType } from '@ui5/webcomponents-react/lib/PlacementType'; +import { PopoverHorizontalAlign } from '@ui5/webcomponents-react/lib/PopoverHorizontalAlign'; +import { PopoverVerticalAlign } from '@ui5/webcomponents-react/lib/PopoverVerticalAlign'; +import { withWebComponent } from '@ui5/webcomponents-react/lib/withWebComponent'; +import UI5ResponsivePopover from '@ui5/webcomponents/dist/ResponsivePopover'; +import React, { FC, ReactNode, RefObject, useCallback, useEffect, useMemo, useRef } from 'react'; +import { Ui5ResponsivePopoverDomRef } from '../../interfaces/Ui5ResponsivePopoverDomRef'; +import { UI5WebComponentsReactPopoverPropTypes } from '../../interfaces/UI5WebComponentsReactPopoverPropTypes'; +import { WithWebComponentPropTypes } from '../../internal/withWebComponent'; + +export interface ResponsivePopoverPropTypes extends WithWebComponentPropTypes { + /** + * Determines if there is no enough space, the ui5-popover can be placed over the target. + */ + allowTargetOverlap?: boolean; + /** + * Defines the header text.

    Note: If header slot is provided, the headerText is ignored. + */ + headerText?: string; + /** + * Determines the horizontal alignment of the ui5-popover.

    Available options are:
    • Center
    • Left
    • Right
    • Stretch
    + */ + horizontalAlign?: PopoverHorizontalAlign; + /** + * Defines the ID of the HTML Element, which will get the initial focus. + */ + initialFocus?: string; + /** + * Defines whether the ui5-popover should close when clicking/tapping outside of the popover. If enabled, it blocks any interaction with the background. + */ + modal?: boolean; + /** + * Determines whether the ui5-popover arrow is hidden. + */ + noArrow?: boolean; + /** + * Determines on which side the ui5-popover is placed at.

    Available options are:
    • Left
    • Right
    • Top
    • Bottom
    + */ + placementType?: PlacementType; + /** + * Determines the vertical alignment of the ui5-popover.

    Available options are:
    • Center
    • Top
    • Bottom
    • Stretch
    + */ + verticalAlign?: PopoverVerticalAlign; + /** + * Defines the header HTML Element. + */ + header?: ReactNode | ReactNode[]; + /** + * Defines the footer HTML Element. + */ + footer?: ReactNode | ReactNode[]; + /** + * Defines the content of the Web Component. + */ + children?: ReactNode | ReactNode[]; + /** + * Fired after the component is closed. + */ + onAfterClose?: (event: CustomEvent<{}>) => void; + /** + * Fired after the component is opened. + */ + onAfterOpen?: (event: CustomEvent<{}>) => void; + /** + * Fired before the component is closed. + */ + onBeforeClose?: (event: CustomEvent<{ escPressed: boolean }>) => void; + /** + * Fired before the component is opened. + */ + onBeforeOpen?: (event: CustomEvent<{}>) => void; +} + +const ResponsivePopoverWebComponent = withWebComponent(UI5ResponsivePopover); + +/** + * import { ResponsivePopover } from '@ui5/webcomponents-react/lib/ResponsivePopover'; + *
    + * UI5 Web Components Playground + */ +const ResponsivePopover: FC = React.forwardRef( + ( + props: ResponsivePopoverPropTypes & UI5WebComponentsReactPopoverPropTypes, + givenRef: RefObject + ) => { + const { propagateOpenByClickEvent, openBy, openByStyle, open, ...rest } = props; + const openByRef: RefObject = useRef(null); + + const internalPopoverRef = useConsolidatedRef(givenRef); + + const handleOpenPopover = useCallback( + (e) => { + if (internalPopoverRef.current) { + internalPopoverRef.current.open(openByRef.current); + } + if (e && !propagateOpenByClickEvent) { + e.stopPropagation(); + } + }, + [internalPopoverRef, openByRef] + ); + + const closePopover = useCallback(() => { + if (internalPopoverRef.current) { + internalPopoverRef.current.close(); + } + }, [internalPopoverRef]); + + useEffect(() => { + if (open) { + handleOpenPopover(null); + } else { + closePopover(); + } + }, [open]); + + const style = useMemo(() => { + return { + display: 'inline-block', + ...openByStyle + }; + }, [openByStyle]); + + return ( + <> + {openBy && ( +
    + {openBy} +
    + )} + + + ); + } +); + +ResponsivePopover.displayName = 'ResponsivePopover'; + +ResponsivePopover.defaultProps = { + allowTargetOverlap: false, + horizontalAlign: PopoverHorizontalAlign.Center, + initialFocus: '', + modal: false, + noArrow: false, + placementType: PlacementType.Right, + verticalAlign: PopoverVerticalAlign.Center, + propagateOpenByClickEvent: true +}; + +export { ResponsivePopover }; diff --git a/packages/main/src/webComponents/SegmentedButton/SegmentedButton.stories.tsx b/packages/main/src/webComponents/SegmentedButton/SegmentedButton.stories.tsx new file mode 100644 index 00000000000..9a8f426300d --- /dev/null +++ b/packages/main/src/webComponents/SegmentedButton/SegmentedButton.stories.tsx @@ -0,0 +1,24 @@ +import { action } from '@storybook/addon-actions'; +import { SegmentedButton } from '@ui5/webcomponents-react/lib/SegmentedButton'; +import { ToggleButton } from '@ui5/webcomponents-react/lib/ToggleButton'; +import React from 'react'; + +export default { + title: 'UI5 Web Components / SegmentedButton', + component: SegmentedButton, + parameters: { + subcomponents: { ToggleButton } + } +}; + +export const generatedDefaultStory = () => ( + + Button 1 + Button 2 + Button 3 + +); + +generatedDefaultStory.story = { + name: 'Generated default story' +}; diff --git a/packages/main/src/webComponents/SegmentedButton/SegmentedButton.test.tsx b/packages/main/src/webComponents/SegmentedButton/SegmentedButton.test.tsx new file mode 100644 index 00000000000..b57433b6592 --- /dev/null +++ b/packages/main/src/webComponents/SegmentedButton/SegmentedButton.test.tsx @@ -0,0 +1,10 @@ +import { SegmentedButton } from '@ui5/webcomponents-react/lib/SegmentedButton'; +import { mount } from 'enzyme'; +import React from 'react'; + +describe('SegmentedButton', () => { + test('Basic Test (generated)', () => { + const wrapper = mount(); + expect(wrapper.render()).toMatchSnapshot(); + }); +}); diff --git a/packages/main/src/webComponents/SegmentedButton/__snapshots__/SegmentedButton.test.tsx.snap b/packages/main/src/webComponents/SegmentedButton/__snapshots__/SegmentedButton.test.tsx.snap new file mode 100644 index 00000000000..9ccb6ed0d90 --- /dev/null +++ b/packages/main/src/webComponents/SegmentedButton/__snapshots__/SegmentedButton.test.tsx.snap @@ -0,0 +1,3 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`SegmentedButton Basic Test (generated) 1`] = ``; diff --git a/packages/main/src/webComponents/SegmentedButton/index.tsx b/packages/main/src/webComponents/SegmentedButton/index.tsx new file mode 100644 index 00000000000..e3c6670abd0 --- /dev/null +++ b/packages/main/src/webComponents/SegmentedButton/index.tsx @@ -0,0 +1,28 @@ +import { withWebComponent } from '@ui5/webcomponents-react/lib/withWebComponent'; +import UI5SegmentedButton from '@ui5/webcomponents/dist/SegmentedButton'; +import React, { FC, ReactNode } from 'react'; +import { WithWebComponentPropTypes } from '../../internal/withWebComponent'; + +export interface SegmentedButtonPropTypes extends WithWebComponentPropTypes { + /** + * Defines the buttons of ui5-segmentedbutton.

    Note: Multiple buttons are allowed.

    Note: Use the ui5-togglebutton for the intended design. + */ + children?: ReactNode | ReactNode[]; + /** + * Fired when the selected button changes. + */ + onSelectionChange?: (event: CustomEvent<{ selectedButton: ReactNode }>) => void; +} + +/** + * import { SegmentedButton } from '@ui5/webcomponents-react/lib/SegmentedButton'; + *
    + * UI5 Web Components Playground + */ +const SegmentedButton: FC = withWebComponent(UI5SegmentedButton); + +SegmentedButton.displayName = 'SegmentedButton'; + +SegmentedButton.defaultProps = {}; + +export { SegmentedButton }; diff --git a/packages/main/src/webComponents/Select/demo.stories.tsx b/packages/main/src/webComponents/Select/Select.stories.tsx similarity index 65% rename from packages/main/src/webComponents/Select/demo.stories.tsx rename to packages/main/src/webComponents/Select/Select.stories.tsx index 7ea0e6ad6ec..62f4afc6352 100644 --- a/packages/main/src/webComponents/Select/demo.stories.tsx +++ b/packages/main/src/webComponents/Select/Select.stories.tsx @@ -1,5 +1,5 @@ import { action } from '@storybook/addon-actions'; -import { boolean, select } from '@storybook/addon-knobs'; +import { boolean, select, text } from '@storybook/addon-knobs'; import { Option } from '@ui5/webcomponents-react/lib/Option'; import { Select } from '@ui5/webcomponents-react/lib/Select'; import { ValueState } from '@ui5/webcomponents-react/lib/ValueState'; @@ -16,16 +16,15 @@ export default { export const generatedDefaultStory = () => ( ); diff --git a/packages/main/src/webComponents/Select/Select.test.tsx b/packages/main/src/webComponents/Select/Select.test.tsx index b645fdc53ef..409daa2b47f 100644 --- a/packages/main/src/webComponents/Select/Select.test.tsx +++ b/packages/main/src/webComponents/Select/Select.test.tsx @@ -1,5 +1,5 @@ -import { mount } from 'enzyme'; import { Select } from '@ui5/webcomponents-react/lib/Select'; +import { mount } from 'enzyme'; import React from 'react'; describe('Select', () => { diff --git a/packages/main/src/webComponents/Select/__snapshots__/Select.test.tsx.snap b/packages/main/src/webComponents/Select/__snapshots__/Select.test.tsx.snap index 44b15fbb2c9..45e975fdd4b 100644 --- a/packages/main/src/webComponents/Select/__snapshots__/Select.test.tsx.snap +++ b/packages/main/src/webComponents/Select/__snapshots__/Select.test.tsx.snap @@ -2,6 +2,7 @@ exports[`Select Basic Test (generated) 1`] = ` `; diff --git a/packages/main/src/webComponents/Select/index.tsx b/packages/main/src/webComponents/Select/index.tsx index 7569af049c7..5d6a54d4fe4 100644 --- a/packages/main/src/webComponents/Select/index.tsx +++ b/packages/main/src/webComponents/Select/index.tsx @@ -1,4 +1,3 @@ -import { enrichEventWithDetails } from '@ui5/webcomponents-react-base/lib/Utils'; import { ValueState } from '@ui5/webcomponents-react/lib/ValueState'; import { withWebComponent } from '@ui5/webcomponents-react/lib/withWebComponent'; import UI5Select from '@ui5/webcomponents/dist/Select'; @@ -6,10 +5,30 @@ import React, { FC, ReactNode } from 'react'; import { WithWebComponentPropTypes } from '../../internal/withWebComponent'; export interface SelectPropTypes extends WithWebComponentPropTypes { - disabled?: boolean; // @generated - valueState?: ValueState; // @generated - onChange?: (event: CustomEvent) => void; // @generated - children?: ReactNode[]; // @generated + /** + * Defines whether ui5-select is in disabled state.

    Note: A disabled ui5-select is noninteractive. + */ + disabled?: boolean; + /** + * Determines the name with which the ui5-select will be submitted in an HTML form. The value of the ui5-select will be the value of the currently selected ui5-option. + *

    Important: For the name property to have effect, you must add the following import to your project: import "@ui5/webcomponents/dist/features/InputElementsFormSupport.js"; + *

    Note: When set, a native input HTML element will be created inside the ui5-select so that it can be submitted as part of an HTML form. Do not use this property unless you need to submit a form. + */ + name?: string; + /** + * Defines the value state of the ui5-select.

    Available options are:
    • None
    • Error
    • Warning
    • Success
    • Information
    + */ + valueState?: ValueState; + /** + * Defines the ui5-select options. + *

    Note: Only one selected option is allowed. If more than one option is defined as selected, the last one would be considered as the selected one. + *

    Note: Use the ui5-option component to define the desired options. + */ + children?: ReactNode | ReactNode[]; + /** + * Fired when the selected option changes. + */ + onChange?: (event: CustomEvent<{ selectedOption: ReactNode }>) => void; } /** @@ -22,7 +41,9 @@ const Select: FC = withWebComponent(UI5Select) Select.displayName = 'Select'; Select.defaultProps = { - valueState: ValueState.None // @generated + disabled: false, + name: '', + valueState: ValueState.None }; export { Select }; diff --git a/packages/main/src/webComponents/ShellBar/ShellBar.stories.tsx b/packages/main/src/webComponents/ShellBar/ShellBar.stories.tsx new file mode 100644 index 00000000000..31878d543d7 --- /dev/null +++ b/packages/main/src/webComponents/ShellBar/ShellBar.stories.tsx @@ -0,0 +1,41 @@ +import { action } from '@storybook/addon-actions'; +import { boolean, text } from '@storybook/addon-knobs'; +import { ShellBar } from '@ui5/webcomponents-react/lib/ShellBar'; +import { ShellBarItem } from '@ui5/webcomponents-react/lib/ShellBarItem'; +import React from 'react'; + +export default { + title: 'UI5 Web Components / ShellBar', + component: ShellBar, + parameters: { + subcomponents: { ShellBarItem } + } +}; + +export const generatedDefaultStory = () => ( + + + +); + +generatedDefaultStory.story = { + name: 'Generated default story' +}; diff --git a/packages/main/src/webComponents/ShellBar/ShellBar.test.tsx b/packages/main/src/webComponents/ShellBar/ShellBar.test.tsx index 44a13301d28..a1e91f92fbe 100644 --- a/packages/main/src/webComponents/ShellBar/ShellBar.test.tsx +++ b/packages/main/src/webComponents/ShellBar/ShellBar.test.tsx @@ -1,5 +1,5 @@ -import { mount } from 'enzyme'; import { ShellBar } from '@ui5/webcomponents-react/lib/ShellBar'; +import { mount } from 'enzyme'; import React from 'react'; describe('ShellBar', () => { diff --git a/packages/main/src/webComponents/ShellBar/__snapshots__/ShellBar.test.tsx.snap b/packages/main/src/webComponents/ShellBar/__snapshots__/ShellBar.test.tsx.snap index 0b0d059fd87..65c9799e265 100644 --- a/packages/main/src/webComponents/ShellBar/__snapshots__/ShellBar.test.tsx.snap +++ b/packages/main/src/webComponents/ShellBar/__snapshots__/ShellBar.test.tsx.snap @@ -1,3 +1,10 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`ShellBar Basic Test (generated) 1`] = ``; +exports[`ShellBar Basic Test (generated) 1`] = ` + +`; diff --git a/packages/main/src/webComponents/ShellBar/demo.stories.tsx b/packages/main/src/webComponents/ShellBar/demo.stories.tsx deleted file mode 100644 index a0e59bee071..00000000000 --- a/packages/main/src/webComponents/ShellBar/demo.stories.tsx +++ /dev/null @@ -1,66 +0,0 @@ -import { action } from '@storybook/addon-actions'; -import { boolean, number } from '@storybook/addon-knobs'; -import { PlacementType } from '@ui5/webcomponents-react/lib/PlacementType'; -import { Popover } from '@ui5/webcomponents-react/lib/Popover'; -import { ProductSwitch } from '@ui5/webcomponents-react/lib/ProductSwitch'; -import { ProductSwitchItem } from '@ui5/webcomponents-react/lib/ProductSwitchItem'; -import { ShellBar } from '@ui5/webcomponents-react/lib/ShellBar'; -import { ShellBarItem } from '@ui5/webcomponents-react/lib/ShellBarItem'; -import React from 'react'; - -export default { - title: 'UI5 Web Components / ShellBar', - component: ShellBar, - parameters: { - subcomponents: { ShellBarItem } - } -}; - -export const generatedDefaultStory = () => ( -
    - { - // @ts-ignore - document.getElementById('product-switch-popover').openBy(e.detail.targetRef); - }} - searchField={null} - startButton={null} - > - - - - - - - - -
    -); - -generatedDefaultStory.story = { - name: 'Generated default story' -}; diff --git a/packages/main/src/webComponents/ShellBar/index.tsx b/packages/main/src/webComponents/ShellBar/index.tsx index a448dfe91a3..ad009777302 100644 --- a/packages/main/src/webComponents/ShellBar/index.tsx +++ b/packages/main/src/webComponents/ShellBar/index.tsx @@ -1,28 +1,81 @@ import UI5ShellBar from '@ui5/webcomponents-fiori/dist/ShellBar'; -import { enrichEventWithDetails } from '@ui5/webcomponents-react-base/lib/Utils'; import { withWebComponent } from '@ui5/webcomponents-react/lib/withWebComponent'; import React, { FC, ReactNode } from 'react'; import { WithWebComponentPropTypes } from '../../internal/withWebComponent'; export interface ShellBarPropTypes extends WithWebComponentPropTypes { - logo?: string; // @generated - primaryTitle?: string; // @generated - secondaryTitle?: string; // @generated - notificationCount?: string; // @generated - profile?: string; // @generated - showNotifications?: boolean; // @generated - showProductSwitch?: boolean; // @generated - showCoPilot?: boolean; // @generated - onNotificationsClick?: (event: CustomEvent) => void; // @generated - onProfileClick?: (event: CustomEvent) => void; // @generated - onProductSwitchClick?: (event: CustomEvent) => void; // @generated - onLogoClick?: (event: CustomEvent) => void; // @generated - onCoPilotClick?: (event: CustomEvent) => void; // @generated - onMenuItemClick?: (event: CustomEvent) => void; // @generated - children?: ReactNode; // @generated - menuItems?: ReactNode; // @generated - searchField?: ReactNode; // @generated - startButton?: ReactNode; // @generated + /** + * Defines the logo source URI. + */ + logo?: string; + /** + * Defines the notificationCount, displayed in the notification icon top-right corner. + */ + notificationCount?: string; + /** + * Defines the primaryTitle.

    Note: The primaryTitle would be hidden on S screen size (less than approx. 700px). + */ + primaryTitle?: string; + /** + * Defines the secondaryTitle.

    Note: The secondaryTitle would be hidden on S and M screen sizes (less than approx. 1300px). + */ + secondaryTitle?: string; + /** + * Defines, if the product CoPilot icon would be displayed.
    Note: By default the co-pilot is displayed as static SVG. If you need an animated co-pilot, you can import the "@ui5/webcomponents-fiori/dist/features/CoPilotAnimation.js" module as add-on feature. + */ + showCoPilot?: boolean; + /** + * Defines, if the notification icon would be displayed. + */ + showNotifications?: boolean; + /** + * Defines, if the product switch icon would be displayed. + */ + showProductSwitch?: boolean; + /** + * Defines the ui5-shellbar aditional items.

    Note: You can use the  <ui5-shellbar-item></ui5-shellbar-item>. + */ + children?: ReactNode | ReactNode[]; + /** + * Defines the items displayed in menu after a click on the primary title.

    Note: You can use the  <ui5-li></ui5-li> and its ancestors. + */ + menuItems?: ReactNode | ReactNode[]; + /** + * You can pass ui5-avatar to set the profile image/icon. If no profile slot is set - profile will be excluded from actions. + */ + profile?: ReactNode; + /** + * Defines the ui5-input, that will be used as a search field. + */ + searchField?: ReactNode | ReactNode[]; + /** + * Defines a ui5-button in the bar that will be placed in the beginning. We encourage this slot to be used for a back or home button. It gets overstyled to match ShellBar's styling. + */ + startButton?: ReactNode | ReactNode[]; + /** + * Fired, when the co pilot is activated. + */ + onCoPilotClick?: (event: CustomEvent<{ targetRef: ReactNode }>) => void; + /** + * Fired, when the logo is activated. + */ + onLogoClick?: (event: CustomEvent<{ targetRef: ReactNode }>) => void; + /** + * Fired, when a menu item is activated Note: You can prevent closing of oveflow popover by calling event.preventDefault(). + */ + onMenuItemClick?: (event: CustomEvent<{ item: ReactNode }>) => void; + /** + * Fired, when the notification icon is activated. + */ + onNotificationsClick?: (event: CustomEvent<{ targetRef: ReactNode }>) => void; + /** + * Fired, when the product switch icon is activated. Note: You can prevent closing of oveflow popover by calling event.preventDefault(). + */ + onProductSwitchClick?: (event: CustomEvent<{ targetRef: ReactNode }>) => void; + /** + * Fired, when the profile slot is present. + */ + onProfileClick?: (event: CustomEvent<{ targetRef: ReactNode }>) => void; } /** @@ -34,4 +87,14 @@ const ShellBar: FC = withWebComponent(UI5S ShellBar.displayName = 'ShellBar'; +ShellBar.defaultProps = { + logo: '', + notificationCount: '', + primaryTitle: '', + secondaryTitle: '', + showCoPilot: false, + showNotifications: false, + showProductSwitch: false +}; + export { ShellBar }; diff --git a/packages/main/src/webComponents/ShellBarItem/ShellBarItem.test.tsx b/packages/main/src/webComponents/ShellBarItem/ShellBarItem.test.tsx index eb6be41e1d3..f2df8a29ac8 100644 --- a/packages/main/src/webComponents/ShellBarItem/ShellBarItem.test.tsx +++ b/packages/main/src/webComponents/ShellBarItem/ShellBarItem.test.tsx @@ -1,5 +1,5 @@ -import { mount } from 'enzyme'; import { ShellBarItem } from '@ui5/webcomponents-react/lib/ShellBarItem'; +import { mount } from 'enzyme'; import React from 'react'; describe('ShellBarItem', () => { diff --git a/packages/main/src/webComponents/ShellBarItem/__snapshots__/ShellBarItem.test.tsx.snap b/packages/main/src/webComponents/ShellBarItem/__snapshots__/ShellBarItem.test.tsx.snap index 90a6c9369c7..a31a86089d0 100644 --- a/packages/main/src/webComponents/ShellBarItem/__snapshots__/ShellBarItem.test.tsx.snap +++ b/packages/main/src/webComponents/ShellBarItem/__snapshots__/ShellBarItem.test.tsx.snap @@ -1,3 +1,7 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`ShellBarItem Basic Test (generated) 1`] = ``; +exports[`ShellBarItem Basic Test (generated) 1`] = ` + +`; diff --git a/packages/main/src/webComponents/ShellBarItem/index.tsx b/packages/main/src/webComponents/ShellBarItem/index.tsx index 59a4de29c7f..4e4c41eec19 100644 --- a/packages/main/src/webComponents/ShellBarItem/index.tsx +++ b/packages/main/src/webComponents/ShellBarItem/index.tsx @@ -1,20 +1,38 @@ import UI5ShellBarItem from '@ui5/webcomponents-fiori/dist/ShellBarItem'; -import { enrichEventWithDetails } from '@ui5/webcomponents-react-base/lib/Utils'; import { withWebComponent } from '@ui5/webcomponents-react/lib/withWebComponent'; -import React, { FC } from 'react'; +import React, { FC, ReactNode } from 'react'; import { WithWebComponentPropTypes } from '../../internal/withWebComponent'; export interface ShellBarItemPropTypes extends WithWebComponentPropTypes { - icon?: string; // @generated - text?: string; // @generated - onItemClick?: (event: CustomEvent) => void; // @generated + /** + * Defines the count displayed in the top-right corner. + */ + count?: string; + /** + * Defines the name of the item's icon. + */ + icon?: string; + /** + * Defines the item text. + */ + text?: string; + /** + * Fired, when the item is pressed. + */ + onItemClick?: (event: CustomEvent<{ targetRef: ReactNode }>) => void; } /** * import { ShellBarItem } from '@ui5/webcomponents-react/lib/ShellBarItem'; + *
    + * UI5 Web Components Playground */ const ShellBarItem: FC = withWebComponent(UI5ShellBarItem); ShellBarItem.displayName = 'ShellBarItem'; +ShellBarItem.defaultProps = { + count: '' +}; + export { ShellBarItem }; diff --git a/packages/main/src/webComponents/StandardListItem/StandardListItem.test.tsx b/packages/main/src/webComponents/StandardListItem/StandardListItem.test.tsx index 6b707420d76..3491338b66f 100644 --- a/packages/main/src/webComponents/StandardListItem/StandardListItem.test.tsx +++ b/packages/main/src/webComponents/StandardListItem/StandardListItem.test.tsx @@ -1,5 +1,5 @@ -import { mount } from 'enzyme'; import { StandardListItem } from '@ui5/webcomponents-react/lib/StandardListItem'; +import { mount } from 'enzyme'; import React from 'react'; describe('StandardListItem', () => { diff --git a/packages/main/src/webComponents/StandardListItem/__snapshots__/StandardListItem.test.tsx.snap b/packages/main/src/webComponents/StandardListItem/__snapshots__/StandardListItem.test.tsx.snap index deb23836612..ee560d0b607 100644 --- a/packages/main/src/webComponents/StandardListItem/__snapshots__/StandardListItem.test.tsx.snap +++ b/packages/main/src/webComponents/StandardListItem/__snapshots__/StandardListItem.test.tsx.snap @@ -2,7 +2,6 @@ exports[`StandardListItem Basic Test (generated) 1`] = ` `; diff --git a/packages/main/src/webComponents/StandardListItem/index.tsx b/packages/main/src/webComponents/StandardListItem/index.tsx index 3d865a4fa36..72c8ecd3b31 100644 --- a/packages/main/src/webComponents/StandardListItem/index.tsx +++ b/packages/main/src/webComponents/StandardListItem/index.tsx @@ -6,19 +6,52 @@ import React, { FC, ReactNode } from 'react'; import { WithWebComponentPropTypes } from '../../internal/withWebComponent'; export interface StandardListItemPropTypes extends WithWebComponentPropTypes { - selected?: boolean; // @generated - type?: ListItemTypes; // @generated - description?: string; // @generated - icon?: string; // @generated - iconEnd?: boolean; // @generated - image?: string; // @generated - info?: string; // @generated - infoState?: ValueState; // @generated - children?: ReactNode | ReactNode[] | string; + /** + * Defines the description displayed right under the item text, if such is present. + */ + description?: string; + /** + * Defines the icon source URI.

    Note: SAP-icons font provides numerous buil-in icons. To find all the available icons, see the Icon Explorer. + */ + icon?: string; + /** + * Defines whether the icon should be displayed in the beginning of the list item or in the end.

    Note: If image is set, the icon would be displayed after the image. + */ + iconEnd?: boolean; + /** + * Defines the image source URI.

    Note: The image would be displayed in the beginning of the list item. + */ + image?: string; + /** + * Defines the info, displayed in the end of the list item. + */ + info?: string; + /** + * Defines the state of the info.
    Available options are: "None" (by default), "Success", "Warning" and "Erorr". + */ + infoState?: ValueState; + /** + * Defines the text of the ui5-li.

    Note: Аlthough this slot accepts HTML Elements, it is strongly recommended that you only use text in order to preserve the intended design. + */ + children?: ReactNode | ReactNode[]; + /** + * Defines the visual indication and behavior of the list items. + * Available options are Active (by default), Inactive and Detail. + *

    + * Note: When set to Active, the item will provide visual response upon press and hover, + * while with type Inactive and Detail - will not. + */ + type?: ListItemTypes; + /** + * Defines the selected state of the ListItem. + */ + selected?: boolean; } /** * import { StandardListItem } from '@ui5/webcomponents-react/lib/StandardListItem'; + *
    + * UI5 Web Components Playground */ const StandardListItem: FC = withWebComponent( UI5StandardListItem @@ -27,8 +60,9 @@ const StandardListItem: FC = withWebComponent { + test('Basic Test (generated)', () => { + const wrapper = mount(); + expect(wrapper.render()).toMatchSnapshot(); + }); +}); diff --git a/packages/main/src/webComponents/SuggestionItem/__snapshots__/SuggestionItem.test.tsx.snap b/packages/main/src/webComponents/SuggestionItem/__snapshots__/SuggestionItem.test.tsx.snap new file mode 100644 index 00000000000..e8be79b8299 --- /dev/null +++ b/packages/main/src/webComponents/SuggestionItem/__snapshots__/SuggestionItem.test.tsx.snap @@ -0,0 +1,7 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`SuggestionItem Basic Test (generated) 1`] = ` + +`; diff --git a/packages/main/src/webComponents/SuggestionItem/index.tsx b/packages/main/src/webComponents/SuggestionItem/index.tsx new file mode 100644 index 00000000000..a2e0c416457 --- /dev/null +++ b/packages/main/src/webComponents/SuggestionItem/index.tsx @@ -0,0 +1,56 @@ +import { ValueState } from '@ui5/webcomponents-react/lib/ValueState'; +import { withWebComponent } from '@ui5/webcomponents-react/lib/withWebComponent'; +import UI5SuggestionItem from '@ui5/webcomponents/dist/SuggestionItem'; +import React, { FC } from 'react'; +import { WithWebComponentPropTypes } from '../../internal/withWebComponent'; + +export interface SuggestionItemPropTypes extends WithWebComponentPropTypes { + /** + * Defines the description displayed right under the item text, if such is present. + */ + description?: string; + /** + * Defines the item to be displayed as a group item.

    Note: When set, the other properties, such as image, icon, description, etc. will be omitted and only the text will be displayed. + */ + group?: string; + /** + * Defines the icon source URI.

    Note: SAP-icons font provides numerous buil-in icons. To find all the available icons, see the Icon Explorer. + */ + icon?: string; + /** + * Defines whether the icon should be displayed in the beginning of the item or in the end.

    Note: If image is set, the icon would be displayed after the image. + */ + iconEnd?: boolean; + /** + * Defines the image source URI.

    Note: The image would be displayed in the beginning of the item. + */ + image?: string; + /** + * Defines the info, displayed in the end of the item. + */ + info?: string; + /** + * Defines the state of the info.

    Available options are: "None" (by default), "Success", "Warning" and "Erorr". + */ + infoState?: ValueState; + /** + * Defines the text of the ui5-suggestion-item. + */ + text?: string; +} + +/** + * import { SuggestionItem } from '@ui5/webcomponents-react/lib/SuggestionItem'; + *
    + * UI5 Web Components Playground + */ +const SuggestionItem: FC = withWebComponent(UI5SuggestionItem); + +SuggestionItem.displayName = 'SuggestionItem'; + +SuggestionItem.defaultProps = { + iconEnd: false, + text: '' +}; + +export { SuggestionItem }; diff --git a/packages/main/src/webComponents/Switch/demo.stories.tsx b/packages/main/src/webComponents/Switch/Switch.stories.tsx similarity index 88% rename from packages/main/src/webComponents/Switch/demo.stories.tsx rename to packages/main/src/webComponents/Switch/Switch.stories.tsx index 0b37348bedf..bfb0c674642 100644 --- a/packages/main/src/webComponents/Switch/demo.stories.tsx +++ b/packages/main/src/webComponents/Switch/Switch.stories.tsx @@ -12,9 +12,9 @@ export const generatedDefaultStory = () => ( ); diff --git a/packages/main/src/webComponents/Switch/Switch.test.tsx b/packages/main/src/webComponents/Switch/Switch.test.tsx index 5c25c7495c2..02e6bdcf5cb 100644 --- a/packages/main/src/webComponents/Switch/Switch.test.tsx +++ b/packages/main/src/webComponents/Switch/Switch.test.tsx @@ -1,5 +1,5 @@ -import { mount } from 'enzyme'; import { Switch } from '@ui5/webcomponents-react/lib/Switch'; +import { mount } from 'enzyme'; import React from 'react'; describe('Switch', () => { diff --git a/packages/main/src/webComponents/Switch/__snapshots__/Switch.test.tsx.snap b/packages/main/src/webComponents/Switch/__snapshots__/Switch.test.tsx.snap index 2421da888b7..403cb535bac 100644 --- a/packages/main/src/webComponents/Switch/__snapshots__/Switch.test.tsx.snap +++ b/packages/main/src/webComponents/Switch/__snapshots__/Switch.test.tsx.snap @@ -1,3 +1,8 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Switch Basic Test (generated) 1`] = ``; +exports[`Switch Basic Test (generated) 1`] = ` + +`; diff --git a/packages/main/src/webComponents/Switch/index.tsx b/packages/main/src/webComponents/Switch/index.tsx index 873f1d544b5..f76d977317c 100644 --- a/packages/main/src/webComponents/Switch/index.tsx +++ b/packages/main/src/webComponents/Switch/index.tsx @@ -1,16 +1,35 @@ -import { enrichEventWithDetails } from '@ui5/webcomponents-react-base/lib/Utils'; import { withWebComponent } from '@ui5/webcomponents-react/lib/withWebComponent'; import UI5Switch from '@ui5/webcomponents/dist/Switch'; import React, { FC } from 'react'; import { WithWebComponentPropTypes } from '../../internal/withWebComponent'; export interface SwitchPropTypes extends WithWebComponentPropTypes { - checked?: boolean; // @generated - disabled?: boolean; // @generated - textOn?: string; // @generated - textOff?: string; // @generated - graphical?: boolean; // @generated - onChange?: (event: CustomEvent) => void; // @generated + /** + * Defines if the ui5-switch is checked.

    Note: The property can be changed with user interaction, either by cliking/tapping on the ui5-switch, or by pressing the Enter or Space key. + */ + checked?: boolean; + /** + * Defines whether the ui5-switch is disabled.

    Note: A disabled ui5-switch is noninteractive. + */ + disabled?: boolean; + /** + * Defines the ui5-switch type.

    Note: If graphical type is set, positive and negative icons will replace the textOn and textOff. + */ + graphical?: boolean; + /** + * Defines the text of the ui5-switch when switched off.

    Note: We recommend using short texts, up to 3 letters (larger texts would be cut off). + */ + textOff?: string; + /** + * Defines the text of the ui5-switch when switched on. + * + *

    Note: We recommend using short texts, up to 3 letters (larger texts would be cut off). + */ + textOn?: string; + /** + * Fired when the ui5-switch checked state changes. + */ + onChange?: (event: CustomEvent<{}>) => void; } /** @@ -22,4 +41,12 @@ const Switch: FC = withWebComponent(UI5Switch) Switch.displayName = 'Switch'; +Switch.defaultProps = { + checked: false, + disabled: false, + graphical: false, + textOff: '', + textOn: '' +}; + export { Switch }; diff --git a/packages/main/src/webComponents/Tab/Tab.test.tsx b/packages/main/src/webComponents/Tab/Tab.test.tsx index 63a39bad749..95b234b4326 100644 --- a/packages/main/src/webComponents/Tab/Tab.test.tsx +++ b/packages/main/src/webComponents/Tab/Tab.test.tsx @@ -1,5 +1,5 @@ -import { mount } from 'enzyme'; import { Tab } from '@ui5/webcomponents-react/lib/Tab'; +import { mount } from 'enzyme'; import React from 'react'; describe('Tab', () => { diff --git a/packages/main/src/webComponents/Tab/__snapshots__/Tab.test.tsx.snap b/packages/main/src/webComponents/Tab/__snapshots__/Tab.test.tsx.snap index eed4bda32f2..45ea48aa5e1 100644 --- a/packages/main/src/webComponents/Tab/__snapshots__/Tab.test.tsx.snap +++ b/packages/main/src/webComponents/Tab/__snapshots__/Tab.test.tsx.snap @@ -2,6 +2,9 @@ exports[`Tab Basic Test (generated) 1`] = ` `; diff --git a/packages/main/src/webComponents/Tab/index.tsx b/packages/main/src/webComponents/Tab/index.tsx index 5d258dbdc6e..7d914f25ed0 100644 --- a/packages/main/src/webComponents/Tab/index.tsx +++ b/packages/main/src/webComponents/Tab/index.tsx @@ -5,24 +5,54 @@ import React, { FC, ReactNode } from 'react'; import { WithWebComponentPropTypes } from '../../internal/withWebComponent'; export interface TabPropTypes extends WithWebComponentPropTypes { - text?: string; // @generated - disabled?: boolean; // @generated - additionalText?: string; // @generated - icon?: string; // @generated - semanticColor?: SemanticColor; // @generated - selected?: boolean; // @generated + /** + * Represents the "additionalText" text, which is displayed in the tab filter. + */ + additionalText?: string; + /** + * Enabled items can be selected. + */ + disabled?: boolean; + /** + * Defines the icon source URI to be displayed as graphical element within the ui5-tab. The SAP-icons font provides numerous built-in icons. See all the available icons in the Icon Explorer. + */ + icon?: string; + /** + * Specifies if the ui5-tab is selected. + */ + selected?: boolean; + /** + * Defines the ui5-tab semantic color.

    The color is applied to:
    • the ui5-tab icon
    • the text when ui5-tab overflows
    • the tab selection line
    + *

    Available semantic colors are: "Default", "Neutral", "Positive", "Critical" and "Negative". + *

    Note: The color value depends on the current theme. + */ + semanticColor?: SemanticColor; + /** + * The text to be displayed for the item. + */ + text?: string; + /** + * Defines the tab content. + */ children?: ReactNode | ReactNode[]; } /** * import { Tab } from '@ui5/webcomponents-react/lib/Tab'; + *
    + * UI5 Web Components Playground */ const Tab: FC = withWebComponent(UI5Tab); Tab.displayName = 'Tab'; Tab.defaultProps = { - semanticColor: SemanticColor.Default // @generated + additionalText: '', + disabled: false, + icon: '', + selected: false, + semanticColor: SemanticColor.Default, + text: '' }; export { Tab }; diff --git a/packages/main/src/webComponents/TabContainer/TabContainer.stories.tsx b/packages/main/src/webComponents/TabContainer/TabContainer.stories.tsx new file mode 100644 index 00000000000..ce3d825ef2e --- /dev/null +++ b/packages/main/src/webComponents/TabContainer/TabContainer.stories.tsx @@ -0,0 +1,33 @@ +import { action } from '@storybook/addon-actions'; +import { boolean, select } from '@storybook/addon-knobs'; +import { Tab } from '@ui5/webcomponents-react/lib/Tab'; +import { TabContainer } from '@ui5/webcomponents-react/lib/TabContainer'; +import { TabLayout } from '@ui5/webcomponents-react/lib/TabLayout'; +import { TabSeparator } from '@ui5/webcomponents-react/lib/TabSeparator'; +import React from 'react'; + +export default { + title: 'UI5 Web Components / TabContainer', + component: TabContainer, + parameters: { + subcomponents: { Tab, TabSeparator } + } +}; + +export const generatedDefaultStory = () => ( + + Content Tab 1 + Content Tab 2 + Content Tab 3 + +); + +generatedDefaultStory.story = { + name: 'Generated default story' +}; diff --git a/packages/main/src/webComponents/TabContainer/TabContainer.test.tsx b/packages/main/src/webComponents/TabContainer/TabContainer.test.tsx index fca2c4c7df4..e1488aea6a9 100644 --- a/packages/main/src/webComponents/TabContainer/TabContainer.test.tsx +++ b/packages/main/src/webComponents/TabContainer/TabContainer.test.tsx @@ -1,5 +1,5 @@ -import { mount } from 'enzyme'; import { TabContainer } from '@ui5/webcomponents-react/lib/TabContainer'; +import { mount } from 'enzyme'; import React from 'react'; describe('TabContainer', () => { diff --git a/packages/main/src/webComponents/TabContainer/__snapshots__/TabContainer.test.tsx.snap b/packages/main/src/webComponents/TabContainer/__snapshots__/TabContainer.test.tsx.snap index f4adc5d8f86..20614c05ee7 100644 --- a/packages/main/src/webComponents/TabContainer/__snapshots__/TabContainer.test.tsx.snap +++ b/packages/main/src/webComponents/TabContainer/__snapshots__/TabContainer.test.tsx.snap @@ -1,3 +1,7 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`TabContainer Basic Test (generated) 1`] = ``; +exports[`TabContainer Basic Test (generated) 1`] = ` + +`; diff --git a/packages/main/src/webComponents/TabContainer/demo.stories.tsx b/packages/main/src/webComponents/TabContainer/demo.stories.tsx deleted file mode 100644 index fac82709301..00000000000 --- a/packages/main/src/webComponents/TabContainer/demo.stories.tsx +++ /dev/null @@ -1,77 +0,0 @@ -import { action } from '@storybook/addon-actions'; -import { boolean } from '@storybook/addon-knobs'; -import '@ui5/webcomponents-icons/dist/icons/add'; -import '@ui5/webcomponents-icons/dist/icons/home'; -import '@ui5/webcomponents-icons/dist/icons/map'; -import '@ui5/webcomponents-icons/dist/icons/process'; -import '@ui5/webcomponents-icons/dist/icons/world'; -import { Label } from '@ui5/webcomponents-react/lib/Label'; -import { Tab } from '@ui5/webcomponents-react/lib/Tab'; -import { TabContainer } from '@ui5/webcomponents-react/lib/TabContainer'; -import React from 'react'; - -export default { - title: 'UI5 Web Components / TabContainer', - component: TabContainer, - parameters: { - subcomponents: { Tab } - } -}; - -export const defaultStory = () => ( - - - - - - - - - - - - - - - - - -); - -defaultStory.story = { - name: 'Default' -}; - -export const withIcons = () => ( - - - - - - - - - - - - - - - - - -); - -withIcons.story = { - name: 'with Icons' -}; diff --git a/packages/main/src/webComponents/TabContainer/index.tsx b/packages/main/src/webComponents/TabContainer/index.tsx index 8848ff1ef65..836a8f8d16a 100644 --- a/packages/main/src/webComponents/TabContainer/index.tsx +++ b/packages/main/src/webComponents/TabContainer/index.tsx @@ -1,15 +1,38 @@ -import { enrichEventWithDetails } from '@ui5/webcomponents-react-base/lib/Utils'; +import { TabLayout } from '@ui5/webcomponents-react/lib/TabLayout'; import { withWebComponent } from '@ui5/webcomponents-react/lib/withWebComponent'; import UI5TabContainer from '@ui5/webcomponents/dist/TabContainer'; import React, { FC, ReactNode } from 'react'; import { WithWebComponentPropTypes } from '../../internal/withWebComponent'; export interface TabContainerPropTypes extends WithWebComponentPropTypes { - fixed?: boolean; + /** + * Defines whether the tab content is collapsed. + */ collapsed?: boolean; + /** + * Defines whether the tabs are in a fixed state that is not expandable/collapsible by user interaction. + */ + fixed?: boolean; + /** + * Defines whether the overflow select list is displayed.

    The overflow select list represents a list, where all tab filters are displayed so that it's easier for the user to select a specific tab filter. + */ showOverflow?: boolean; - onItemSelect?: (event: CustomEvent) => any; + /** + * Defines the alignment of the main text and the additionalText of a tab. + +

    Note: The main text and the additionalText would be displayed vertically by defualt, but when set to Inline, they would be displayed horizontally. + +

    Available options are:
    • Standard
    • Inline
      • + */ + tabLayout?: TabLayout; + /** + * Defines the tabs.

        Note: Use ui5-tab and ui5-tab-separator for the intended design. + */ children?: ReactNode | ReactNode[]; + /** + * Fired when a tab is selected. + */ + onTabSelect?: (event: CustomEvent<{ tab: ReactNode; tabIndex: undefined }>) => void; } /** @@ -21,4 +44,11 @@ const TabContainer: FC = withWebComponent { diff --git a/packages/main/src/webComponents/TabSeparator/index.tsx b/packages/main/src/webComponents/TabSeparator/index.tsx index 1f23f797623..d1e0162f183 100644 --- a/packages/main/src/webComponents/TabSeparator/index.tsx +++ b/packages/main/src/webComponents/TabSeparator/index.tsx @@ -7,9 +7,13 @@ export interface TabSeparatorPropTypes extends WithWebComponentPropTypes {} /** * import { TabSeparator } from '@ui5/webcomponents-react/lib/TabSeparator'; + *
        + * UI5 Web Components Playground */ const TabSeparator: FC = withWebComponent(UI5TabSeparator); TabSeparator.displayName = 'TabSeparator'; +TabSeparator.defaultProps = {}; + export { TabSeparator }; diff --git a/packages/main/src/webComponents/Table/Table.stories.tsx b/packages/main/src/webComponents/Table/Table.stories.tsx new file mode 100644 index 00000000000..3c71c28ef4a --- /dev/null +++ b/packages/main/src/webComponents/Table/Table.stories.tsx @@ -0,0 +1,88 @@ +import { action } from '@storybook/addon-actions'; +import { boolean, text } from '@storybook/addon-knobs'; +import { Label } from '@ui5/webcomponents-react/lib/Label'; +import { Table } from '@ui5/webcomponents-react/lib/Table'; +import { TableCell } from '@ui5/webcomponents-react/lib/TableCell'; +import { TableColumn } from '@ui5/webcomponents-react/lib/TableColumn'; +import { TableRow } from '@ui5/webcomponents-react/lib/TableRow'; +import React from 'react'; + +export default { + title: 'UI5 Web Components / Table', + component: Table, + parameters: { + subcomponents: { TableColumn, TableRow, TableCell } + } +}; + +export const generatedDefaultStory = () => ( + + + + + + + + + + + + + + + + + + + + + + } + onPopinChange={action('onPopinChange')} + onRowClick={action('onRowClick')} + > + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        +); + +generatedDefaultStory.story = { + name: 'Generated default story' +}; diff --git a/packages/main/src/webComponents/Table/Table.test.tsx b/packages/main/src/webComponents/Table/Table.test.tsx index ebaa221afa3..725f78aa755 100644 --- a/packages/main/src/webComponents/Table/Table.test.tsx +++ b/packages/main/src/webComponents/Table/Table.test.tsx @@ -1,5 +1,5 @@ -import { mount } from 'enzyme'; import { Table } from '@ui5/webcomponents-react/lib/Table'; +import { mount } from 'enzyme'; import React from 'react'; describe('Table', () => { diff --git a/packages/main/src/webComponents/Table/__snapshots__/Table.test.tsx.snap b/packages/main/src/webComponents/Table/__snapshots__/Table.test.tsx.snap index f8474919454..7aa4505dfab 100644 --- a/packages/main/src/webComponents/Table/__snapshots__/Table.test.tsx.snap +++ b/packages/main/src/webComponents/Table/__snapshots__/Table.test.tsx.snap @@ -1,3 +1,7 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Table Basic Test (generated) 1`] = ``; +exports[`Table Basic Test (generated) 1`] = ` + +`; diff --git a/packages/main/src/webComponents/Table/demo.stories.tsx b/packages/main/src/webComponents/Table/demo.stories.tsx deleted file mode 100644 index adf23f354e4..00000000000 --- a/packages/main/src/webComponents/Table/demo.stories.tsx +++ /dev/null @@ -1,60 +0,0 @@ -import { boolean } from '@storybook/addon-knobs'; -import { Label } from '@ui5/webcomponents-react/lib/Label'; -import { Table } from '@ui5/webcomponents-react/lib/Table'; -import { TableCell } from '@ui5/webcomponents-react/lib/TableCell'; -import { TableColumn } from '@ui5/webcomponents-react/lib/TableColumn'; -import { TableRow } from '@ui5/webcomponents-react/lib/TableRow'; -import { Text } from '@ui5/webcomponents-react/lib/Text'; -import React from 'react'; - -export default { - title: 'UI5 Web Components / Table', - component: Table, - parameters: { - subcomponents: { TableColumn, TableRow, TableCell } - } -}; - -export const defaultStory = () => ( - - - , - - Column 2 - , - - Column 3 - - ]} - > - - - - - - - - - - - - - - - - - - - - - - -
        -); - -defaultStory.story = { - name: 'Default' -}; diff --git a/packages/main/src/webComponents/Table/index.tsx b/packages/main/src/webComponents/Table/index.tsx index b376d532029..9145d94f68e 100644 --- a/packages/main/src/webComponents/Table/index.tsx +++ b/packages/main/src/webComponents/Table/index.tsx @@ -4,11 +4,34 @@ import React, { FC, ReactNode } from 'react'; import { WithWebComponentPropTypes } from '../../internal/withWebComponent'; export interface TablePropTypes extends WithWebComponentPropTypes { - showNoData?: boolean; // @generated - noDataText?: string; // @generated + /** + * Defines the text that will be displayed when there is no data and showNoData is present. + */ + noDataText?: string; + /** + * Defines if the value of noDataText will be diplayed when there is no rows present in the table. + */ + showNoData?: boolean; + /** + * Determines whether the column headers remain fixed at the top of the page during vertical scrolling as long as the Web Component is in the viewport.

        Limitations:
        • Browsers that do not support this feature:
          • Internet Explorer
          • Microsoft Edge lower than version 41 (EdgeHTML 16)
          • Mozilla Firefox lower than version 59
        • Scrolling behavior:
          • If the Web Component is placed in layout containers that have the overflow: hidden or overflow: auto style definition, this can prevent the sticky elements of the Web Component from becoming fixed at the top of the viewport.
        + */ stickyColumnHeader?: boolean; - children?: ReactNode | ReactNode[]; + /** + * Defines the configuration for the columns of the ui5-table.

        Note: Use ui5-table-column for the intended design. + */ columns?: ReactNode | ReactNode[]; + /** + * Defines the ui5-table rows.

        Note: Use ui5-table-row for the intended design. + */ + children?: ReactNode | ReactNode[]; + /** + * Fired when the ui5-table-column is shown as a pop-in instead of hiding it. + */ + onPopinChange?: (event: CustomEvent<{ poppedColumns: unknown[] }>) => void; + /** + * Fired when a row is clicked. + */ + onRowClick?: (event: CustomEvent<{ row: ReactNode }>) => void; } /** @@ -20,4 +43,10 @@ const Table: FC = withWebComponent(UI5Table); Table.displayName = 'Table'; +Table.defaultProps = { + noDataText: '', + showNoData: false, + stickyColumnHeader: false +}; + export { Table }; diff --git a/packages/main/src/webComponents/TableCell/TableCell.test.tsx b/packages/main/src/webComponents/TableCell/TableCell.test.tsx index 759e2d0ae2b..d9b429c4390 100644 --- a/packages/main/src/webComponents/TableCell/TableCell.test.tsx +++ b/packages/main/src/webComponents/TableCell/TableCell.test.tsx @@ -1,5 +1,5 @@ -import { mount } from 'enzyme'; import { TableCell } from '@ui5/webcomponents-react/lib/TableCell'; +import { mount } from 'enzyme'; import React from 'react'; describe('TableCell', () => { diff --git a/packages/main/src/webComponents/TableCell/index.tsx b/packages/main/src/webComponents/TableCell/index.tsx index 27db87ef987..b2787570510 100644 --- a/packages/main/src/webComponents/TableCell/index.tsx +++ b/packages/main/src/webComponents/TableCell/index.tsx @@ -4,14 +4,21 @@ import React, { FC, ReactNode } from 'react'; import { WithWebComponentPropTypes } from '../../internal/withWebComponent'; export interface TableCellPropTypes extends WithWebComponentPropTypes { - content?: ReactNode | ReactNode[]; + /** + * Specifies the content of the ui5-table-cell. + */ + children?: ReactNode | ReactNode[]; } /** * import { TableCell } from '@ui5/webcomponents-react/lib/TableCell'; + *
        + * UI5 Web Components Playground */ const TableCell: FC = withWebComponent(UI5TableCell); TableCell.displayName = 'TableCell'; +TableCell.defaultProps = {}; + export { TableCell }; diff --git a/packages/main/src/webComponents/TableColumn/TableColumn.test.tsx b/packages/main/src/webComponents/TableColumn/TableColumn.test.tsx index 9873317ff7f..061dfb1fcac 100644 --- a/packages/main/src/webComponents/TableColumn/TableColumn.test.tsx +++ b/packages/main/src/webComponents/TableColumn/TableColumn.test.tsx @@ -1,5 +1,5 @@ -import { mount } from 'enzyme'; import { TableColumn } from '@ui5/webcomponents-react/lib/TableColumn'; +import { mount } from 'enzyme'; import React from 'react'; describe('TableColumn', () => { diff --git a/packages/main/src/webComponents/TableColumn/index.tsx b/packages/main/src/webComponents/TableColumn/index.tsx index 20ea1ff90d6..fe0f3dd8f04 100644 --- a/packages/main/src/webComponents/TableColumn/index.tsx +++ b/packages/main/src/webComponents/TableColumn/index.tsx @@ -4,21 +4,35 @@ import React, { FC, ReactNode } from 'react'; import { WithWebComponentPropTypes } from '../../internal/withWebComponent'; export interface TableColumnPropTypes extends WithWebComponentPropTypes { - minWidth?: number; // @generated - popinText?: string; // @generated - demandPopin?: boolean; // @generated - children?: ReactNode; // @generated + /** + * According to your minWidth settings, the ui5-table-column can be hidden in different screen sizes.

        Setting this property to true, shows this column as pop-in instead of hiding it. + */ + demandPopin?: boolean; + /** + * Defines the minimum table width required to display this column. By default it is always displayed.

        The responsive behavior of the ui5-table is determined by this property. As an example, by setting minWidth property to 40em shows this column on tablet (and desktop) but hides it on mobile.
        For further responsive design options, see demandPopin property. + */ + minWidth?: number; + /** + * The text for the column when it pops in. + */ + popinText?: string; + /** + * Defines the content of the column header. + */ + children?: ReactNode | ReactNode[]; } /** * import { TableColumn } from '@ui5/webcomponents-react/lib/TableColumn'; + *
        + * UI5 Web Components Playground */ const TableColumn: FC = withWebComponent(UI5TableColumn); TableColumn.displayName = 'TableColumn'; TableColumn.defaultProps = { - minWidth: null // @generated + demandPopin: false }; export { TableColumn }; diff --git a/packages/main/src/webComponents/TableRow/TableRow.test.tsx b/packages/main/src/webComponents/TableRow/TableRow.test.tsx index 8e9362e1f9a..914768acc79 100644 --- a/packages/main/src/webComponents/TableRow/TableRow.test.tsx +++ b/packages/main/src/webComponents/TableRow/TableRow.test.tsx @@ -1,5 +1,5 @@ -import { mount } from 'enzyme'; import { TableRow } from '@ui5/webcomponents-react/lib/TableRow'; +import { mount } from 'enzyme'; import React from 'react'; describe('TableRow', () => { diff --git a/packages/main/src/webComponents/TableRow/index.tsx b/packages/main/src/webComponents/TableRow/index.tsx index 15c35e24f8a..8df107149d0 100644 --- a/packages/main/src/webComponents/TableRow/index.tsx +++ b/packages/main/src/webComponents/TableRow/index.tsx @@ -4,14 +4,21 @@ import React, { FC, ReactNode } from 'react'; import { WithWebComponentPropTypes } from '../../internal/withWebComponent'; export interface TableRowPropTypes extends WithWebComponentPropTypes { + /** + * Defines the cells of the ui5-table-row.

        Note: Use ui5-table-cell for the intended design. + */ children?: ReactNode | ReactNode[]; } /** * import { TableRow } from '@ui5/webcomponents-react/lib/TableRow'; + *
        + * UI5 Web Components Playground */ const TableRow: FC = withWebComponent(UI5TableRow); TableRow.displayName = 'TableRow'; +TableRow.defaultProps = {}; + export { TableRow }; diff --git a/packages/main/src/webComponents/TextArea/demo.stories.tsx b/packages/main/src/webComponents/TextArea/TextArea.stories.tsx similarity index 52% rename from packages/main/src/webComponents/TextArea/demo.stories.tsx rename to packages/main/src/webComponents/TextArea/TextArea.stories.tsx index 58629213e6a..b0bdc49088e 100644 --- a/packages/main/src/webComponents/TextArea/demo.stories.tsx +++ b/packages/main/src/webComponents/TextArea/TextArea.stories.tsx @@ -1,4 +1,5 @@ -import { boolean } from '@storybook/addon-knobs'; +import { action } from '@storybook/addon-actions'; +import { boolean, number, text } from '@storybook/addon-knobs'; import { TextArea } from '@ui5/webcomponents-react/lib/TextArea'; import React from 'react'; @@ -9,16 +10,19 @@ export default { export const generatedDefaultStory = () => (