From c11bfd36b7b97482e707ef3c9a27fde3b8da4138 Mon Sep 17 00:00:00 2001 From: Movin Silva Date: Sat, 11 May 2024 17:39:54 +0530 Subject: [PATCH 01/19] feat(react): :sparkles: add cryptoutils class and required packages --- packages/react/.eslintrc.cjs | 3 + packages/react/package.json | 8 +- .../react/src/models/jwt-verify-options.ts | 27 +++++ packages/react/src/utils/crypto-utils.ts | 109 ++++++++++++++++++ pnpm-lock.yaml | 53 ++++++++- 5 files changed, 196 insertions(+), 4 deletions(-) create mode 100644 packages/react/src/models/jwt-verify-options.ts create mode 100644 packages/react/src/utils/crypto-utils.ts diff --git a/packages/react/.eslintrc.cjs b/packages/react/.eslintrc.cjs index ca335bec..99ac21da 100644 --- a/packages/react/.eslintrc.cjs +++ b/packages/react/.eslintrc.cjs @@ -32,4 +32,7 @@ module.exports = { project: [path.resolve(__dirname, 'tsconfig.lib.json'), path.resolve(__dirname, 'tsconfig.eslint.json')], }, plugins: ['@wso2'], + rules: { + 'class-methods-use-this': 'off', + }, }; diff --git a/packages/react/package.json b/packages/react/package.json index 43c060cd..f5fb85af 100644 --- a/packages/react/package.json +++ b/packages/react/package.json @@ -34,6 +34,7 @@ }, "devDependencies": { "@types/node": "^20.12.7", + "@types/randombytes": "^2.0.3", "@types/react": "^18.2.79", "@types/react-dom": "^18.2.25", "@wso2/eslint-plugin": "https://gitpkg.now.sh/brionmario/wso2-ui-configs/packages/eslint-plugin?fa0b844715320a3953d6d055997c0770f8695082", @@ -51,7 +52,12 @@ "dependencies": { "@asgardeo/js-ui-core": "*", "@oxygen-ui/react": "^1.11.0", - "clsx": "^2.1.1" + "base64url": "^3.0.1", + "buffer": "^6.0.3", + "clsx": "^2.1.1", + "fast-sha256": "^1.3.0", + "jose": "^5.3.0", + "randombytes": "^2.1.0" }, "peerDependencies": { "react": ">=18.0.0", diff --git a/packages/react/src/models/jwt-verify-options.ts b/packages/react/src/models/jwt-verify-options.ts new file mode 100644 index 00000000..bb1bc207 --- /dev/null +++ b/packages/react/src/models/jwt-verify-options.ts @@ -0,0 +1,27 @@ +/** + * Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +interface JwtVerifyOptions { + algorithms: string[]; + audience: string; + clockTolerance: number; + issuer: string; + subject: string; +} + +export default JwtVerifyOptions; diff --git a/packages/react/src/utils/crypto-utils.ts b/packages/react/src/utils/crypto-utils.ts new file mode 100644 index 00000000..6fb44544 --- /dev/null +++ b/packages/react/src/utils/crypto-utils.ts @@ -0,0 +1,109 @@ +/** + * Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import {Buffer} from 'buffer'; +import {CryptoUtils, JWKInterface, AsgardeoUIException} from '@asgardeo/js-ui-core'; +import base64url from 'base64url'; +import sha256 from 'fast-sha256'; +import {createLocalJWKSet, jwtVerify} from 'jose'; +import randombytes from 'randombytes'; +import JwtVerifyOptions from '../models/jwt-verify-options'; + +export default class SPACryptoUtils implements CryptoUtils { + /** + * Get URL encoded string. + * + * @returns {string} base 64 url encoded value. + */ + public base64URLEncode(value: Buffer | string): string { + return base64url.encode(value).replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, ''); + } + + /** + * Get URL decoded string. + * + * @returns {string} base 64 url decoded value. + */ + public base64URLDecode(value: string): string { + return base64url.decode(value).toString(); + } + + /** + * Get SHA256 hash of the given data. + * + * @returns {string | Buffer} SHA256 hash of the data. + */ + public hashSha256(data: string): string | Buffer { + return Buffer.from(sha256(new TextEncoder().encode(data))); + } + + /** + * Generate random bytes. + * + * @returns {string | Buffer} Random bytes. + */ + public generateRandomBytes(length: number): string | Buffer { + return randombytes(length); + } + + /** + * Verify the given JWT. + * + * @returns {Promise} Promise containing the verification status. + */ + public verifyJwt( + idToken: string, + jwk: Partial, + algorithms: string[], + clientID: string, + issuer: string, + subject: string, + clockTolerance?: number, + validateJwtIssuer?: boolean, + ): Promise { + const jwtVerifyOptions: JwtVerifyOptions = { + algorithms, + audience: clientID, + clockTolerance, + issuer, + subject, + }; + + if (validateJwtIssuer ?? true) { + jwtVerifyOptions.issuer = issuer; + } + + return jwtVerify( + idToken, + createLocalJWKSet({ + keys: [jwk], + }), + jwtVerifyOptions, + ) + .then(() => Promise.resolve(true)) + .catch(error => + Promise.reject( + new AsgardeoUIException( + 'REACT_UI-CRYPTO-UTILS-VJ-IV01', + error?.reason ?? JSON.stringify(error), + `${error?.code} ${error?.claim}`, + ), + ), + ); + } +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index dffab43c..19e08746 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -78,13 +78,31 @@ importers: '@oxygen-ui/react': specifier: ^1.11.0 version: 1.11.0(@emotion/react@11.11.4)(@emotion/styled@11.11.5)(@mui/icons-material@5.15.17)(@mui/lab@5.0.0-alpha.110)(@mui/material@5.15.17)(@mui/system@5.15.15)(@mui/utils@5.15.14)(@types/react@18.3.1)(react-dom@18.3.1)(react@18.3.1)(typescript@5.4.5) + base64url: + specifier: ^3.0.1 + version: 3.0.1 + buffer: + specifier: ^6.0.3 + version: 6.0.3 clsx: specifier: ^2.1.1 version: 2.1.1 + fast-sha256: + specifier: ^1.3.0 + version: 1.3.0 + jose: + specifier: ^5.3.0 + version: 5.3.0 + randombytes: + specifier: ^2.1.0 + version: 2.1.0 devDependencies: '@types/node': specifier: ^20.12.7 version: 20.12.7 + '@types/randombytes': + specifier: ^2.0.3 + version: 2.0.3 '@types/react': specifier: ^18.2.79 version: 18.3.1 @@ -1362,6 +1380,12 @@ packages: /@types/prop-types@15.7.12: resolution: {integrity: sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==} + /@types/randombytes@2.0.3: + resolution: {integrity: sha512-+NRgihTfuURllWCiIAhm1wsJqzsocnqXM77V/CalsdJIYSRGEHMnritxh+6EsBklshC+clo1KgnN14qgSGeQdw==} + dependencies: + '@types/node': 20.12.7 + dev: true + /@types/react-dom@18.3.0: resolution: {integrity: sha512-EhwApuTmMBmXuFOikhQLIBUn6uFg81SwLMOAUgodJF14SOBOCMdU04gDoYi0WOJJHD144TL32z4yDqCW3dnkQg==} dependencies: @@ -1811,7 +1835,11 @@ packages: /base64-js@1.5.1: resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} - dev: true + + /base64url@3.0.1: + resolution: {integrity: sha512-ir1UPr3dkwexU7FdV8qBBbNDRUhMmIekYMFZfi+C/sLNnRESKPl23nB9b2pltqfOQNnGzsDdId90AEtG5tCx4A==} + engines: {node: '>=6.0.0'} + dev: false /binary-extensions@2.3.0: resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} @@ -1868,6 +1896,13 @@ packages: ieee754: 1.2.1 dev: true + /buffer@6.0.3: + resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==} + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + dev: false + /builtin-modules@3.3.0: resolution: {integrity: sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==} engines: {node: '>=6'} @@ -2960,6 +2995,10 @@ packages: resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} dev: true + /fast-sha256@1.3.0: + resolution: {integrity: sha512-n11RGP/lrWEFI/bWdygLxhI+pVeo1ZYIVwvvPkW7azl/rOy+F3HYRZ2K5zeE9mmkhQppyv9sQFx0JM9UabnpPQ==} + dev: false + /fastest-levenshtein@1.0.16: resolution: {integrity: sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==} engines: {node: '>= 4.9.1'} @@ -3300,7 +3339,6 @@ packages: /ieee754@1.2.1: resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} - dev: true /ignore@5.3.1: resolution: {integrity: sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==} @@ -3624,6 +3662,10 @@ packages: resolution: {integrity: sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==} dev: true + /jose@5.3.0: + resolution: {integrity: sha512-IChe9AtAE79ru084ow8jzkN2lNrG3Ntfiv65Cvj9uOCE2m5LNsdHG+9EbxWxAoWRF9TgDOqLN5jm08++owDVRg==} + dev: false + /js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} @@ -4343,6 +4385,12 @@ packages: engines: {node: '>=8'} dev: true + /randombytes@2.1.0: + resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==} + dependencies: + safe-buffer: 5.2.1 + dev: false + /react-dom@18.3.1(react@18.3.1): resolution: {integrity: sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==} peerDependencies: @@ -4593,7 +4641,6 @@ packages: /safe-buffer@5.2.1: resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} - dev: true /safe-regex-test@1.0.3: resolution: {integrity: sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==} From 57aadea006f89223a36fe9d0f02545a4063ff0b3 Mon Sep 17 00:00:00 2001 From: Movin Silva Date: Sat, 11 May 2024 17:41:29 +0530 Subject: [PATCH 02/19] feat(react): :sparkles: add SessionStore class --- packages/react/src/utils/session-store.ts | 39 +++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 packages/react/src/utils/session-store.ts diff --git a/packages/react/src/utils/session-store.ts b/packages/react/src/utils/session-store.ts new file mode 100644 index 00000000..15ca7fcb --- /dev/null +++ b/packages/react/src/utils/session-store.ts @@ -0,0 +1,39 @@ +/** + * Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import {Store} from '@asgardeo/js-ui-core'; + +export default class SessionStore implements Store { + private storage: Storage; + + constructor() { + this.storage = sessionStorage; + } + + public async setData(key: string, value: string): Promise { + this.storage.setItem(key, value); + } + + public async getData(key: string): Promise { + return this.storage.getItem(key) ?? '{}'; + } + + public async removeData(key: string): Promise { + this.storage.removeItem(key); + } +} From 5b328567b382106998e9f15a376094126b8dc3a3 Mon Sep 17 00:00:00 2001 From: Movin Silva Date: Sat, 11 May 2024 18:17:12 +0530 Subject: [PATCH 03/19] feat(react): :sparkles: add AsgardeoProvider & asgardeoContext --- .../react/src/contexts/asgardeo-context.ts | 24 +++++ .../src/models/asgardeo-provider-props.ts | 27 ++++++ packages/react/src/models/auth-context.ts | 30 ++++++ .../react/src/providers/AsgardeoProvider.tsx | 97 +++++++++++++++++++ 4 files changed, 178 insertions(+) create mode 100644 packages/react/src/contexts/asgardeo-context.ts create mode 100644 packages/react/src/models/asgardeo-provider-props.ts create mode 100644 packages/react/src/models/auth-context.ts create mode 100644 packages/react/src/providers/AsgardeoProvider.tsx diff --git a/packages/react/src/contexts/asgardeo-context.ts b/packages/react/src/contexts/asgardeo-context.ts new file mode 100644 index 00000000..d04644ef --- /dev/null +++ b/packages/react/src/contexts/asgardeo-context.ts @@ -0,0 +1,24 @@ +/** + * Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import {Context, createContext} from 'react'; +import AuthContext from '../models/auth-context'; + +const AsgardeoContext: Context = createContext(undefined); + +export default AsgardeoContext; diff --git a/packages/react/src/models/asgardeo-provider-props.ts b/packages/react/src/models/asgardeo-provider-props.ts new file mode 100644 index 00000000..b080687b --- /dev/null +++ b/packages/react/src/models/asgardeo-provider-props.ts @@ -0,0 +1,27 @@ +/** + * Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import {BrandingProps, Store, UIAuthConfig} from '@asgardeo/js-ui-core'; + +interface AsgardeProviderProps { + branding?: BrandingProps; + config: UIAuthConfig; + store?: Store; +} + +export default AsgardeProviderProps; diff --git a/packages/react/src/models/auth-context.ts b/packages/react/src/models/auth-context.ts new file mode 100644 index 00000000..1960de6d --- /dev/null +++ b/packages/react/src/models/auth-context.ts @@ -0,0 +1,30 @@ +/** + * Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import {UIAuthConfig, MeAPIResponse} from '@asgardeo/js-ui-core'; + +interface AuthContext { + accessToken: string; + config: UIAuthConfig; + customizationOptions?: any; + isAuthenticated: boolean | undefined; + setAuthentication: () => void; + user: MeAPIResponse; +} + +export default AuthContext; diff --git a/packages/react/src/providers/AsgardeoProvider.tsx b/packages/react/src/providers/AsgardeoProvider.tsx new file mode 100644 index 00000000..25002955 --- /dev/null +++ b/packages/react/src/providers/AsgardeoProvider.tsx @@ -0,0 +1,97 @@ +/** + * Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import {AuthClient, CryptoUtils, MeAPIResponse, Store, UIAuthClient, getProfileInformation} from '@asgardeo/js-ui-core'; +import {FC, PropsWithChildren, useCallback, useEffect, useMemo, useState} from 'react'; +import BrandingPreferenceProvider from './BrandingPreferenceProvider'; +import AsgardeoContext from '../contexts/asgardeo-context'; +import AsgardeProviderProps from '../models/asgardeo-provider-props'; +import AuthContext from '../models/auth-context'; +import SPACryptoUtils from '../utils/crypto-utils'; +import SessionStore from '../utils/session-store'; + +const AsgardeoProvider: FC = (props: PropsWithChildren) => { + const {children, config, store, branding} = props; + + const [accessToken, setAccessToken] = useState(''); + const [isAuthenticated, setIsAuthenticated] = useState(); + const [user, setUser] = useState(); + + const storeInstance: Store = store || new SessionStore(); + + const spaUtils: CryptoUtils = new SPACryptoUtils(); + + const authClient: UIAuthClient = AuthClient.getInstance(config, storeInstance, spaUtils); + + /** + * Sets the authentication status and access token. + */ + const setAuthentication: () => void = useCallback((): void => { + authClient.isAuthenticated().then((isAuth: boolean) => { + setIsAuthenticated(isAuth); + }); + + authClient.getAccessToken().then((accessTokenFromClient: string) => { + if (accessTokenFromClient) { + setAccessToken(accessTokenFromClient); + + getProfileInformation().then((response: MeAPIResponse) => { + setUser(response); + }); + } + }); + }, [authClient]); + + useEffect(() => { + setAuthentication(); + + /** + * This script is added so that the popup window can send the code and state to the parent window + */ + const url: URL = new URL(window.location.href); + if (url.searchParams.has('code') && url.searchParams.has('state')) { + const code: string = url.searchParams.get('code'); + const state: string = url.searchParams.get('state'); + + /** + * Send the 'code' and 'state' to the parent window and close the current window (popup) + */ + window.opener.postMessage({code, state}, config.signInRedirectURL); + window.close(); + } + }, [config.signInRedirectURL, setAuthentication]); + + const value: AuthContext = useMemo( + () => ({ + accessToken, + config, + isAuthenticated, + setAuthentication, + user, + }), + [accessToken, config, isAuthenticated, setAuthentication, user], + ); + + return ( + + {children} + + ); +}; + +export default AsgardeoProvider; From c0bd7e84f9a6f560e5e9595c7b749d52e041fbaa Mon Sep 17 00:00:00 2001 From: Movin Silva Date: Sat, 11 May 2024 18:20:18 +0530 Subject: [PATCH 04/19] fix(core): :bug: fix parameter passing to getLocalization function --- packages/core/src/i18n/get-localization.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/core/src/i18n/get-localization.ts b/packages/core/src/i18n/get-localization.ts index c8c0c96b..5b7c3a78 100644 --- a/packages/core/src/i18n/get-localization.ts +++ b/packages/core/src/i18n/get-localization.ts @@ -39,12 +39,12 @@ const getLocalization = async (props: GetLocalizationProps): Promise try { if ((await AuthClient.getInstance().getDataLayer().getConfigData()).enableConsoleTextBranding ?? true) { - textFromConsoleBranding = await getBrandingPreferenceText( + textFromConsoleBranding = await getBrandingPreferenceText({ locale, - providerCustomization.name, + name: providerCustomization.name, screen, - providerCustomization.type, - ); + type: providerCustomization.type, + }); } } catch (error) { throw new AsgardeoUIException( From d17f0b0e3fe62800d6d4aeb000380884d9115460 Mon Sep 17 00:00:00 2001 From: Movin Silva Date: Sat, 11 May 2024 18:55:20 +0530 Subject: [PATCH 05/19] feat(react): :sparkles: add BrandingPreferenceProvider and brandingPreferenceContext --- .../contexts/branding-preference-context.ts | 24 ++++++++ .../branding-preference-provider-props.ts | 25 +++++++++ .../react/src/providers/AsgardeoProvider.tsx | 6 +- .../providers/BrandingPreferenceProvider.tsx | 56 +++++++++++++++++++ 4 files changed, 109 insertions(+), 2 deletions(-) create mode 100644 packages/react/src/contexts/branding-preference-context.ts create mode 100644 packages/react/src/models/branding-preference-provider-props.ts create mode 100644 packages/react/src/providers/BrandingPreferenceProvider.tsx diff --git a/packages/react/src/contexts/branding-preference-context.ts b/packages/react/src/contexts/branding-preference-context.ts new file mode 100644 index 00000000..602111e5 --- /dev/null +++ b/packages/react/src/contexts/branding-preference-context.ts @@ -0,0 +1,24 @@ +/** + * Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import {BrandingProps} from '@asgardeo/js-ui-core'; +import {Context, createContext} from 'react'; + +const BrandingPreferenceContext: Context = createContext(undefined); + +export default BrandingPreferenceContext; diff --git a/packages/react/src/models/branding-preference-provider-props.ts b/packages/react/src/models/branding-preference-provider-props.ts new file mode 100644 index 00000000..2766be00 --- /dev/null +++ b/packages/react/src/models/branding-preference-provider-props.ts @@ -0,0 +1,25 @@ +/** + * Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import {BrandingProps} from '@asgardeo/js-ui-core'; + +interface BrandingPreferenceProviderProps { + branding?: BrandingProps; +} + +export default BrandingPreferenceProviderProps; diff --git a/packages/react/src/providers/AsgardeoProvider.tsx b/packages/react/src/providers/AsgardeoProvider.tsx index 25002955..00b1abff 100644 --- a/packages/react/src/providers/AsgardeoProvider.tsx +++ b/packages/react/src/providers/AsgardeoProvider.tsx @@ -25,7 +25,9 @@ import AuthContext from '../models/auth-context'; import SPACryptoUtils from '../utils/crypto-utils'; import SessionStore from '../utils/session-store'; -const AsgardeoProvider: FC = (props: PropsWithChildren) => { +const AsgardeoProvider: FC> = ( + props: PropsWithChildren, +) => { const {children, config, store, branding} = props; const [accessToken, setAccessToken] = useState(''); @@ -89,7 +91,7 @@ const AsgardeoProvider: FC = (props: PropsWithChildren - {children} + {children} ); }; diff --git a/packages/react/src/providers/BrandingPreferenceProvider.tsx b/packages/react/src/providers/BrandingPreferenceProvider.tsx new file mode 100644 index 00000000..e6536b81 --- /dev/null +++ b/packages/react/src/providers/BrandingPreferenceProvider.tsx @@ -0,0 +1,56 @@ +/** + * Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import {Branding, getBranding} from '@asgardeo/js-ui-core'; +import {ThemeProvider} from '@oxygen-ui/react'; +import {FC, PropsWithChildren, useCallback, useEffect, useState} from 'react'; +import BrandingPreferenceContext from '../contexts/branding-preference-context'; +import generateTheme from '../customization/theme'; +import getThemeSkeleton from '../customization/theme/theme-skeleton'; +import BrandingPreferenceProviderProps from '../models/branding-preference-provider-props'; + +const BrandingPreferenceProvider: FC> = ( + props: PropsWithChildren, +) => { + const {children, branding} = props; + + const [brandingPreference, setBrandingPreference] = useState(); + + const injectBrandingCSSSkeleton: () => void = useCallback((): void => { + if (brandingPreference) { + const styleElement: HTMLStyleElement = document.createElement('style'); + styleElement.innerHTML = getThemeSkeleton(brandingPreference.preference.theme); + document.head.appendChild(styleElement); + } + }, [brandingPreference]); + + useEffect(() => { + getBranding({customization: branding}).then((response: Branding) => { + setBrandingPreference(response); + injectBrandingCSSSkeleton(); + }); + }, [branding, injectBrandingCSSSkeleton]); + + return ( + + {children} + + ); +}; + +export default BrandingPreferenceProvider; From 41be6db6b81c8a37abcd5fcc28974a1107c72116 Mon Sep 17 00:00:00 2001 From: Movin Silva Date: Sat, 11 May 2024 18:56:58 +0530 Subject: [PATCH 06/19] refactor(core): :recycle: rename a parameter of getBranding function --- packages/core/src/branding/get-branding.ts | 8 ++++---- packages/core/src/models/get-branding-props.ts | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/core/src/branding/get-branding.ts b/packages/core/src/branding/get-branding.ts index 64fb3754..0f63c92c 100644 --- a/packages/core/src/branding/get-branding.ts +++ b/packages/core/src/branding/get-branding.ts @@ -31,7 +31,7 @@ import GetBrandingProps from '../models/get-branding-props'; * @returns {Promise} A promise that resolves with the merged branding properties. */ const getBranding = async (props: GetBrandingProps): Promise => { - const {customization, merged} = props; + const {branding, merged} = props; let mergedBranding: Branding; /** @@ -46,12 +46,12 @@ const getBranding = async (props: GetBrandingProps): Promise => { } if (brandingFromConsole?.preference?.configs?.isBrandingEnabled) { - mergedBranding = merge(DEFAULT_BRANDING, brandingFromConsole ?? {}, customization ?? {}); + mergedBranding = merge(DEFAULT_BRANDING, brandingFromConsole ?? {}, branding ?? {}); } else { - mergedBranding = merge(DEFAULT_BRANDING, customization ?? {}); + mergedBranding = merge(DEFAULT_BRANDING, branding ?? {}); } } else { - mergedBranding = merge(merged, customization ?? {}); + mergedBranding = merge(merged, branding ?? {}); } return mergedBranding; diff --git a/packages/core/src/models/get-branding-props.ts b/packages/core/src/models/get-branding-props.ts index 3beec285..0ebe3b2a 100644 --- a/packages/core/src/models/get-branding-props.ts +++ b/packages/core/src/models/get-branding-props.ts @@ -25,7 +25,7 @@ interface GetBrandingProps { /** * Customization prop passed to the component/provider. */ - customization?: BrandingProps; + branding?: BrandingProps; /** * Merged customization object. */ From 8c949e14cf88b9b4766882e9e80711cb5717256d Mon Sep 17 00:00:00 2001 From: Movin Silva Date: Sat, 11 May 2024 19:03:24 +0530 Subject: [PATCH 07/19] fix(react): :coffin: update parameter name of getBranding function --- packages/react/src/providers/BrandingPreferenceProvider.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/react/src/providers/BrandingPreferenceProvider.tsx b/packages/react/src/providers/BrandingPreferenceProvider.tsx index e6536b81..a71d6b9c 100644 --- a/packages/react/src/providers/BrandingPreferenceProvider.tsx +++ b/packages/react/src/providers/BrandingPreferenceProvider.tsx @@ -40,7 +40,7 @@ const BrandingPreferenceProvider: FC { - getBranding({customization: branding}).then((response: Branding) => { + getBranding({branding}).then((response: Branding) => { setBrandingPreference(response); injectBrandingCSSSkeleton(); }); From d8f21aa70178a535be59320997a749e77212e808 Mon Sep 17 00:00:00 2001 From: Movin Silva Date: Tue, 14 May 2024 14:12:56 +0530 Subject: [PATCH 08/19] fix(auth-components): :lipstick: update styling of SignInTypography and SignInImage components --- .../SignInImage/sign-in-image.scss | 3 ++- .../SignInTypography/sign-in-typography.scss | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/react/src/oxygen-ui-react-auth-components/SignInImage/sign-in-image.scss b/packages/react/src/oxygen-ui-react-auth-components/SignInImage/sign-in-image.scss index 49eda1de..9ea4cc88 100644 --- a/packages/react/src/oxygen-ui-react-auth-components/SignInImage/sign-in-image.scss +++ b/packages/react/src/oxygen-ui-react-auth-components/SignInImage/sign-in-image.scss @@ -18,5 +18,6 @@ .OxygenSignInImage { margin: 16px 0; - width: 65px; + min-height: 40px; + max-height: 100px; } diff --git a/packages/react/src/oxygen-ui-react-auth-components/SignInTypography/sign-in-typography.scss b/packages/react/src/oxygen-ui-react-auth-components/SignInTypography/sign-in-typography.scss index ae3a72de..86e3d249 100644 --- a/packages/react/src/oxygen-ui-react-auth-components/SignInTypography/sign-in-typography.scss +++ b/packages/react/src/oxygen-ui-react-auth-components/SignInTypography/sign-in-typography.scss @@ -17,5 +17,5 @@ */ .OxygenSignInTypography-subtitle { - color: grey; + color: var(--oxygen-palette-text-secondary); } From 34fad5f904958a8867de7b99d67700f1c14b1213 Mon Sep 17 00:00:00 2001 From: Movin Silva Date: Tue, 14 May 2024 14:15:35 +0530 Subject: [PATCH 09/19] refactor(auth-components): :recycle: refactor SignInComponent's children usage --- .../oxygen-ui-react-auth-components/SignIn/SignIn.tsx | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/packages/react/src/oxygen-ui-react-auth-components/SignIn/SignIn.tsx b/packages/react/src/oxygen-ui-react-auth-components/SignIn/SignIn.tsx index c79aa6db..0eef4fb4 100644 --- a/packages/react/src/oxygen-ui-react-auth-components/SignIn/SignIn.tsx +++ b/packages/react/src/oxygen-ui-react-auth-components/SignIn/SignIn.tsx @@ -89,6 +89,7 @@ const COMPONENT_NAME: string = 'SignIn'; const SignIn: ForwardRefExoticComponent & WithWrapperProps & SignInCompoundProps = forwardRef( (props: SignInProps, ref: MutableRefObject): ReactElement => { const { + children, className, title, subtitle, @@ -140,8 +141,12 @@ const SignIn: ForwardRefExoticComponent & WithWrapperProps & SignIn * If SignIn component contains any children render only the outer box. * Otherwise render the default SignIn component. */ - if (props?.['children']) { - return ; + if (children) { + return ( + + {children} + + ); } return ( From cb1129ebee50a97c3940c5a60fbf6c1420cecfbd Mon Sep 17 00:00:00 2001 From: Movin Silva Date: Tue, 14 May 2024 14:21:19 +0530 Subject: [PATCH 10/19] fix(react): :fire: remove branding css functions from BrandingPreferenceProvider --- .../src/providers/BrandingPreferenceProvider.tsx | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/packages/react/src/providers/BrandingPreferenceProvider.tsx b/packages/react/src/providers/BrandingPreferenceProvider.tsx index a71d6b9c..33ea36d8 100644 --- a/packages/react/src/providers/BrandingPreferenceProvider.tsx +++ b/packages/react/src/providers/BrandingPreferenceProvider.tsx @@ -18,10 +18,8 @@ import {Branding, getBranding} from '@asgardeo/js-ui-core'; import {ThemeProvider} from '@oxygen-ui/react'; -import {FC, PropsWithChildren, useCallback, useEffect, useState} from 'react'; +import {FC, PropsWithChildren, useEffect, useState} from 'react'; import BrandingPreferenceContext from '../contexts/branding-preference-context'; -import generateTheme from '../customization/theme'; -import getThemeSkeleton from '../customization/theme/theme-skeleton'; import BrandingPreferenceProviderProps from '../models/branding-preference-provider-props'; const BrandingPreferenceProvider: FC> = ( @@ -31,20 +29,11 @@ const BrandingPreferenceProvider: FC(); - const injectBrandingCSSSkeleton: () => void = useCallback((): void => { - if (brandingPreference) { - const styleElement: HTMLStyleElement = document.createElement('style'); - styleElement.innerHTML = getThemeSkeleton(brandingPreference.preference.theme); - document.head.appendChild(styleElement); - } - }, [brandingPreference]); - useEffect(() => { getBranding({branding}).then((response: Branding) => { setBrandingPreference(response); - injectBrandingCSSSkeleton(); }); - }, [branding, injectBrandingCSSSkeleton]); + }, [branding]); return ( From f0e60a6b68645df94232a6ffe7f07d45b9ae8213 Mon Sep 17 00:00:00 2001 From: Movin Silva Date: Tue, 14 May 2024 15:07:58 +0530 Subject: [PATCH 11/19] feat(react): :sparkles: add generateTheme generates a theme that can be passed to the ThemeProvider --- .../providers/BrandingPreferenceProvider.tsx | 3 +- packages/react/src/theme/generate-theme.ts | 130 ++++++++++++++++++ 2 files changed, 132 insertions(+), 1 deletion(-) create mode 100644 packages/react/src/theme/generate-theme.ts diff --git a/packages/react/src/providers/BrandingPreferenceProvider.tsx b/packages/react/src/providers/BrandingPreferenceProvider.tsx index 33ea36d8..bc0a39f8 100644 --- a/packages/react/src/providers/BrandingPreferenceProvider.tsx +++ b/packages/react/src/providers/BrandingPreferenceProvider.tsx @@ -21,6 +21,7 @@ import {ThemeProvider} from '@oxygen-ui/react'; import {FC, PropsWithChildren, useEffect, useState} from 'react'; import BrandingPreferenceContext from '../contexts/branding-preference-context'; import BrandingPreferenceProviderProps from '../models/branding-preference-provider-props'; +import generateTheme from '../theme/generate-theme'; const BrandingPreferenceProvider: FC> = ( props: PropsWithChildren, @@ -37,7 +38,7 @@ const BrandingPreferenceProvider: FC - {children} + {children} ); }; diff --git a/packages/react/src/theme/generate-theme.ts b/packages/react/src/theme/generate-theme.ts new file mode 100644 index 00000000..c03c1d5d --- /dev/null +++ b/packages/react/src/theme/generate-theme.ts @@ -0,0 +1,130 @@ +/** + * Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import {BrandingPreferenceTheme, ThemeConfig} from '@asgardeo/js-ui-core'; +import {extendTheme, Theme} from '@oxygen-ui/react'; + +const generateTheme: (brandingPreferenceTheme: BrandingPreferenceTheme) => Theme = ( + brandingPreferenceTheme: BrandingPreferenceTheme, +) => { + const mode: string = brandingPreferenceTheme?.activeTheme.toLowerCase() ?? 'light'; + const brandingTheme: ThemeConfig = brandingPreferenceTheme[mode.toUpperCase()]; + + return extendTheme({ + colorSchemes: { + dark: { + brand: { + logo: { + main: brandingTheme?.images?.myAccountLogo?.imgURL ?? `../assets/asgardeo-logo.svg`, + }, + }, + palette: { + primary: { + main: brandingTheme?.colors?.primary?.main ?? 'var(--oxygen-palette-primary-main)', + }, + }, + }, + light: { + brand: { + logo: { + main: brandingTheme?.images?.myAccountLogo?.imgURL ?? `../assets/asgardeo-logo.svg`, + }, + }, + palette: { + primary: { + main: brandingTheme?.colors?.primary?.main ?? 'var(--oxygen-palette-primary-main)', + }, + }, + }, + }, + components: { + MuiButton: { + styleOverrides: { + root: { + borderRadius: brandingTheme?.buttons?.primary?.base?.border?.borderRadius, + color: brandingTheme?.buttons?.primary?.base?.font?.color, + }, + }, + }, + MuiFormControl: { + styleOverrides: { + root: { + background: brandingTheme?.inputs?.base?.background?.backgroundColor, + borderColor: brandingTheme?.inputs?.base?.border?.borderColor, + borderRadius: brandingTheme?.inputs?.base?.border?.borderRadius, + color: brandingTheme?.inputs?.base?.font?.color, + }, + }, + }, + MuiInputLabel: { + styleOverrides: { + root: { + color: `${ + brandingTheme?.inputs?.base?.labels?.font?.color ?? brandingTheme?.colors?.text?.primary + } !important`, + }, + }, + }, + MuiOutlinedInput: { + styleOverrides: { + input: { + padding: '0.67857143em 1em', + }, + }, + }, + MuiPaper: { + styleOverrides: { + root: { + '.OxygenSignInButton-social': { + backgroundColor: brandingTheme?.buttons.externalConnection.base.background.backgroundColor, + borderRadius: brandingTheme?.buttons.externalConnection.base.border.borderRadius, + color: brandingTheme?.buttons.externalConnection.base.font.color, + }, + background: brandingTheme?.colors?.background?.surface?.main, + borderColor: brandingTheme?.colors?.outlined?.default, + }, + }, + }, + MuiTextField: { + styleOverrides: { + root: { + borderColor: `${brandingTheme?.colors?.outlined?.default} !important`, + }, + }, + }, + MuiTypography: { + styleOverrides: { + root: { + color: brandingTheme?.colors?.text?.primary, + }, + }, + }, + }, + shape: { + borderRadius: 4, + }, + typography: { + fontFamily: brandingTheme?.typography.font.fontFamily ?? 'Gilmer, sans-serif', + h1: { + fontWeight: 700, + }, + }, + }); +}; + +export default generateTheme; From 83cc49bb1b16bd6d5366c65dabeff9f95dcdf264 Mon Sep 17 00:00:00 2001 From: Movin Silva Date: Tue, 14 May 2024 15:14:42 +0530 Subject: [PATCH 12/19] feat(react): :sparkles: add i18n context --- packages/react/src/contexts/i18n-context.ts | 24 +++++++++++++++ packages/react/src/models/i18n.ts | 34 +++++++++++++++++++++ 2 files changed, 58 insertions(+) create mode 100644 packages/react/src/contexts/i18n-context.ts create mode 100644 packages/react/src/models/i18n.ts diff --git a/packages/react/src/contexts/i18n-context.ts b/packages/react/src/contexts/i18n-context.ts new file mode 100644 index 00000000..e826ae17 --- /dev/null +++ b/packages/react/src/contexts/i18n-context.ts @@ -0,0 +1,24 @@ +/** + * Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import {Context, createContext} from 'react'; +import {I18n} from '../models/i18n'; + +const I18nContext: Context = createContext(undefined); + +export default I18nContext; diff --git a/packages/react/src/models/i18n.ts b/packages/react/src/models/i18n.ts new file mode 100644 index 00000000..76eebda5 --- /dev/null +++ b/packages/react/src/models/i18n.ts @@ -0,0 +1,34 @@ +/** + * Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import {BrandingPreferenceTextProps, ScreenType, TextObject} from '@asgardeo/js-ui-core'; + +export type I18nLocalization = + | { + [key in ScreenType]: TextObject; + } + | {}; + +export interface I18n { + setTranslations: ( + screen: ScreenType, + componentLocaleOverride?: string, + componentTextOverrides?: BrandingPreferenceTextProps, + ) => Promise; + text: I18nLocalization; +} From 16346d45952693014fa8543bc7d96a9030b431f9 Mon Sep 17 00:00:00 2001 From: Movin Silva Date: Tue, 14 May 2024 15:25:19 +0530 Subject: [PATCH 13/19] feat(react): :sparkles: add I18nProvider --- packages/react/src/models/i18n.ts | 11 ++-- .../react/src/providers/AsgardeoProvider.tsx | 7 ++- packages/react/src/providers/I18nProvider.tsx | 58 +++++++++++++++++++ 3 files changed, 70 insertions(+), 6 deletions(-) create mode 100644 packages/react/src/providers/I18nProvider.tsx diff --git a/packages/react/src/models/i18n.ts b/packages/react/src/models/i18n.ts index 76eebda5..4221a953 100644 --- a/packages/react/src/models/i18n.ts +++ b/packages/react/src/models/i18n.ts @@ -24,11 +24,12 @@ export type I18nLocalization = } | {}; +export interface SetTranslationsProps { + componentLocaleOverride?: string; + componentTextOverrides?: BrandingPreferenceTextProps; + screen: ScreenType; +} export interface I18n { - setTranslations: ( - screen: ScreenType, - componentLocaleOverride?: string, - componentTextOverrides?: BrandingPreferenceTextProps, - ) => Promise; + setTranslations: (props: SetTranslationsProps) => Promise; text: I18nLocalization; } diff --git a/packages/react/src/providers/AsgardeoProvider.tsx b/packages/react/src/providers/AsgardeoProvider.tsx index 00b1abff..af5b92f6 100644 --- a/packages/react/src/providers/AsgardeoProvider.tsx +++ b/packages/react/src/providers/AsgardeoProvider.tsx @@ -24,6 +24,7 @@ import AsgardeProviderProps from '../models/asgardeo-provider-props'; import AuthContext from '../models/auth-context'; import SPACryptoUtils from '../utils/crypto-utils'; import SessionStore from '../utils/session-store'; +import I18nProvider from './I18nProvider'; const AsgardeoProvider: FC> = ( props: PropsWithChildren, @@ -91,7 +92,11 @@ const AsgardeoProvider: FC> = ( return ( - {children} + + + {children} + + ); }; diff --git a/packages/react/src/providers/I18nProvider.tsx b/packages/react/src/providers/I18nProvider.tsx new file mode 100644 index 00000000..f6d3ace4 --- /dev/null +++ b/packages/react/src/providers/I18nProvider.tsx @@ -0,0 +1,58 @@ +/** + * Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import {BrandingPreferenceTextProps, TextObject, getLocalization} from '@asgardeo/js-ui-core'; +import {FC, PropsWithChildren, useCallback, useMemo, useState} from 'react'; +import I18nContext from '../contexts/i18n-context'; +import {I18n, I18nLocalization, SetTranslationsProps} from '../models/i18n'; + +interface I18nProviderProps { + providerLocaleOverride?: string; + providerTextOverrides?: BrandingPreferenceTextProps; +} + +const I18nProvider: FC> = (props: PropsWithChildren) => { + const {children, providerLocaleOverride, providerTextOverrides} = props; + + const [text, setText] = useState({}); + + const setTranslations: (setTranslationProps: SetTranslationsProps) => Promise = useCallback( + async (setTranslationProps: SetTranslationsProps): Promise => { + const {componentLocaleOverride, componentTextOverrides, screen} = setTranslationProps; + + if (!Object.prototype.hasOwnProperty.call(text, screen)) { + const newText: TextObject = await getLocalization({ + componentTextOverrides, + locale: componentLocaleOverride ?? providerLocaleOverride ?? 'en-US', + providerTextOverrides, + screen, + }); + + setText({...text, [screen]: newText}); + } + return true; + }, + [providerLocaleOverride, providerTextOverrides, text], + ); + + const value: I18n = useMemo(() => ({setTranslations, text}), [setTranslations, text]); + + return {children}; +}; + +export default I18nProvider; From f95920a4d0af3cdf35bc94d7a4d96f5719079553 Mon Sep 17 00:00:00 2001 From: Movin Silva Date: Tue, 14 May 2024 15:40:47 +0530 Subject: [PATCH 14/19] refactor(core): :recycle: refactor getLocalization function --- packages/core/src/i18n/get-localization.ts | 17 +++++++++++------ packages/core/src/models/auth-config.ts | 12 ++---------- packages/core/src/models/branding.ts | 2 ++ .../core/src/models/get-localization-props.ts | 6 +++--- 4 files changed, 18 insertions(+), 19 deletions(-) diff --git a/packages/core/src/i18n/get-localization.ts b/packages/core/src/i18n/get-localization.ts index 5b7c3a78..84844730 100644 --- a/packages/core/src/i18n/get-localization.ts +++ b/packages/core/src/i18n/get-localization.ts @@ -16,11 +16,14 @@ * under the License. */ +import {AuthClientConfig} from '@asgardeo/auth-js'; import merge from 'lodash.merge'; import {TextObject} from './screens/model'; import getBrandingPreferenceText from '../api/get-branding-preference-text'; import {AuthClient} from '../auth-client'; import AsgardeoUIException from '../exception'; +import {UIAuthConfig} from '../models/auth-config'; +import {BrandingPreferenceTypes} from '../models/branding-api-response'; import {BrandingPreferenceTextAPIResponse} from '../models/branding-text-api-response'; import GetLocalizationProps from '../models/get-localization-props'; @@ -31,19 +34,21 @@ import GetLocalizationProps from '../models/get-localization-props'; * @returns {Promise} A promise that resolves with the merged branding properties. */ const getLocalization = async (props: GetLocalizationProps): Promise => { - const {componentCustomization, locale, providerCustomization, screen} = props; + const {componentTextOverrides, locale, providerTextOverrides, screen} = props; const module: TextObject = await import(`./screens/${screen}/${locale}.ts`); let textFromConsoleBranding: BrandingPreferenceTextAPIResponse; + const configData: AuthClientConfig = await AuthClient.getInstance().getDataLayer().getConfigData(); + try { - if ((await AuthClient.getInstance().getDataLayer().getConfigData()).enableConsoleTextBranding ?? true) { + if (configData.enableConsoleTextBranding ?? true) { textFromConsoleBranding = await getBrandingPreferenceText({ locale, - name: providerCustomization.name, + name: configData.name ?? 'carbon.super', screen, - type: providerCustomization.type, + type: configData.type ?? BrandingPreferenceTypes.Org, }); } } catch (error) { @@ -69,11 +74,11 @@ const getLocalization = async (props: GetLocalizationProps): Promise /** * PRIORITY 02: Text from provider customization */ - providerCustomization?.preference?.text?.[locale]?.[screen] ?? {}, + providerTextOverrides?.[locale]?.[screen] ?? {}, /** * PRIORITY 01: Text from component customization */ - componentCustomization?.preference?.text?.[locale]?.[screen] ?? {}, + componentTextOverrides?.[locale]?.[screen] ?? {}, ); return mergedText; diff --git a/packages/core/src/models/auth-config.ts b/packages/core/src/models/auth-config.ts index db96624c..a86565df 100644 --- a/packages/core/src/models/auth-config.ts +++ b/packages/core/src/models/auth-config.ts @@ -17,6 +17,7 @@ */ import {AsgardeoAuthClient, AuthClientConfig} from '@asgardeo/auth-js'; +import {BrandingPreferenceTypes} from './branding-api-response'; /** * Interface for the configuration extension from the AuthClientConfig of '@asgardeo/auth-js'. @@ -39,16 +40,7 @@ interface AuthClientConfigExtension { /** * Type to filter the retrieval of customizations. */ - type?: OrgType; -} - -/** - * Enum for the organization type. - */ -export enum OrgType { - App = 'APP', - Custom = 'CUSTOM', - Org = 'ORG', + type?: BrandingPreferenceTypes; } /** diff --git a/packages/core/src/models/branding.ts b/packages/core/src/models/branding.ts index 972e929f..1c2be0dd 100644 --- a/packages/core/src/models/branding.ts +++ b/packages/core/src/models/branding.ts @@ -25,6 +25,8 @@ import {TextPreference} from '../i18n/screens/model'; */ export type BrandingPreferenceText = Record; +export type BrandingPreferenceTextProps = RecursivePartial; + interface BrandingPreferenceWithText extends BrandingPreference { text?: BrandingPreferenceText; } diff --git a/packages/core/src/models/get-localization-props.ts b/packages/core/src/models/get-localization-props.ts index 63abeb47..7eee4d56 100644 --- a/packages/core/src/models/get-localization-props.ts +++ b/packages/core/src/models/get-localization-props.ts @@ -16,7 +16,7 @@ * under the License. */ -import {BrandingProps} from './branding'; +import {BrandingPreferenceTextProps} from './branding'; import {ScreenType} from './screen-type'; /** @@ -26,7 +26,7 @@ interface GetLocalizationProps { /** * Customiztion prop passed to the component */ - componentCustomization?: BrandingProps; + componentTextOverrides?: BrandingPreferenceTextProps; /** * Locale to filter the retrieval of localization. */ @@ -34,7 +34,7 @@ interface GetLocalizationProps { /** * Customization prop passed to the provider */ - providerCustomization?: BrandingProps; + providerTextOverrides?: BrandingPreferenceTextProps; /** * Screen to filter the retrieval of localization. */ From 92a994ff73a9a071144b584ba0bd5540b0942428 Mon Sep 17 00:00:00 2001 From: Movin Silva Date: Tue, 14 May 2024 16:02:47 +0530 Subject: [PATCH 15/19] feat(react): :sparkles: add useAuthentication hook --- .../react/src/hooks/use-authentication.ts | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 packages/react/src/hooks/use-authentication.ts diff --git a/packages/react/src/hooks/use-authentication.ts b/packages/react/src/hooks/use-authentication.ts new file mode 100644 index 00000000..dd727f8e --- /dev/null +++ b/packages/react/src/hooks/use-authentication.ts @@ -0,0 +1,43 @@ +/** + * Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import {MeAPIResponse, signOut as signOutApiCall} from '@asgardeo/js-ui-core'; +import {useContext} from 'react'; +import AsgardeoContext from '../contexts/asgardeo-context'; +import AuthContext from '../models/auth-context'; + +interface UseAuthenticationResponse { + accessToken: string; + isAuthenticated: Promise | boolean; + signOut: () => void; + user: MeAPIResponse; +} + +export const useAuthentication = (): UseAuthenticationResponse => { + const contextValue: AuthContext = useContext(AsgardeoContext); + + const {user, isAuthenticated, accessToken} = contextValue; + + const signOut: () => void = () => { + signOutApiCall(); + sessionStorage.clear(); + window.location.reload(); + }; + + return {accessToken, isAuthenticated, signOut, user}; +}; From b620fc0162652b61b567c83038205c9d3012dd1d Mon Sep 17 00:00:00 2001 From: Movin Silva Date: Tue, 14 May 2024 16:29:29 +0530 Subject: [PATCH 16/19] feat(react): :sparkles: add useConfig hook --- packages/react/src/hooks/use-config.ts | 34 +++++++++++++++++++++++++ packages/react/src/models/use-config.ts | 25 ++++++++++++++++++ 2 files changed, 59 insertions(+) create mode 100644 packages/react/src/hooks/use-config.ts create mode 100644 packages/react/src/models/use-config.ts diff --git a/packages/react/src/hooks/use-config.ts b/packages/react/src/hooks/use-config.ts new file mode 100644 index 00000000..7e2c9171 --- /dev/null +++ b/packages/react/src/hooks/use-config.ts @@ -0,0 +1,34 @@ +/** + * Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import {UIAuthConfig} from '@asgardeo/js-ui-core'; +import {useContext} from 'react'; +import AsgardeoContext from '../contexts/asgardeo-context'; +import UseConfig from '../models/use-config'; + +/** + * Custom hook to access the authentication configuration from the AsgardeoProviderContext. + * @returns An object containing the authentication configuration. + */ +export const useConfig = (): UseConfig => { + const {config} = useContext(AsgardeoContext) as { + config: UIAuthConfig; + }; + + return {config}; +}; diff --git a/packages/react/src/models/use-config.ts b/packages/react/src/models/use-config.ts new file mode 100644 index 00000000..169d1d51 --- /dev/null +++ b/packages/react/src/models/use-config.ts @@ -0,0 +1,25 @@ +/** + * Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import {UIAuthConfig} from '@asgardeo/js-ui-core'; + +interface UseConfig { + config: UIAuthConfig; +} + +export default UseConfig; From 7280565f6ebe2f502e39d1e96c5ecef581a04bc0 Mon Sep 17 00:00:00 2001 From: Movin Silva Date: Tue, 14 May 2024 16:47:36 +0530 Subject: [PATCH 17/19] feat(react): :sparkles: add useTranslations hook --- packages/react/package.json | 2 +- packages/react/src/hooks/use-translations.ts | 71 ++++ packages/react/src/models/use-translations.ts | 24 ++ pnpm-lock.yaml | 308 ++++++++++++++++-- 4 files changed, 376 insertions(+), 29 deletions(-) create mode 100644 packages/react/src/hooks/use-translations.ts create mode 100644 packages/react/src/models/use-translations.ts diff --git a/packages/react/package.json b/packages/react/package.json index f5fb85af..5c48988b 100644 --- a/packages/react/package.json +++ b/packages/react/package.json @@ -47,7 +47,7 @@ "sass": "^1.75.0", "stylelint": "15.1.0", "tslib": "^2.6.2", - "typescript": "^5.4.5" + "typescript": "5.1.6" }, "dependencies": { "@asgardeo/js-ui-core": "*", diff --git a/packages/react/src/hooks/use-translations.ts b/packages/react/src/hooks/use-translations.ts new file mode 100644 index 00000000..f8750ca2 --- /dev/null +++ b/packages/react/src/hooks/use-translations.ts @@ -0,0 +1,71 @@ +/** + * Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import {useContext, useEffect, useState} from 'react'; +import I18nContext from '../contexts/i18n-context'; +import {I18n, SetTranslationsProps} from '../models/i18n'; +import UseTranslations from '../models/use-translations'; + +/** + * `useTranslations` is a custom hook that fetches translations. + * It takes an object of type `SetTranslationsProps` as an argument, which includes the screen type, + * and optional locale and text overrides. + * + * @param {SetTranslationsProps} props - The properties used to fetch the translations. + * @param {ScreenType} props.screen - The screen type for which to fetch translations. + * @param {string} [props.componentLocaleOverride] - Optional locale override. + * @param {BrandingPreferenceTextProps} [props.componentTextOverrides] - Optional text overrides. + * + * @returns {UseTranslations} An object containing the translations (`t`) and a loading state (`isLoading`). + */ +const useTranslations = (props: SetTranslationsProps): UseTranslations => { + const {componentLocaleOverride, componentTextOverrides, screen} = props; + + const [isLoading, setIsLoading] = useState(true); + + const contextValue: I18n = useContext(I18nContext); + const {text, setTranslations} = contextValue; + + useEffect(() => { + setTranslations({componentLocaleOverride, componentTextOverrides, screen}).then((response: boolean) => { + setIsLoading(!response); + }); + }, [componentLocaleOverride, componentTextOverrides, screen, setTranslations]); + + /** + * `t` is a function that retrieves a specific translation from the fetched translations. + * It takes a key as an argument, which is a string that represents a path to the desired translation. + * + * @param {string} key - The key of the translation to retrieve. This is a string that represents + * a path in the translations object, with parts separated by '.'. + * + * @returns {string} The requested translation. + */ + const t = (key: string): string => { + const parts: string[] = key.split('.'); + + const screenKey: string = parts[0]; + const rightPart: string = parts.slice(1).join('.'); + + return text[screenKey][rightPart]; + }; + + return {isLoading, t}; +}; + +export default useTranslations; diff --git a/packages/react/src/models/use-translations.ts b/packages/react/src/models/use-translations.ts new file mode 100644 index 00000000..ed53fe5b --- /dev/null +++ b/packages/react/src/models/use-translations.ts @@ -0,0 +1,24 @@ +/** + * Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +interface UseTranslations { + isLoading: boolean; + t: (key: string) => string; +} + +export default UseTranslations; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 19e08746..87817104 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -77,7 +77,7 @@ importers: version: link:../core '@oxygen-ui/react': specifier: ^1.11.0 - version: 1.11.0(@emotion/react@11.11.4)(@emotion/styled@11.11.5)(@mui/icons-material@5.15.17)(@mui/lab@5.0.0-alpha.110)(@mui/material@5.15.17)(@mui/system@5.15.15)(@mui/utils@5.15.14)(@types/react@18.3.1)(react-dom@18.3.1)(react@18.3.1)(typescript@5.4.5) + version: 1.11.0(@emotion/react@11.11.4)(@emotion/styled@11.11.5)(@mui/icons-material@5.15.17)(@mui/lab@5.0.0-alpha.110)(@mui/material@5.15.17)(@mui/system@5.15.15)(@mui/utils@5.15.14)(@types/react@18.3.1)(react-dom@18.3.1)(react@18.3.1)(typescript@5.1.6) base64url: specifier: ^3.0.1 version: 3.0.1 @@ -111,13 +111,13 @@ importers: version: 18.3.0 '@wso2/eslint-plugin': specifier: https://gitpkg.now.sh/brionmario/wso2-ui-configs/packages/eslint-plugin?fa0b844715320a3953d6d055997c0770f8695082 - version: '@gitpkg.now.sh/brionmario/wso2-ui-configs/packages/eslint-plugin?fa0b844715320a3953d6d055997c0770f8695082(eslint@8.57.0)(typescript@5.4.5)' + version: '@gitpkg.now.sh/brionmario/wso2-ui-configs/packages/eslint-plugin?fa0b844715320a3953d6d055997c0770f8695082(eslint@8.57.0)(typescript@5.1.6)' '@wso2/prettier-config': specifier: https://gitpkg.now.sh/brionmario/wso2-ui-configs/packages/prettier-config?fa0b844715320a3953d6d055997c0770f8695082 - version: '@gitpkg.now.sh/brionmario/wso2-ui-configs/packages/prettier-config?fa0b844715320a3953d6d055997c0770f8695082(prettier@3.2.5)(typescript@5.4.5)' + version: '@gitpkg.now.sh/brionmario/wso2-ui-configs/packages/prettier-config?fa0b844715320a3953d6d055997c0770f8695082(prettier@3.2.5)(typescript@5.1.6)' '@wso2/stylelint-config': specifier: https://gitpkg.now.sh/brionmario/wso2-ui-configs/packages/stylelint-config?fa0b844715320a3953d6d055997c0770f8695082 - version: '@gitpkg.now.sh/brionmario/wso2-ui-configs/packages/stylelint-config?fa0b844715320a3953d6d055997c0770f8695082(postcss@8.4.38)(stylelint@15.1.0)(typescript@5.4.5)' + version: '@gitpkg.now.sh/brionmario/wso2-ui-configs/packages/stylelint-config?fa0b844715320a3953d6d055997c0770f8695082(postcss@8.4.38)(stylelint@15.1.0)(typescript@5.1.6)' eslint: specifier: ~8.57.0 version: 8.57.0 @@ -135,13 +135,13 @@ importers: version: 1.76.0 stylelint: specifier: 15.1.0 - version: 15.1.0(typescript@5.4.5) + version: 15.1.0(typescript@5.1.6) tslib: specifier: ^2.6.2 version: 2.6.2 typescript: - specifier: ^5.4.5 - version: 5.4.5 + specifier: 5.1.6 + version: 5.1.6 packages: @@ -1051,7 +1051,7 @@ packages: resolution: {integrity: sha512-z1d75MVfkYYrLiBRFPJJNvcMc1/j5qd9eZZGMXH04Ipg1VbVHj3DGl6BvqRGIHeBdNtm3NgjBwx8VfqHQ/i6HA==} dev: false - /@oxygen-ui/react-icons@1.11.0(react-dom@18.3.1)(react@18.3.1)(typescript@5.4.5): + /@oxygen-ui/react-icons@1.11.0(react-dom@18.3.1)(react@18.3.1)(typescript@5.1.6): resolution: {integrity: sha512-qb1bCzC6c0xecRHneQy6T0LlGNLMvqomw1kuExubstn1kcebF7Y+TH8hjlrr4F3tp+upTBRXNEsVAUeq24Xnpw==} peerDependencies: react: '>=18.0.0' @@ -1063,10 +1063,10 @@ packages: dependencies: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - typescript: 5.4.5 + typescript: 5.1.6 dev: false - /@oxygen-ui/react@1.11.0(@emotion/react@11.11.4)(@emotion/styled@11.11.5)(@mui/icons-material@5.15.17)(@mui/lab@5.0.0-alpha.110)(@mui/material@5.15.17)(@mui/system@5.15.15)(@mui/utils@5.15.14)(@types/react@18.3.1)(react-dom@18.3.1)(react@18.3.1)(typescript@5.4.5): + /@oxygen-ui/react@1.11.0(@emotion/react@11.11.4)(@emotion/styled@11.11.5)(@mui/icons-material@5.15.17)(@mui/lab@5.0.0-alpha.110)(@mui/material@5.15.17)(@mui/system@5.15.15)(@mui/utils@5.15.14)(@types/react@18.3.1)(react-dom@18.3.1)(react@18.3.1)(typescript@5.1.6): resolution: {integrity: sha512-Ij9E3CvX/fNGQkWbH6ic9LNsldFHeuy/2adksNsJLQgVsbvPct/coXyPYF8duH17dPEu6nksEHJwIfxoz9ekww==} peerDependencies: '@emotion/react': ^11.10.5 @@ -1092,12 +1092,12 @@ packages: '@mui/utils': 5.15.14(@types/react@18.3.1)(react@18.3.1) '@mui/x-data-grid': 6.19.11(@mui/material@5.15.17)(@mui/system@5.15.15)(@types/react@18.3.1)(react-dom@18.3.1)(react@18.3.1) '@oxygen-ui/primitives': 1.11.0 - '@oxygen-ui/react-icons': 1.11.0(react-dom@18.3.1)(react@18.3.1)(typescript@5.4.5) + '@oxygen-ui/react-icons': 1.11.0(react-dom@18.3.1)(react@18.3.1)(typescript@5.1.6) clsx: 1.2.1 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) react-world-flags: 1.6.0(react@18.3.1) - typescript: 5.4.5 + typescript: 5.1.6 transitivePeerDependencies: - '@types/react' dev: false @@ -1412,6 +1412,34 @@ packages: resolution: {integrity: sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==} dev: true + /@typescript-eslint/eslint-plugin@5.62.0(@typescript-eslint/parser@5.62.0)(eslint@8.57.0)(typescript@5.1.6): + resolution: {integrity: sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + '@typescript-eslint/parser': ^5.0.0 + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@eslint-community/regexpp': 4.10.0 + '@typescript-eslint/parser': 5.62.0(eslint@8.57.0)(typescript@5.1.6) + '@typescript-eslint/scope-manager': 5.62.0 + '@typescript-eslint/type-utils': 5.62.0(eslint@8.57.0)(typescript@5.1.6) + '@typescript-eslint/utils': 5.62.0(eslint@8.57.0)(typescript@5.1.6) + debug: 4.3.4 + eslint: 8.57.0 + graphemer: 1.4.0 + ignore: 5.3.1 + natural-compare-lite: 1.4.0 + semver: 7.6.0 + tsutils: 3.21.0(typescript@5.1.6) + typescript: 5.1.6 + transitivePeerDependencies: + - supports-color + dev: true + /@typescript-eslint/eslint-plugin@5.62.0(@typescript-eslint/parser@5.62.0)(eslint@8.57.0)(typescript@5.4.5): resolution: {integrity: sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -1440,6 +1468,19 @@ packages: - supports-color dev: true + /@typescript-eslint/experimental-utils@5.62.0(eslint@8.57.0)(typescript@5.1.6): + resolution: {integrity: sha512-RTXpeB3eMkpoclG3ZHft6vG/Z30azNHuqY6wKPBHlVMZFuEvrtlEDe8gMqDb+SO+9hjC/pLekeSCryf9vMZlCw==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + dependencies: + '@typescript-eslint/utils': 5.62.0(eslint@8.57.0)(typescript@5.1.6) + eslint: 8.57.0 + transitivePeerDependencies: + - supports-color + - typescript + dev: true + /@typescript-eslint/experimental-utils@5.62.0(eslint@8.57.0)(typescript@5.4.5): resolution: {integrity: sha512-RTXpeB3eMkpoclG3ZHft6vG/Z30azNHuqY6wKPBHlVMZFuEvrtlEDe8gMqDb+SO+9hjC/pLekeSCryf9vMZlCw==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -1453,6 +1494,26 @@ packages: - typescript dev: true + /@typescript-eslint/parser@5.62.0(eslint@8.57.0)(typescript@5.1.6): + resolution: {integrity: sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/scope-manager': 5.62.0 + '@typescript-eslint/types': 5.62.0 + '@typescript-eslint/typescript-estree': 5.62.0(typescript@5.1.6) + debug: 4.3.4 + eslint: 8.57.0 + typescript: 5.1.6 + transitivePeerDependencies: + - supports-color + dev: true + /@typescript-eslint/parser@5.62.0(eslint@8.57.0)(typescript@5.4.5): resolution: {integrity: sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -1481,6 +1542,26 @@ packages: '@typescript-eslint/visitor-keys': 5.62.0 dev: true + /@typescript-eslint/type-utils@5.62.0(eslint@8.57.0)(typescript@5.1.6): + resolution: {integrity: sha512-xsSQreu+VnfbqQpW5vnCJdq1Z3Q0U31qiWmRhr98ONQmcp/yhiPJFPq8MXiJVLiksmOKSjIldZzkebzHuCGzew==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: '*' + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/typescript-estree': 5.62.0(typescript@5.1.6) + '@typescript-eslint/utils': 5.62.0(eslint@8.57.0)(typescript@5.1.6) + debug: 4.3.4 + eslint: 8.57.0 + tsutils: 3.21.0(typescript@5.1.6) + typescript: 5.1.6 + transitivePeerDependencies: + - supports-color + dev: true + /@typescript-eslint/type-utils@5.62.0(eslint@8.57.0)(typescript@5.4.5): resolution: {integrity: sha512-xsSQreu+VnfbqQpW5vnCJdq1Z3Q0U31qiWmRhr98ONQmcp/yhiPJFPq8MXiJVLiksmOKSjIldZzkebzHuCGzew==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -1506,6 +1587,27 @@ packages: engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dev: true + /@typescript-eslint/typescript-estree@5.62.0(typescript@5.1.6): + resolution: {integrity: sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/types': 5.62.0 + '@typescript-eslint/visitor-keys': 5.62.0 + debug: 4.3.4 + globby: 11.1.0 + is-glob: 4.0.3 + semver: 7.6.0 + tsutils: 3.21.0(typescript@5.1.6) + typescript: 5.1.6 + transitivePeerDependencies: + - supports-color + dev: true + /@typescript-eslint/typescript-estree@5.62.0(typescript@5.4.5): resolution: {integrity: sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -1527,6 +1629,26 @@ packages: - supports-color dev: true + /@typescript-eslint/utils@5.62.0(eslint@8.57.0)(typescript@5.1.6): + resolution: {integrity: sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) + '@types/json-schema': 7.0.15 + '@types/semver': 7.5.8 + '@typescript-eslint/scope-manager': 5.62.0 + '@typescript-eslint/types': 5.62.0 + '@typescript-eslint/typescript-estree': 5.62.0(typescript@5.1.6) + eslint: 8.57.0 + eslint-scope: 5.1.1 + semver: 7.6.0 + transitivePeerDependencies: + - supports-color + - typescript + dev: true + /@typescript-eslint/utils@5.62.0(eslint@8.57.0)(typescript@5.4.5): resolution: {integrity: sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -2082,7 +2204,7 @@ packages: yaml: 1.10.2 dev: false - /cosmiconfig@8.3.6(typescript@5.4.5): + /cosmiconfig@8.3.6(typescript@5.1.6): resolution: {integrity: sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==} engines: {node: '>=14'} peerDependencies: @@ -2095,7 +2217,7 @@ packages: js-yaml: 4.1.0 parse-json: 5.2.0 path-type: 4.0.0 - typescript: 5.4.5 + typescript: 5.1.6 dev: true /cross-spawn@7.0.3: @@ -2533,8 +2655,8 @@ packages: eslint: ^7.32.0 || ^8.2.0 eslint-plugin-import: ^2.25.3 dependencies: - '@typescript-eslint/eslint-plugin': 5.62.0(@typescript-eslint/parser@5.62.0)(eslint@8.57.0)(typescript@5.4.5) - '@typescript-eslint/parser': 5.62.0(eslint@8.57.0)(typescript@5.4.5) + '@typescript-eslint/eslint-plugin': 5.62.0(@typescript-eslint/parser@5.62.0)(eslint@8.57.0)(typescript@5.1.6) + '@typescript-eslint/parser': 5.62.0(eslint@8.57.0)(typescript@5.1.6) eslint: 8.57.0 eslint-config-airbnb-base: 15.0.0(eslint-plugin-import@2.29.1)(eslint@8.57.0) eslint-plugin-import: 2.29.1(@typescript-eslint/parser@5.62.0)(eslint@8.57.0) @@ -2600,7 +2722,7 @@ packages: eslint-import-resolver-webpack: optional: true dependencies: - '@typescript-eslint/parser': 5.62.0(eslint@8.57.0)(typescript@5.4.5) + '@typescript-eslint/parser': 5.62.0(eslint@8.57.0)(typescript@5.1.6) debug: 3.2.7 eslint: 8.57.0 eslint-import-resolver-node: 0.3.9 @@ -2648,7 +2770,7 @@ packages: '@typescript-eslint/parser': optional: true dependencies: - '@typescript-eslint/parser': 5.62.0(eslint@8.57.0)(typescript@5.4.5) + '@typescript-eslint/parser': 5.62.0(eslint@8.57.0)(typescript@5.1.6) array-includes: 3.1.8 array.prototype.findlastindex: 1.2.5 array.prototype.flat: 1.3.2 @@ -2673,6 +2795,27 @@ packages: - supports-color dev: true + /eslint-plugin-jest@27.9.0(@typescript-eslint/eslint-plugin@5.62.0)(eslint@8.57.0)(typescript@5.1.6): + resolution: {integrity: sha512-QIT7FH7fNmd9n4se7FFKHbsLKGQiw885Ds6Y/sxKgCZ6natwCsXdgPOADnYVxN2QrRweF0FZWbJ6S7Rsn7llug==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + peerDependencies: + '@typescript-eslint/eslint-plugin': ^5.0.0 || ^6.0.0 || ^7.0.0 + eslint: ^7.0.0 || ^8.0.0 + jest: '*' + peerDependenciesMeta: + '@typescript-eslint/eslint-plugin': + optional: true + jest: + optional: true + dependencies: + '@typescript-eslint/eslint-plugin': 5.62.0(@typescript-eslint/parser@5.62.0)(eslint@8.57.0)(typescript@5.1.6) + '@typescript-eslint/utils': 5.62.0(eslint@8.57.0)(typescript@5.1.6) + eslint: 8.57.0 + transitivePeerDependencies: + - supports-color + - typescript + dev: true + /eslint-plugin-jest@27.9.0(@typescript-eslint/eslint-plugin@5.62.0)(eslint@8.57.0)(typescript@5.4.5): resolution: {integrity: sha512-QIT7FH7fNmd9n4se7FFKHbsLKGQiw885Ds6Y/sxKgCZ6natwCsXdgPOADnYVxN2QrRweF0FZWbJ6S7Rsn7llug==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -2787,6 +2930,19 @@ packages: string.prototype.matchall: 4.0.11 dev: true + /eslint-plugin-testing-library@5.11.1(eslint@8.57.0)(typescript@5.1.6): + resolution: {integrity: sha512-5eX9e1Kc2PqVRed3taaLnAAqPZGEX75C+M/rXzUAI3wIg/ZxzUm1OVAwfe/O+vE+6YXOLetSe9g5GKD2ecXipw==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0, npm: '>=6'} + peerDependencies: + eslint: ^7.5.0 || ^8.0.0 + dependencies: + '@typescript-eslint/utils': 5.62.0(eslint@8.57.0)(typescript@5.1.6) + eslint: 8.57.0 + transitivePeerDependencies: + - supports-color + - typescript + dev: true + /eslint-plugin-testing-library@5.11.1(eslint@8.57.0)(typescript@5.4.5): resolution: {integrity: sha512-5eX9e1Kc2PqVRed3taaLnAAqPZGEX75C+M/rXzUAI3wIg/ZxzUm1OVAwfe/O+vE+6YXOLetSe9g5GKD2ecXipw==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0, npm: '>=6'} @@ -2807,6 +2963,24 @@ packages: '@microsoft/tsdoc-config': 0.16.2 dev: true + /eslint-plugin-typescript-sort-keys@2.3.0(@typescript-eslint/parser@5.62.0)(eslint@8.57.0)(typescript@5.1.6): + resolution: {integrity: sha512-3LAcYulo5gNYiPWee+TksITfvWeBuBjGgcSLTacPESFVKEoy8laOQuZvJlSCwTBHT2SCGIxr3bJ56zuux+3MCQ==} + engines: {node: 12 || >= 13.9} + peerDependencies: + '@typescript-eslint/parser': ^1 || ^2 || ^3 || ^4 || ^5 + eslint: ^5 || ^6 || ^7 || ^8 + typescript: ^3 || ^4 || ^5 + dependencies: + '@typescript-eslint/experimental-utils': 5.62.0(eslint@8.57.0)(typescript@5.1.6) + '@typescript-eslint/parser': 5.62.0(eslint@8.57.0)(typescript@5.1.6) + eslint: 8.57.0 + json-schema: 0.4.0 + natural-compare-lite: 1.4.0 + typescript: 5.1.6 + transitivePeerDependencies: + - supports-color + dev: true + /eslint-plugin-typescript-sort-keys@2.3.0(@typescript-eslint/parser@5.62.0)(eslint@8.57.0)(typescript@5.4.5): resolution: {integrity: sha512-3LAcYulo5gNYiPWee+TksITfvWeBuBjGgcSLTacPESFVKEoy8laOQuZvJlSCwTBHT2SCGIxr3bJ56zuux+3MCQ==} engines: {node: 12 || >= 13.9} @@ -4895,7 +5069,7 @@ packages: dependencies: postcss: 8.4.38 postcss-scss: 4.0.9(postcss@8.4.38) - stylelint: 15.1.0(typescript@5.4.5) + stylelint: 15.1.0(typescript@5.1.6) stylelint-config-recommended: 9.0.0(stylelint@15.1.0) stylelint-scss: 4.7.0(stylelint@15.1.0) dev: true @@ -4905,7 +5079,7 @@ packages: peerDependencies: stylelint: ^14.10.0 dependencies: - stylelint: 15.1.0(typescript@5.4.5) + stylelint: 15.1.0(typescript@5.1.6) dev: true /stylelint-config-standard-scss@6.1.0(postcss@8.4.38)(stylelint@15.1.0): @@ -4918,7 +5092,7 @@ packages: optional: true dependencies: postcss: 8.4.38 - stylelint: 15.1.0(typescript@5.4.5) + stylelint: 15.1.0(typescript@5.1.6) stylelint-config-recommended-scss: 8.0.0(postcss@8.4.38)(stylelint@15.1.0) stylelint-config-standard: 29.0.0(stylelint@15.1.0) dev: true @@ -4928,7 +5102,7 @@ packages: peerDependencies: stylelint: ^14.14.0 dependencies: - stylelint: 15.1.0(typescript@5.4.5) + stylelint: 15.1.0(typescript@5.1.6) stylelint-config-recommended: 9.0.0(stylelint@15.1.0) dev: true @@ -4941,10 +5115,10 @@ packages: postcss-resolve-nested-selector: 0.1.1 postcss-selector-parser: 6.0.16 postcss-value-parser: 4.2.0 - stylelint: 15.1.0(typescript@5.4.5) + stylelint: 15.1.0(typescript@5.1.6) dev: true - /stylelint@15.1.0(typescript@5.4.5): + /stylelint@15.1.0(typescript@5.1.6): resolution: {integrity: sha512-Tw8OyIiYhxnIHUzgoLlCyWgCUKsPYiP3TDgs7M1VbayS+q5qZly2yxABg+YPe/hFRWiu0cOtptCtpyrn1CrnYw==} engines: {node: ^14.13.1 || >=16.0.0} hasBin: true @@ -4955,7 +5129,7 @@ packages: '@csstools/selector-specificity': 2.2.0(postcss-selector-parser@6.0.16) balanced-match: 2.0.0 colord: 2.9.3 - cosmiconfig: 8.3.6(typescript@5.4.5) + cosmiconfig: 8.3.6(typescript@5.1.6) css-functions-list: 3.2.2 css-tree: 2.3.1 debug: 4.3.4 @@ -5125,6 +5299,16 @@ packages: resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==} dev: true + /tsutils@3.21.0(typescript@5.1.6): + resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==} + engines: {node: '>= 6'} + peerDependencies: + typescript: '>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta' + dependencies: + tslib: 1.14.1 + typescript: 5.1.6 + dev: true + /tsutils@3.21.0(typescript@5.4.5): resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==} engines: {node: '>= 6'} @@ -5206,10 +5390,16 @@ packages: possible-typed-array-names: 1.0.0 dev: true + /typescript@5.1.6: + resolution: {integrity: sha512-zaWCozRZ6DLEWAWFrVDz1H6FVXzUSfTy5FUMWsQlU8Ym5JP9eO4xkTIROFCQvhQf61z6O/G6ugw3SgAnvvm+HA==} + engines: {node: '>=14.17'} + hasBin: true + /typescript@5.4.5: resolution: {integrity: sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==} engines: {node: '>=14.17'} hasBin: true + dev: true /unbox-primitive@1.0.2: resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==} @@ -5402,6 +5592,51 @@ packages: engines: {node: '>=10'} dev: true + '@gitpkg.now.sh/brionmario/wso2-ui-configs/packages/eslint-plugin?fa0b844715320a3953d6d055997c0770f8695082(eslint@8.57.0)(typescript@5.1.6)': + resolution: {tarball: https://gitpkg.now.sh/brionmario/wso2-ui-configs/packages/eslint-plugin?fa0b844715320a3953d6d055997c0770f8695082} + id: '@gitpkg.now.sh/brionmario/wso2-ui-configs/packages/eslint-plugin?fa0b844715320a3953d6d055997c0770f8695082' + name: '@wso2/eslint-plugin' + version: 0.1.0 + engines: {node: ^14.17.0 || ^16.0.0 || >= 18.0.0} + peerDependencies: + eslint: '>=8.0.0' + typescript: '>=4.0.0' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@babel/core': 7.24.4 + '@babel/eslint-parser': 7.24.1(@babel/core@7.24.4)(eslint@8.57.0) + '@next/eslint-plugin-next': 13.5.6 + '@typescript-eslint/eslint-plugin': 5.62.0(@typescript-eslint/parser@5.62.0)(eslint@8.57.0)(typescript@5.1.6) + '@typescript-eslint/parser': 5.62.0(eslint@8.57.0)(typescript@5.1.6) + eslint: 8.57.0 + eslint-config-airbnb: 19.0.4(eslint-plugin-import@2.29.1)(eslint-plugin-jsx-a11y@6.8.0)(eslint-plugin-react-hooks@4.6.0)(eslint-plugin-react@7.34.1)(eslint@8.57.0) + eslint-config-airbnb-base: 15.0.0(eslint-plugin-import@2.29.1)(eslint@8.57.0) + eslint-config-airbnb-typescript: 17.1.0(@typescript-eslint/eslint-plugin@5.62.0)(@typescript-eslint/parser@5.62.0)(eslint-plugin-import@2.29.1)(eslint@8.57.0) + eslint-config-prettier: 8.10.0(eslint@8.57.0) + eslint-plugin-eslint-plugin: 5.5.1(eslint@8.57.0) + eslint-plugin-header: 3.1.1(eslint@8.57.0) + eslint-plugin-import: 2.29.1(@typescript-eslint/parser@5.62.0)(eslint@8.57.0) + eslint-plugin-jest: 27.9.0(@typescript-eslint/eslint-plugin@5.62.0)(eslint@8.57.0)(typescript@5.1.6) + eslint-plugin-jsx-a11y: 6.8.0(eslint@8.57.0) + eslint-plugin-node: 11.1.0(eslint@8.57.0) + eslint-plugin-prettier: 4.2.1(eslint-config-prettier@8.10.0)(eslint@8.57.0)(prettier@2.8.8) + eslint-plugin-react: 7.34.1(eslint@8.57.0) + eslint-plugin-react-hooks: 4.6.0(eslint@8.57.0) + eslint-plugin-testing-library: 5.11.1(eslint@8.57.0)(typescript@5.1.6) + eslint-plugin-tsdoc: 0.2.17 + eslint-plugin-typescript-sort-keys: 2.3.0(@typescript-eslint/parser@5.62.0)(eslint@8.57.0)(typescript@5.1.6) + prettier: 2.8.8 + requireindex: 1.2.0 + typescript: 5.1.6 + transitivePeerDependencies: + - eslint-import-resolver-typescript + - eslint-import-resolver-webpack + - jest + - supports-color + dev: true + '@gitpkg.now.sh/brionmario/wso2-ui-configs/packages/eslint-plugin?fa0b844715320a3953d6d055997c0770f8695082(eslint@8.57.0)(typescript@5.4.5)': resolution: {tarball: https://gitpkg.now.sh/brionmario/wso2-ui-configs/packages/eslint-plugin?fa0b844715320a3953d6d055997c0770f8695082} id: '@gitpkg.now.sh/brionmario/wso2-ui-configs/packages/eslint-plugin?fa0b844715320a3953d6d055997c0770f8695082' @@ -5447,6 +5682,23 @@ packages: - supports-color dev: true + '@gitpkg.now.sh/brionmario/wso2-ui-configs/packages/prettier-config?fa0b844715320a3953d6d055997c0770f8695082(prettier@3.2.5)(typescript@5.1.6)': + resolution: {tarball: https://gitpkg.now.sh/brionmario/wso2-ui-configs/packages/prettier-config?fa0b844715320a3953d6d055997c0770f8695082} + id: '@gitpkg.now.sh/brionmario/wso2-ui-configs/packages/prettier-config?fa0b844715320a3953d6d055997c0770f8695082' + name: '@wso2/prettier-config' + version: 0.1.0 + engines: {node: '>=14.0.0'} + peerDependencies: + prettier: '>=2.0.0' + typescript: '>=4.0.0' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + prettier: 3.2.5 + typescript: 5.1.6 + dev: true + '@gitpkg.now.sh/brionmario/wso2-ui-configs/packages/prettier-config?fa0b844715320a3953d6d055997c0770f8695082(prettier@3.2.5)(typescript@5.4.5)': resolution: {tarball: https://gitpkg.now.sh/brionmario/wso2-ui-configs/packages/prettier-config?fa0b844715320a3953d6d055997c0770f8695082} id: '@gitpkg.now.sh/brionmario/wso2-ui-configs/packages/prettier-config?fa0b844715320a3953d6d055997c0770f8695082' @@ -5464,7 +5716,7 @@ packages: typescript: 5.4.5 dev: true - '@gitpkg.now.sh/brionmario/wso2-ui-configs/packages/stylelint-config?fa0b844715320a3953d6d055997c0770f8695082(postcss@8.4.38)(stylelint@15.1.0)(typescript@5.4.5)': + '@gitpkg.now.sh/brionmario/wso2-ui-configs/packages/stylelint-config?fa0b844715320a3953d6d055997c0770f8695082(postcss@8.4.38)(stylelint@15.1.0)(typescript@5.1.6)': resolution: {tarball: https://gitpkg.now.sh/brionmario/wso2-ui-configs/packages/stylelint-config?fa0b844715320a3953d6d055997c0770f8695082} id: '@gitpkg.now.sh/brionmario/wso2-ui-configs/packages/stylelint-config?fa0b844715320a3953d6d055997c0770f8695082' name: '@wso2/stylelint-config' @@ -5478,9 +5730,9 @@ packages: optional: true dependencies: postcss-scss: 4.0.9(postcss@8.4.38) - stylelint: 15.1.0(typescript@5.4.5) + stylelint: 15.1.0(typescript@5.1.6) stylelint-config-standard-scss: 6.1.0(postcss@8.4.38)(stylelint@15.1.0) - typescript: 5.4.5 + typescript: 5.1.6 transitivePeerDependencies: - postcss dev: true From 0090aa9ea6e43f011d2e26e7100e18bbdc6756e3 Mon Sep 17 00:00:00 2001 From: Movin Silva Date: Tue, 14 May 2024 16:51:45 +0530 Subject: [PATCH 18/19] refactor(react): :recycle: refactor and add comments for useAuthentication hook --- .../react/src/hooks/use-authentication.ts | 21 ++++++++------ .../react/src/models/use-authentication.ts | 28 +++++++++++++++++++ 2 files changed, 40 insertions(+), 9 deletions(-) create mode 100644 packages/react/src/models/use-authentication.ts diff --git a/packages/react/src/hooks/use-authentication.ts b/packages/react/src/hooks/use-authentication.ts index dd727f8e..701093bc 100644 --- a/packages/react/src/hooks/use-authentication.ts +++ b/packages/react/src/hooks/use-authentication.ts @@ -16,19 +16,20 @@ * under the License. */ -import {MeAPIResponse, signOut as signOutApiCall} from '@asgardeo/js-ui-core'; +import {signOut as signOutApiCall} from '@asgardeo/js-ui-core'; import {useContext} from 'react'; import AsgardeoContext from '../contexts/asgardeo-context'; import AuthContext from '../models/auth-context'; +import UseAuthentication from '../models/use-authentication'; -interface UseAuthenticationResponse { - accessToken: string; - isAuthenticated: Promise | boolean; - signOut: () => void; - user: MeAPIResponse; -} - -export const useAuthentication = (): UseAuthenticationResponse => { +/** + * `useAuthentication` is a custom hook that provides access to the authentication context. + * It returns an object containing the current user, the authentication status, the access token, and a sign out function. + * + * @returns {UseAuthentication} An object containing the current user (`user`), the authentication status (`isAuthenticated`), + * the access token (`accessToken`), and a sign out function (`signOut`). + */ +const useAuthentication = (): UseAuthentication => { const contextValue: AuthContext = useContext(AsgardeoContext); const {user, isAuthenticated, accessToken} = contextValue; @@ -41,3 +42,5 @@ export const useAuthentication = (): UseAuthenticationResponse => { return {accessToken, isAuthenticated, signOut, user}; }; + +export default useAuthentication; diff --git a/packages/react/src/models/use-authentication.ts b/packages/react/src/models/use-authentication.ts new file mode 100644 index 00000000..dc18eafa --- /dev/null +++ b/packages/react/src/models/use-authentication.ts @@ -0,0 +1,28 @@ +/** + * Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import {MeAPIResponse} from '@asgardeo/js-ui-core'; + +interface UseAuthentication { + accessToken: string; + isAuthenticated: Promise | boolean; + signOut: () => void; + user: MeAPIResponse; +} + +export default UseAuthentication; From 23a37859b44599e454deaf3d569a48d0f9c69f6c Mon Sep 17 00:00:00 2001 From: Movin Silva Date: Tue, 14 May 2024 17:01:56 +0530 Subject: [PATCH 19/19] docs(react): :memo: add jsdocs --- packages/react/src/models/i18n.ts | 5 ++++ .../react/src/providers/AsgardeoProvider.tsx | 15 +++++++++- .../providers/BrandingPreferenceProvider.tsx | 11 +++++++ packages/react/src/providers/I18nProvider.tsx | 30 ++++++++++++++----- packages/react/src/theme/generate-theme.ts | 9 ++++++ 5 files changed, 62 insertions(+), 8 deletions(-) diff --git a/packages/react/src/models/i18n.ts b/packages/react/src/models/i18n.ts index 4221a953..343a78ff 100644 --- a/packages/react/src/models/i18n.ts +++ b/packages/react/src/models/i18n.ts @@ -33,3 +33,8 @@ export interface I18n { setTranslations: (props: SetTranslationsProps) => Promise; text: I18nLocalization; } + +export interface I18nProviderProps { + providerLocaleOverride?: string; + providerTextOverrides?: BrandingPreferenceTextProps; +} diff --git a/packages/react/src/providers/AsgardeoProvider.tsx b/packages/react/src/providers/AsgardeoProvider.tsx index af5b92f6..bab24026 100644 --- a/packages/react/src/providers/AsgardeoProvider.tsx +++ b/packages/react/src/providers/AsgardeoProvider.tsx @@ -19,13 +19,26 @@ import {AuthClient, CryptoUtils, MeAPIResponse, Store, UIAuthClient, getProfileInformation} from '@asgardeo/js-ui-core'; import {FC, PropsWithChildren, useCallback, useEffect, useMemo, useState} from 'react'; import BrandingPreferenceProvider from './BrandingPreferenceProvider'; +import I18nProvider from './I18nProvider'; import AsgardeoContext from '../contexts/asgardeo-context'; import AsgardeProviderProps from '../models/asgardeo-provider-props'; import AuthContext from '../models/auth-context'; import SPACryptoUtils from '../utils/crypto-utils'; import SessionStore from '../utils/session-store'; -import I18nProvider from './I18nProvider'; +/** + * `AsgardeoProvider` is a component that provides an Asgardeo context to all its children. + * It takes an object of type `AsgardeProviderProps` as props, which includes the children to render, + * a configuration object, a store instance, and a branding object. + * + * @param {PropsWithChildren} props - The properties passed to the component. + * @param {ReactNode} props.children - The children to render inside the provider. + * @param {Config} props.config - The configuration object for the Asgardeo context. + * @param {Store} [props.store] - An optional store instance. If not provided, a new SessionStore will be created. + * @param {Branding} props.branding - The branding object for the Asgardeo context. + * + * @returns {ReactElement} A React element that provides the Asgardeo context to all its children. + */ const AsgardeoProvider: FC> = ( props: PropsWithChildren, ) => { diff --git a/packages/react/src/providers/BrandingPreferenceProvider.tsx b/packages/react/src/providers/BrandingPreferenceProvider.tsx index bc0a39f8..845928e1 100644 --- a/packages/react/src/providers/BrandingPreferenceProvider.tsx +++ b/packages/react/src/providers/BrandingPreferenceProvider.tsx @@ -23,6 +23,17 @@ import BrandingPreferenceContext from '../contexts/branding-preference-context'; import BrandingPreferenceProviderProps from '../models/branding-preference-provider-props'; import generateTheme from '../theme/generate-theme'; +/** + * `BrandingPreferenceProvider` is a component that provides a branding context to all its children. + * It takes an object of type `BrandingPreferenceProviderProps` as props, which includes the children to render, + * and a branding object. + * + * @param {PropsWithChildren} props - The properties passed to the component. + * @param {ReactNode} props.children - The children to render inside the provider. + * @param {Branding} props.branding - The branding object for the context. + * + * @returns {ReactElement} A React element that provides the branding context to all its children. + */ const BrandingPreferenceProvider: FC> = ( props: PropsWithChildren, ) => { diff --git a/packages/react/src/providers/I18nProvider.tsx b/packages/react/src/providers/I18nProvider.tsx index f6d3ace4..0d7f7905 100644 --- a/packages/react/src/providers/I18nProvider.tsx +++ b/packages/react/src/providers/I18nProvider.tsx @@ -16,21 +16,37 @@ * under the License. */ -import {BrandingPreferenceTextProps, TextObject, getLocalization} from '@asgardeo/js-ui-core'; +import {TextObject, getLocalization} from '@asgardeo/js-ui-core'; import {FC, PropsWithChildren, useCallback, useMemo, useState} from 'react'; import I18nContext from '../contexts/i18n-context'; -import {I18n, I18nLocalization, SetTranslationsProps} from '../models/i18n'; - -interface I18nProviderProps { - providerLocaleOverride?: string; - providerTextOverrides?: BrandingPreferenceTextProps; -} +import {I18n, I18nLocalization, I18nProviderProps, SetTranslationsProps} from '../models/i18n'; +/** + * `I18nProvider` is a component that provides an internationalization context to all its children. + * It takes an object of type `I18nProviderProps` as props, which includes the children to render, + * a locale override, and text overrides. + * + * @param {PropsWithChildren} props - The properties passed to the component. + * @param {ReactNode} props.children - The children to render inside the provider. + * @param {string} [props.providerLocaleOverride] - Optional locale override. + * @param {TextObject} [props.providerTextOverrides] - Optional text overrides. + * + * @returns {ReactElement} A React element that provides the internationalization context to all its children. + */ const I18nProvider: FC> = (props: PropsWithChildren) => { const {children, providerLocaleOverride, providerTextOverrides} = props; const [text, setText] = useState({}); + /** + * `setTranslations` is a function that fetches and sets the translations for a specific screen. + * It takes an object of type `SetTranslationsProps` as an argument, which includes the screen type, + * and optional locale and text overrides. + * + * @param {SetTranslationsProps} setTranslationProps - The properties used to fetch and set the translations. + * + * @returns {Promise} A promise that resolves to `true` when the translations have been set. + */ const setTranslations: (setTranslationProps: SetTranslationsProps) => Promise = useCallback( async (setTranslationProps: SetTranslationsProps): Promise => { const {componentLocaleOverride, componentTextOverrides, screen} = setTranslationProps; diff --git a/packages/react/src/theme/generate-theme.ts b/packages/react/src/theme/generate-theme.ts index c03c1d5d..5f2cee55 100644 --- a/packages/react/src/theme/generate-theme.ts +++ b/packages/react/src/theme/generate-theme.ts @@ -19,6 +19,15 @@ import {BrandingPreferenceTheme, ThemeConfig} from '@asgardeo/js-ui-core'; import {extendTheme, Theme} from '@oxygen-ui/react'; +/** + * `generateTheme` is a function that generates a theme based on the provided branding preferences. + * It takes an object of type `BrandingPreferenceTheme` as an argument, which includes the active + * theme and configurations for different themes. + * + * @param {BrandingPreferenceTheme} brandingPreferenceTheme - The branding preferences used to generate the theme. + * + * @returns {Theme} A theme object that can be used with the `extendTheme` function from `@oxygen-ui/react`. + */ const generateTheme: (brandingPreferenceTheme: BrandingPreferenceTheme) => Theme = ( brandingPreferenceTheme: BrandingPreferenceTheme, ) => {