refactor(experience): experience api migration (#6407)
* refactor(experience): migrate the password register and sign-in migrate the password register and sign-in flow * fix(experience): update some namings update some namings * refactor(experience): refactor the verification code flow (migration-2) (#6408) * refactor(experience): refactor the verificaiton code flow refactor the verification code flow * refactor(experience): migrate the social and sso flow (migration-3) (#6406) * refactor(experience): migrate the social and sso flow migrate the social and sso flow * refactor(experience): migrate profile fulfillment flow (migration-4) (#6414) * refactor(experience): migrate profile fulfillment flow migrate the profile fulfillment flow * refactor(experience): remove unused hook remove unused hook * fix(experience): fix password policy checker fix password policy checker error display * fix(experience): fix the api name fix the api name * refactor(experience): migrate mfa flow (migration-5) (#6417) * refactor(experience): migrate mfa binding flow migrate mfa binding flow * test(experience): update unit tests (migration-6) (#6420) * test(experience): update unit tests update unit tests * chore(experience): remove legacy APIs remove legacy APIs * refactor(experience): revert api prefix revert api prefix * fix(experience): update the sso connectors endpoint update the sso connectors endpoint * chore: add changeset add changeset * fix(experience): comments fix comments fix * refactor(experience): refactor the code verificatin api refactor the code verification api * refactor(experience): code refactor refactor some implementation logic * feat(experience, core): add experience legacy package (#6527) add experience legacy package
12
.changeset/fresh-shrimps-rhyme.md
Normal file
|
@ -0,0 +1,12 @@
|
|||
---
|
||||
"@logto/experience": minor
|
||||
---
|
||||
|
||||
migrate experience app using Experience API.
|
||||
|
||||
Migrate experience app API requests from legacy [Interaction API](https://openapi.logto.io/group/endpoint-interaction) to the new [Experience API](https://openapi.logto.io/group/endpoint-experience), except the following endpoints:
|
||||
|
||||
- `GET /api/interaction/consent`
|
||||
- `POST /api/interaction/consent`
|
||||
|
||||
Those endpoints are used in the third-party application's consent page only. Remain unchanged.
|
|
@ -10,7 +10,7 @@
|
|||
"prepack": "pnpm -r prepack",
|
||||
"dev": "pnpm -r prepack && pnpm start:dev",
|
||||
"dev:cloud": "IS_CLOUD=1 CONSOLE_PUBLIC_URL=/ pnpm dev",
|
||||
"start:dev": "pnpm -r --parallel --filter=!@logto/integration-tests --filter \"!./packages/connectors/connector-*\" dev",
|
||||
"start:dev": "pnpm -r --parallel --filter=!@logto/integration-tests --filter=!@logto/experience-legacy --filter \"!./packages/connectors/connector-*\" dev",
|
||||
"start": "cd packages/core && NODE_ENV=production node .",
|
||||
"cli": "logto",
|
||||
"translate": "logto-translate",
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
"@logto/core-kit": "workspace:^2.5.0",
|
||||
"@logto/demo-app": "workspace:*",
|
||||
"@logto/experience": "workspace:*",
|
||||
"@logto/experience-legacy": "workspace:*",
|
||||
"@logto/language-kit": "workspace:^1.1.0",
|
||||
"@logto/phrases": "workspace:^1.13.0",
|
||||
"@logto/phrases-experience": "workspace:^1.7.0",
|
||||
|
|
|
@ -22,7 +22,7 @@ type Properties = {
|
|||
|
||||
export default function koaSpaProxy<StateT, ContextT extends IRouterParamContext, ResponseBodyT>({
|
||||
mountedApps,
|
||||
packagePath = 'experience',
|
||||
packagePath = EnvSet.values.isDevFeaturesEnabled ? 'experience' : 'experience-legacy',
|
||||
port = 5001,
|
||||
prefix = '',
|
||||
queries,
|
||||
|
|
22
packages/experience-legacy/.eslintrc.cjs
Normal file
|
@ -0,0 +1,22 @@
|
|||
/** @type {import('eslint').Linter.Config} */
|
||||
module.exports = {
|
||||
extends: '@silverhand/react',
|
||||
rules: {
|
||||
'jsx-a11y/no-autofocus': 'off',
|
||||
'unicorn/prefer-string-replace-all': 'off',
|
||||
},
|
||||
overrides: [
|
||||
{
|
||||
files: ['*.config.js', '*.config.ts', '*.d.ts'],
|
||||
rules: {
|
||||
'import/no-unused-modules': 'off',
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ['*.d.ts'],
|
||||
rules: {
|
||||
'import/no-unassigned-import': 'off',
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
727
packages/experience-legacy/CHANGELOG.md
Normal file
|
@ -0,0 +1,727 @@
|
|||
# Change Log
|
||||
|
||||
## 1.8.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- 3a839f6d6: support organization logo and sign-in experience override
|
||||
|
||||
Now it's able to set light and dark logos for organizations. You can upload the logos in the organization settings page.
|
||||
|
||||
Also, it's possible to override the sign-in experience logo from an organization. Simply add the `organization_id` parameter to the authentication request. In most Logto SDKs, it can be done by using the `extraParams` field in the `signIn` method.
|
||||
|
||||
For example, in the JavaScript SDK:
|
||||
|
||||
```ts
|
||||
import LogtoClient from "@logto/client";
|
||||
|
||||
const logtoClient = new LogtoClient(/* your configuration */);
|
||||
|
||||
logtoClient.signIn({
|
||||
redirectUri: "https://your-app.com/callback",
|
||||
extraParams: {
|
||||
organization_id: "<organization-id>",
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
The value `<organization-id>` can be found in the organization settings page.
|
||||
|
||||
If you could not find the `extraParams` field in the SDK you are using, please let us know.
|
||||
|
||||
- 62f5e5e0c: support app-level branding
|
||||
|
||||
You can now set logos, favicons, and colors for your app. These settings will be used in the sign-in experience when the app initiates the authentication flow. For apps that have no branding settings, the omni sign-in experience branding will be used.
|
||||
|
||||
If `organization_id` is provided in the authentication request, the app-level branding settings will be overridden by the organization's branding settings, if available.
|
||||
|
||||
- d203c8d2f: support experience data server-side rendering
|
||||
|
||||
Logto now injects the sign-in experience settings and phrases into the `index.html` file for better first-screen performance. The experience app will still fetch the settings and phrases from the server if:
|
||||
|
||||
- The server didn't inject the settings and phrases.
|
||||
- The parameters in the URL are different from server-rendered data.
|
||||
|
||||
- 3bf756f2b: use Vite for transpilation and bundling
|
||||
|
||||
Removed ParcelJS and replaced with Vite. No breaking changes should be expected, but use a minor version bump to catch your attention.
|
||||
|
||||
> [!Important]
|
||||
> The browserlist configuration for `@logto/experience` and been synced with what is stated in README.md.
|
||||
|
||||
- 62f5e5e0c: support dark favicon
|
||||
|
||||
The favicon for the dark theme now can be set in the sign-in experience branding settings.
|
||||
|
||||
## 1.7.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- 061a30a87: support agree to terms polices for Logto’s sign-in experiences
|
||||
|
||||
- Automatic: Users automatically agree to terms by continuing to use the service
|
||||
- ManualRegistrationOnly: Users must agree to terms by checking a box during registration, and don't need to agree when signing in
|
||||
- Manual: Users must agree to terms by checking a box during registration or signing in
|
||||
|
||||
- 50c35a214: support Google One Tap
|
||||
|
||||
- Conditionally load Google One Tap script if it's enabled in the config.
|
||||
- Support callback from Google One Tap.
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 136320584: allow skipping manual account linking during sign-in
|
||||
|
||||
You can find this configuration in Console -> Sign-in experience -> Sign-up and sign-in -> Social sign-in -> Automatic account linking.
|
||||
|
||||
When switched on, if a user signs in with a social identity that is new to the system, and there is exactly one existing account with the same identifier (e.g., email), Logto will automatically link the account with the social identity instead of prompting the user for account linking.
|
||||
|
||||
## 1.6.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- cb1a38c40: show global loading icon on page relocate
|
||||
|
||||
This is to address the issue where the user is redirected back to the client after a successful login, but the page is not yet fully loaded. This will show a global loading icon to indicate that the page is still loading. Preventing the user from interacting with the current sign-in page and avoid page idling confusion.
|
||||
|
||||
## 1.6.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- b80934ac5: fix native social sign-in callback
|
||||
|
||||
In a native environment, the social sign-in callback that posts to the native container (e.g. WKWebView in iOS) was wrong.
|
||||
|
||||
This was introduced by a refactor in #5536: It updated the callback path from `/sign-in/social/:connectorId` to `/callback/social/:connectorId`. However, the function to post the message to the native container was not updated accordingly.
|
||||
|
||||
- bbd399e15: fix the new user from SSO register hook event not triggering bug
|
||||
|
||||
### Issue
|
||||
|
||||
When a new user registers via SSO, the `PostRegister` interaction hook event is not triggered. `PostSignIn` event is mistakenly triggered instead.
|
||||
|
||||
### Root Cause
|
||||
|
||||
In the SSO `post /api/interaction/sso/:connectionId/registration` API, we update the interaction event to `Register`.
|
||||
However, the hook middleware reads the event from interaction session ahead of the API logic, and the event is not updated resulting in the wrong event being triggered.
|
||||
|
||||
In the current interaction API design, we should mutate the interaction event by calling the `PUT /api/interaction/event` API, instead of updating the event directly in the submit interaction APIs. (Just like the no direct mutation rule for a react state). So we can ensure the correct side effect like logs and hooks are triggered properly.
|
||||
|
||||
All the other sign-in methods are using the `PUT /api/interaction/event` API to update the event. But when implementing the SSO registration API, we were trying to reduce the API requests and directly updated the event in the registration API which will submit the interaction directly.
|
||||
|
||||
### Solution
|
||||
|
||||
Remove the event update logic in the SSO registration API and call the `PUT /api/interaction/event` API to update the event.
|
||||
This will ensure the correct event is triggered in the hook middleware.
|
||||
|
||||
### Action Items
|
||||
|
||||
Align the current interaction API design for now.
|
||||
Need to improve the session/interaction API logic to simplify the whole process.
|
||||
|
||||
## 1.6.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- 7756f50f8: support direct sign-in for sso
|
||||
- 2cbc591ff: support direct sign-in
|
||||
|
||||
Instead of showing a screen for the user to choose between the sign-in methods, a specific sign-in method can be initiated directly by setting the `direct_sign_in` parameter in the OIDC authentication request.
|
||||
|
||||
This parameter follows the format of `direct_sign_in=<method>:<target>`, where:
|
||||
|
||||
- `<method>` is the sign-in method to trigger. Currently the only supported value is `social`.
|
||||
- `<target>` is the target value for the sign-in method. If the method is `social`, the value is the social connector's `target`.
|
||||
|
||||
When a valid `direct_sign_in` parameter is set, the first screen will be skipped and the specified sign-in method will be triggered immediately upon entering the sign-in experience. If the parameter is invalid, the default behavior of showing the first screen will be used.
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 5a7204571: skip non-object messages in the native environment
|
||||
|
||||
In the `WKWebView` of new iOS versions, some script will constantly post messages to the
|
||||
window object with increasing numbers as the message content ("1", "2", "3", ...).
|
||||
|
||||
Ideally, we should check the source of the message with Logto-specific identifier in the
|
||||
`event.data`; however, this change will result a breaking change for the existing
|
||||
native SDK implementations. Add the `isObject` check to prevent the crazy messages while
|
||||
keeping the backward compatibility.
|
||||
|
||||
## 1.5.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- 32df9acde: update user consent page to support the new third-party application feature
|
||||
|
||||
- Only show the user consent page if current application is a third-party application, otherwise auto-consent the requested scopes.
|
||||
- Add the new fetching API to get the user consent context. Including the application detail, authenticated user info, all the requested scopes and user organizations info (if requested scopes include the organization scope).
|
||||
- Add the new user consent interaction API and authorize button. User have to manually authorize the requested scopes for the third-party application before continue the authentication flow.
|
||||
|
||||
- 31e60811d: use Node 20 LTS for engine requirement.
|
||||
|
||||
Note: We mark it as minor because Logto is shipping with Docker image and it's not a breaking change for users.
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 9089dbf84: upgrade TypeScript to 5.3.3
|
||||
|
||||
## 1.4.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- 9a7b19e49: Implement the new single sign-on (SSO) interaction flow
|
||||
|
||||
- `/single-sign-on/email` - The SSO email form page for user to enter their email address.
|
||||
- `/single-sign-on/connectors` - The SSO connectors page for user to select the enabled SSO connector they want to use.
|
||||
- Implement the email identifier guard on all the sign-in and registration identifier forms. If the email address is enabled with SSO, redirect user to the SSO flow.
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 9421375d7: Bump libphonenumber-js to v1.10.51 to support China 19 started phone numbers. Thanks to @agileago
|
||||
|
||||
## 1.3.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- 6727f629d: feature: introduce multi-factor authentication
|
||||
|
||||
We're excited to announce that Logto now supports multi-factor authentication (MFA) for your sign-in experience. Navigate to the "Multi-factor auth" tab to configure how you want to secure your users' accounts.
|
||||
|
||||
In this release, we introduce the following MFA methods:
|
||||
|
||||
- Authenticator app OTP: users can add any authenticator app that supports the TOTP standard, such as Google Authenticator, Duo, etc.
|
||||
- WebAuthn (Passkey): users can use the standard WebAuthn protocol to register a hardware security key, such as biometric keys, Yubikey, etc.
|
||||
- Backup codes:users can generate a set of backup codes to use when they don't have access to other MFA methods.
|
||||
|
||||
For a smooth transition, we also support to configure the MFA policy to require MFA for sign-in experience, or to allow users to opt-in to MFA.
|
||||
|
||||
## 1.2.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 6f5a0acad: fix a bug that prevents user from customizing i18n translations in Sign-in Experience config
|
||||
|
||||
## 1.2.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- e8b0b1d02: feature: password policy
|
||||
|
||||
### Summary
|
||||
|
||||
This feature enables custom password policy for users. Now it is possible to guard with the following rules when a user is creating a new password:
|
||||
|
||||
- Minimum length (default: `8`)
|
||||
- Minimum character types (default: `1`)
|
||||
- If the password has been pwned (default: `true`)
|
||||
- If the password is exactly the same as or made up of the restricted phrases:
|
||||
- Repetitive or sequential characters (default: `true`)
|
||||
- User information (default: `true`)
|
||||
- Custom words (default: `[]`)
|
||||
|
||||
If you are an existing Logto Cloud user or upgrading from a previous version, to ensure a smooth experience, we'll keep the original policy as much as possible:
|
||||
|
||||
> The original password policy requires a minimum length of 8 and at least 2 character types (letters, numbers, and symbols).
|
||||
|
||||
Note in the new policy implementation, it is not possible to combine lower and upper case letters into one character type. So the original password policy will be translated into the following:
|
||||
|
||||
- Minimum length: `8`
|
||||
- Minimum character types: `2`
|
||||
- Pwned: `false`
|
||||
- Repetitive or sequential characters: `false`
|
||||
- User information: `false`
|
||||
- Custom words: `[]`
|
||||
|
||||
If you want to change the policy, you can do it:
|
||||
|
||||
- Logto Console -> Sign-in experience -> Password policy.
|
||||
- Update `passwordPolicy` property in the sign-in experience via Management API.
|
||||
|
||||
### Side effects
|
||||
|
||||
- All new users will be affected by the new policy immediately.
|
||||
- Existing users will not be affected by the new policy until they change their password.
|
||||
- We removed password restrictions when adding or updating a user via Management API.
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- f8408fa77: rename the package `phrases-ui` to `phrases-experience`
|
||||
- f6723d5e2: rename the package `ui` to `experience`
|
||||
|
||||
## 1.1.5
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- c743cef42: Bug fix main flow preview mode should not allow user interaction.
|
||||
|
||||
- Recover the missing preview classname from the preview mode body element
|
||||
|
||||
## 1.1.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 046a5771b: upgrade i18next series packages (#3733, #3743)
|
||||
|
||||
## 1.1.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 748878ce5: add React context and hook to app-insights, fix init issue for frontend projects
|
||||
|
||||
## 1.1.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 352807b16: support setting cloud role name for AppInsights in React
|
||||
|
||||
## 1.1.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 4945b0be2: Apply security headers
|
||||
|
||||
Apply security headers to logto http request response using (helmetjs)[https://helmetjs.github.io/].
|
||||
|
||||
- [x] crossOriginOpenerPolicy
|
||||
- [x] crossOriginEmbedderPolicy
|
||||
- [x] crossOriginResourcePolicy
|
||||
- [x] hidePoweredBy
|
||||
- [x] hsts
|
||||
- [x] ieNoOpen
|
||||
- [x] noSniff
|
||||
- [x] referrerPolicy
|
||||
- [x] xssFilter
|
||||
- [x] Content-Security-Policy
|
||||
|
||||
## 1.1.0
|
||||
|
||||
## 1.0.3
|
||||
|
||||
## 1.0.2
|
||||
|
||||
## 1.0.1
|
||||
|
||||
## 1.0.0
|
||||
|
||||
### Major Changes
|
||||
|
||||
- 1c9160112: ### Features
|
||||
|
||||
- Enhanced user search params #2639
|
||||
- Web hooks
|
||||
|
||||
### Improvements
|
||||
|
||||
- Refactored Interaction APIs and Audit logs
|
||||
|
||||
- 343b1090f: **💥 BREAKING CHANGE 💥** Move `/api/phrase` API to `/api/.well-known/phrases`
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- 343b1090f: ### Simplify the terms of use and privacy policy manual agreement steps for the sign-in flow
|
||||
|
||||
The Terms of Use and Privacy Policy manuel agreement are now removed from the sign-in flow.
|
||||
|
||||
- The changes may take effect on all the existing sign-in flows, including password sign-in, social sign-in, and verification-code sign-in.
|
||||
- The agreement checkbox in sign-in pages is now replaced with links to the Terms of Use and Privacy Policy pages. Users can still read the agreements before signing in.
|
||||
- The manual agreement steps are still mandatory for the sign-up flow. Users must agree to the Terms of Use and Privacy Policy before signing up a new account. Including sign-up with new social identities. The agreement checkbox in sign-up pages remain still.
|
||||
|
||||
- f41fd3f05: Replace `passcode` naming convention in the interaction APIs and main flow ui with `verificationCode`.
|
||||
- 343b1090f: ### Update the password policy
|
||||
|
||||
Password policy description: Password requires a minimum of 8 characters and contains a mix of letters, numbers, and symbols.
|
||||
|
||||
- min-length updates: Password requires a minimum of 8 characters
|
||||
- allowed characters updates: Password contains a mix of letters, numbers, and symbols
|
||||
- digits: 0-9
|
||||
- letters: a-z, A-Z
|
||||
- symbols: !"#$%&'()\*+,./:;<=>?@[\]^\_`{|}~-
|
||||
- At least two types of characters are required:
|
||||
- letters and digits
|
||||
- letters and symbols
|
||||
- digits and symbols
|
||||
|
||||
> notice: The new password policy is applied to new users or new passwords only. Existing users are not affected by this change, users may still use their old password to sign-in.
|
||||
|
||||
- 343b1090f: ### Add dynamic favicon and html title
|
||||
|
||||
- Add the favicon field in the sign-in-experience branding settings. Users would be able to upload their own favicon. Use local logto icon as a fallback
|
||||
|
||||
- Set different html title for different pages.
|
||||
- sign-in
|
||||
- register
|
||||
- forgot-password
|
||||
- logto
|
||||
|
||||
- 343b1090f: Allow admin tenant admin to create tenants without limitation
|
||||
- 343b1090f: ## Add iframe modal for mobile platform
|
||||
|
||||
Implement a full screen iframe modal on the mobile platform. As for most of the webview containers, opening a new tab is not allowed. So we need to implement a full screen iframe modal to show the external link page on the mobile platform.
|
||||
|
||||
- 343b1090f: New feature: User account settings page
|
||||
|
||||
- We have removed the previous settings page and moved it to the account settings page. You can access to the new settings menu by clicking the user avatar in the top right corner.
|
||||
- You can directly change the language or theme from the popover menu, and explore more account settings by clicking the "Profile" menu item.
|
||||
- You can update your avatar, name and username in the profile page, and also changing your password.
|
||||
- [Cloud] Cloud users can also link their email address and social accounts (Google and GitHub at first launch).
|
||||
|
||||
- c12717412: ## Smart Identifier Input designed to streamline your sign-in experience
|
||||
|
||||
- Smart Contact Input
|
||||
- Smart Identifier Input
|
||||
- Intelligent Identifier Input Field
|
||||
|
||||
Content:
|
||||
We have integrated the traditional input fields for username, phone number, and email into a single intelligent input box. This advanced input box automatically identifies the type of characters you’re entering, such as an @ sign or consecutive numbers, and provides relevant error feedback. By streamlining the sign-in process, users no longer need to waste time figuring out which button to click to switch their desired login method. This reduces the risk of errors and ensures a smoother sign-in experience.
|
||||
|
||||
- 343b1090f: Implement a country code selector dropdown component with search box. Users may able to quick search for a country code by typing in the search box.
|
||||
- 343b1090f: remove the branding style config and make the logo URL config optional
|
||||
- c12717412: **Customize CSS for Sign-in Experience**
|
||||
|
||||
We have put a lot of effort into improving the user sign-in experience and have provided a brand color option for the UI. However, we know that fine-tuning UI requirements can be unpredictable. While Logto is still exploring the best options for customization, we want to provide a programmatic method to unblock your development.
|
||||
|
||||
You can now use the Management API `PATCH /api/sign-in-exp` with body `{ "customCss": "arbitrary string" }` to set customized CSS for the sign-in experience. You should see the value of `customCss` attached after `<title>` of the page. If the style has a higher priority, it should be able to override.
|
||||
|
||||
> **Note**
|
||||
>
|
||||
> Since Logto uses CSS Modules, you may see a hash value in the `class` property of DOM elements (e.g. a `<div>` with `vUugRG_container`). To override these, you can use the `$=` CSS selector to match elements that end with a specified value. In this case, it should be `div[class$=container]`.
|
||||
|
||||
- 343b1090f: Add custom CSS code editor so that users can apply advanced UI customization.
|
||||
- Users can check the real time preview of the CSS via SIE preview on the right side.
|
||||
- 2168936b9: **Sign-in Experience v2**
|
||||
|
||||
We are thrilled to announce the release of the newest version of the Sign-in Experience, which includes more ways to sign-in and sign-up, as well as a framework that is easier to understand and more flexible to configure in the Admin Console.
|
||||
|
||||
When compared to Sign-in Experience v1, this version’s capability was expanded so that it could support a greater variety of flexible use cases. For example, now users can sign up with email verification code and sign in with email and password.
|
||||
|
||||
We hope that this will be able to assist developers in delivering a successful sign-in flow, which will also be appreciated by the end users.
|
||||
|
||||
- 343b1090f: ### Add custom content sign-in-experience settings to allow insert custom static html content to the logto sign-in pages
|
||||
|
||||
- feat: combine with the custom css, give the user the ability to further customize the sign-in pages
|
||||
|
||||
- fdb2bb48e: **Streamlining the social sign-up flow**
|
||||
|
||||
- detect trusted email (or phone number) from the social account
|
||||
- email (or phone number) has been registered: automatically connecting the social identity to the existing user account with a single click
|
||||
- email (or phone number) not registered: automatically sync up the user profile with the social provided email (or phone) if and only if marked as a required user profile.
|
||||
|
||||
- f41fd3f05: Replace the `sms` naming convention using `phone` cross logto codebase. Including Sign-in Experience types, API paths, API payload and internal variable names.
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 51f527b0c: bug fixes
|
||||
|
||||
- core: fix 500 error when enabling app admin access in console
|
||||
- ui: handle required profile errors on social binding flow
|
||||
|
||||
- 343b1090f: ## Implement a lite version of set password form.
|
||||
|
||||
To simplify the effort when user set new password, we implement a lite version of set password form.
|
||||
|
||||
The lite version of set password form only contains only one field password. It will be used if and only if the forgot-password feature is enabled (password can be reset either by email and phone).
|
||||
|
||||
If you do not have any email or sms service enabled, we still use the old version of set password form which contains two fields: password and confirm password.
|
||||
|
||||
- 38970fb88: Fix a Sign-in experience bug that may block some users to sign in.
|
||||
- 02cc9abd8: Fix a bug to show forgot password when only SMS connector is configured
|
||||
- 343b1090f: - Add Power By Logto Signature to the main-flow pages
|
||||
|
||||
## 1.0.0-rc.3
|
||||
|
||||
## 1.0.0-rc.2
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- c12717412: ## Smart Identifier Input designed to streamline your sign-in experience
|
||||
|
||||
- Smart Contact Input
|
||||
- Smart Identifier Input
|
||||
- Intelligent Identifier Input Field
|
||||
|
||||
Content:
|
||||
We have integrated the traditional input fields for username, phone number, and email into a single intelligent input box. This advanced input box automatically identifies the type of characters you’re entering, such as an @ sign or consecutive numbers, and provides relevant error feedback. By streamlining the sign-in process, users no longer need to waste time figuring out which button to click to switch their desired login method. This reduces the risk of errors and ensures a smoother sign-in experience.
|
||||
|
||||
- c12717412: **Customize CSS for Sign-in Experience**
|
||||
|
||||
We have put a lot of effort into improving the user sign-in experience and have provided a brand color option for the UI. However, we know that fine-tuning UI requirements can be unpredictable. While Logto is still exploring the best options for customization, we want to provide a programmatic method to unblock your development.
|
||||
|
||||
You can now use the Management API `PATCH /api/sign-in-exp` with body `{ "customCss": "arbitrary string" }` to set customized CSS for the sign-in experience. You should see the value of `customCss` attached after `<title>` of the page. If the style has a higher priority, it should be able to override.
|
||||
|
||||
> **Note**
|
||||
>
|
||||
> Since Logto uses CSS Modules, you may see a hash value in the `class` property of DOM elements (e.g. a `<div>` with `vUugRG_container`). To override these, you can use the `$=` CSS selector to match elements that end with a specified value. In this case, it should be `div[class$=container]`.
|
||||
|
||||
## 1.0.0-rc.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 51f527b0: bug fixes
|
||||
|
||||
- core: fix 500 error when enabling app admin access in console
|
||||
- ui: handle required profile errors on social binding flow
|
||||
|
||||
## 1.0.0-rc.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- f41fd3f0: Replace `passcode` naming convention in the interaction APIs and main flow ui with `verificationCode`.
|
||||
- fdb2bb48: **Streamlining the social sign-up flow**
|
||||
|
||||
- detect trusted email (or phone number) from the social account
|
||||
- email (or phone number) has been registered: automatically connecting the social identity to the existing user account with a single click
|
||||
- email (or phone number) not registered: automatically sync up the user profile with the social provided email (or phone) if and only if marked as a required user profile.
|
||||
|
||||
- f41fd3f0: Replace the `sms` naming convention using `phone` cross logto codebase. Including Sign-in Experience types, API paths, API payload and internal variable names.
|
||||
|
||||
## 1.0.0-beta.19
|
||||
|
||||
## 1.0.0-beta.18
|
||||
|
||||
### Major Changes
|
||||
|
||||
- 1c916011: ### Features
|
||||
|
||||
- Enhanced user search params #2639
|
||||
- Web hooks
|
||||
|
||||
### Improvements
|
||||
|
||||
- Refactored Interaction APIs and Audit logs
|
||||
|
||||
## 1.0.0-beta.17
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 02cc9abd: Fix a bug to show forgot password when only SMS connector is configured
|
||||
|
||||
## 1.0.0-beta.16
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 38970fb8: Fix a Sign-in experience bug that may block some users to sign in.
|
||||
|
||||
## 1.0.0-beta.15
|
||||
|
||||
## 1.0.0-beta.14
|
||||
|
||||
## 1.0.0-beta.13
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- 2168936b: **Sign-in Experience v2**
|
||||
|
||||
We are thrilled to announce the release of the newest version of the Sign-in Experience, which includes more ways to sign-in and sign-up, as well as a framework that is easier to understand and more flexible to configure in the Admin Console.
|
||||
|
||||
When compared to Sign-in Experience v1, this version’s capability was expanded so that it could support a greater variety of flexible use cases. For example, now users can sign up with email verification code and sign in with email and password.
|
||||
|
||||
We hope that this will be able to assist developers in delivering a successful sign-in flow, which will also be appreciated by the end users.
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.0.0-beta.12](https://github.com/logto-io/logto/compare/v1.0.0-beta.11...v1.0.0-beta.12) (2022-10-19)
|
||||
|
||||
**Note:** Version bump only for package @logto/ui
|
||||
|
||||
## [1.0.0-beta.11](https://github.com/logto-io/logto/compare/v1.0.0-beta.10...v1.0.0-beta.11) (2022-10-19)
|
||||
|
||||
### Features
|
||||
|
||||
- **ui:** add a11y support ([#2076](https://github.com/logto-io/logto/issues/2076)) ([2249d71](https://github.com/logto-io/logto/commit/2249d717a8928597d00c383c268d6fdc506ac437))
|
||||
- **ui:** add reset password error handling flow ([#2079](https://github.com/logto-io/logto/issues/2079)) ([afa2ac4](https://github.com/logto-io/logto/commit/afa2ac47ee461e3526f61594e456d484fd3166af))
|
||||
- **ui:** global confirm modal ([#2018](https://github.com/logto-io/logto/issues/2018)) ([f1ca49c](https://github.com/logto-io/logto/commit/f1ca49c89253daef8b47ec88e30f69df818374d1))
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- **console:** remove connector id and prevent text overflow ([#2072](https://github.com/logto-io/logto/issues/2072)) ([05b5025](https://github.com/logto-io/logto/commit/05b50250a387635649614aaeeec9757e7034a19d))
|
||||
- **ui:** fix ut ([9ea6a8c](https://github.com/logto-io/logto/commit/9ea6a8c8e94e116d8efbbff63b39738162cbaec1))
|
||||
- **ui:** revert color token changes in ui as it uses different design system ([489e2b3](https://github.com/logto-io/logto/commit/489e2b3a1129fbbf824955e4697c1d64ff294d95))
|
||||
|
||||
## [1.0.0-beta.10](https://github.com/logto-io/logto/compare/v1.0.0-beta.9...v1.0.0-beta.10) (2022-09-28)
|
||||
|
||||
### Features
|
||||
|
||||
- **ui:** add forget password flow ([#1952](https://github.com/logto-io/logto/issues/1952)) ([ba787b4](https://github.com/logto-io/logto/commit/ba787b434ba4dd43064c56115eabfdba9912f98a))
|
||||
- **ui:** add forget password page ([#1943](https://github.com/logto-io/logto/issues/1943)) ([39d80d9](https://github.com/logto-io/logto/commit/39d80d991235c93346c26977541d3c7040379a13))
|
||||
- **ui:** add passwordless switch ([#1976](https://github.com/logto-io/logto/issues/1976)) ([ddb0e47](https://github.com/logto-io/logto/commit/ddb0e47950b3bd7f92af2a8a5e14b201e0a10ed7))
|
||||
- **ui:** add reset password form ([#1964](https://github.com/logto-io/logto/issues/1964)) ([f97ec56](https://github.com/logto-io/logto/commit/f97ec56fbf169538cff5f8f23ed8bb67e9483b27))
|
||||
- **ui:** add reset password page ([#1961](https://github.com/logto-io/logto/issues/1961)) ([ff81b0f](https://github.com/logto-io/logto/commit/ff81b0f83e86dd3686341d3612f3f5e8f075cba6))
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- bump react sdk and essentials toolkit to support CJK characters in idToken ([2f92b43](https://github.com/logto-io/logto/commit/2f92b438644bd330fa4b8cd3698d9129ecbae282))
|
||||
- **ui:** align mobile input outline ([#1991](https://github.com/logto-io/logto/issues/1991)) ([c9ba198](https://github.com/logto-io/logto/commit/c9ba198b59ae52d3c5b4520a98864519d7a756f7))
|
||||
|
||||
## [1.0.0-beta.9](https://github.com/logto-io/logto/compare/v1.0.0-beta.8...v1.0.0-beta.9) (2022-09-07)
|
||||
|
||||
### Features
|
||||
|
||||
- add Portuguese translation ([f268ecb](https://github.com/logto-io/logto/commit/f268ecb1a8d57d1e33225bec8852f3bc377dd478))
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- **console,ui:** fix locale guard issue in settings page ([e200578](https://github.com/logto-io/logto/commit/e2005780a39fa7b5f5c5e406f37805913b684c18))
|
||||
|
||||
## [1.0.0-beta.8](https://github.com/logto-io/logto/compare/v1.0.0-beta.6...v1.0.0-beta.8) (2022-09-01)
|
||||
|
||||
**Note:** Version bump only for package @logto/ui
|
||||
|
||||
## [1.0.0-beta.6](https://github.com/logto-io/logto/compare/v1.0.0-beta.5...v1.0.0-beta.6) (2022-08-30)
|
||||
|
||||
**Note:** Version bump only for package @logto/ui
|
||||
|
||||
## [1.0.0-beta.5](https://github.com/logto-io/logto/compare/v1.0.0-beta.4...v1.0.0-beta.5) (2022-08-19)
|
||||
|
||||
**Note:** Version bump only for package @logto/ui
|
||||
|
||||
## [1.0.0-beta.4](https://github.com/logto-io/logto/compare/v1.0.0-beta.3...v1.0.0-beta.4) (2022-08-11)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- build and types ([8b51543](https://github.com/logto-io/logto/commit/8b515435cdb0644d0ca19e2c26ba3e744355bb0b))
|
||||
- **ui,console,demo-app:** update react render method ([#1750](https://github.com/logto-io/logto/issues/1750)) ([4b972f2](https://github.com/logto-io/logto/commit/4b972f2e23e2d4609d9955c4d1d42972f368f5b9))
|
||||
- **ui:** add sandbox props to iframe ([#1757](https://github.com/logto-io/logto/issues/1757)) ([62d2afe](https://github.com/logto-io/logto/commit/62d2afe9579334547b7ff5b803299b89933a5bd8))
|
||||
- **ui:** connector name should fallback to en ([#1718](https://github.com/logto-io/logto/issues/1718)) ([3af5b1b](https://github.com/logto-io/logto/commit/3af5b1b4250d6de6883b4c8a8b9f7cf4f9b12dab))
|
||||
- **ui:** extract ReactModal elementApp and fix act warning in ut ([#1756](https://github.com/logto-io/logto/issues/1756)) ([0270bf1](https://github.com/logto-io/logto/commit/0270bf1be3a51d9b9f8ed84a0327c58ed8a1bd4d))
|
||||
- **ui:** fix ui test ([e4629f2](https://github.com/logto-io/logto/commit/e4629f2a5fd26a1d8eaefd04042eaeb5563ec30c))
|
||||
|
||||
## [1.0.0-beta.3](https://github.com/logto-io/logto/compare/v1.0.0-beta.2...v1.0.0-beta.3) (2022-08-01)
|
||||
|
||||
### Features
|
||||
|
||||
- **phrases:** tr language ([#1707](https://github.com/logto-io/logto/issues/1707)) ([411a8c2](https://github.com/logto-io/logto/commit/411a8c2fa2bfb16c4fef5f0a55c3c1dc5ead1124))
|
||||
|
||||
## [1.0.0-beta.2](https://github.com/logto-io/logto/compare/v1.0.0-beta.1...v1.0.0-beta.2) (2022-07-25)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- **ui:** fix some firefox standout bug ([#1615](https://github.com/logto-io/logto/issues/1615)) ([4ce6bd8](https://github.com/logto-io/logto/commit/4ce6bd8cf5c5953d9f62878ab2ea6ede74f6ca48))
|
||||
- **ui:** protect window.location xss ([#1639](https://github.com/logto-io/logto/issues/1639)) ([34b465c](https://github.com/logto-io/logto/commit/34b465c7d83999e2215ef83555b64e38778b8b49))
|
||||
- **ui:** should clear prev passcode input when click on backspace ([#1660](https://github.com/logto-io/logto/issues/1660)) ([7dfbc30](https://github.com/logto-io/logto/commit/7dfbc300b09cc3dac2a06176bf2cbc9f338d857e))
|
||||
|
||||
## [1.0.0-beta.1](https://github.com/logto-io/logto/compare/v1.0.0-beta.0...v1.0.0-beta.1) (2022-07-19)
|
||||
|
||||
### Features
|
||||
|
||||
- **ui:** add submit input to all the sign-in & register forms ([#1587](https://github.com/logto-io/logto/issues/1587)) ([0c0c83c](https://github.com/logto-io/logto/commit/0c0c83cc8f78f611f5a8527ecedd6ce21d1dad80))
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- **ui:** fix no-restrict-syntax in ui ([#1559](https://github.com/logto-io/logto/issues/1559)) ([816ce9f](https://github.com/logto-io/logto/commit/816ce9f903fc939b676165c5ad7e17c72f4c1c86))
|
||||
- **ui:** format phone number with country calling code ([#1551](https://github.com/logto-io/logto/issues/1551)) ([c6384be](https://github.com/logto-io/logto/commit/c6384bed84340909aaa41f10abaea26b5195e6a5))
|
||||
|
||||
## [1.0.0-beta.0](https://github.com/logto-io/logto/compare/v1.0.0-alpha.4...v1.0.0-beta.0) (2022-07-14)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- **ui,core:** fix i18n issue ([#1548](https://github.com/logto-io/logto/issues/1548)) ([6b58d8a](https://github.com/logto-io/logto/commit/6b58d8a1610b1b75155d873e8898786d2b723ec6))
|
||||
- **ui:** fix multiple libphonmenumber packed bug ([#1544](https://github.com/logto-io/logto/issues/1544)) ([e06f8d0](https://github.com/logto-io/logto/commit/e06f8d027eaea3ab89b4fd301be46af3508b61b5))
|
||||
|
||||
## [1.0.0-alpha.4](https://github.com/logto-io/logto/compare/v1.0.0-alpha.3...v1.0.0-alpha.4) (2022-07-08)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- **ui:** add form submit event ([#1489](https://github.com/logto-io/logto/issues/1489)) ([f52fa58](https://github.com/logto-io/logto/commit/f52fa5891d70bf9a50c76eb3efa35f6031dc88cb))
|
||||
|
||||
## [1.0.0-alpha.3](https://github.com/logto-io/logto/compare/v1.0.0-alpha.2...v1.0.0-alpha.3) (2022-07-07)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- **core,ui:** remove todo comments ([#1454](https://github.com/logto-io/logto/issues/1454)) ([d5d6c5e](https://github.com/logto-io/logto/commit/d5d6c5ed083364dabaa0220deaa6a22e0350d146))
|
||||
|
||||
## [1.0.0-alpha.2](https://github.com/logto-io/logto/compare/v1.0.0-alpha.1...v1.0.0-alpha.2) (2022-07-07)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- **ui:** dark mode seed ([#1426](https://github.com/logto-io/logto/issues/1426)) ([be73dbf](https://github.com/logto-io/logto/commit/be73dbf4ef14cf49779775dd95848ba73904a4b2))
|
||||
- **ui:** set ui specific i18n storage key ([#1441](https://github.com/logto-io/logto/issues/1441)) ([5b121d7](https://github.com/logto-io/logto/commit/5b121d78551d471125737daf31d4e0505e69e409))
|
||||
|
||||
## [1.0.0-alpha.1](https://github.com/logto-io/logto/compare/v1.0.0-alpha.0...v1.0.0-alpha.1) (2022-07-05)
|
||||
|
||||
**Note:** Version bump only for package @logto/ui
|
||||
|
||||
## [1.0.0-alpha.0](https://github.com/logto-io/logto/compare/v0.1.2-alpha.5...v1.0.0-alpha.0) (2022-07-04)
|
||||
|
||||
**Note:** Version bump only for package @logto/ui
|
||||
|
||||
### [0.1.2-alpha.5](https://github.com/logto-io/logto/compare/v0.1.2-alpha.4...v0.1.2-alpha.5) (2022-07-03)
|
||||
|
||||
**Note:** Version bump only for package @logto/ui
|
||||
|
||||
### [0.1.2-alpha.4](https://github.com/logto-io/logto/compare/v0.1.2-alpha.3...v0.1.2-alpha.4) (2022-07-03)
|
||||
|
||||
**Note:** Version bump only for package @logto/ui
|
||||
|
||||
### [0.1.2-alpha.3](https://github.com/logto-io/logto/compare/v0.1.2-alpha.2...v0.1.2-alpha.3) (2022-07-03)
|
||||
|
||||
**Note:** Version bump only for package @logto/ui
|
||||
|
||||
### [0.1.2-alpha.2](https://github.com/logto-io/logto/compare/v0.1.2-alpha.1...v0.1.2-alpha.2) (2022-07-02)
|
||||
|
||||
**Note:** Version bump only for package @logto/ui
|
||||
|
||||
### [0.1.2-alpha.1](https://github.com/logto-io/logto/compare/v0.1.2-alpha.0...v0.1.2-alpha.1) (2022-07-02)
|
||||
|
||||
**Note:** Version bump only for package @logto/ui
|
||||
|
||||
### [0.1.2-alpha.0](https://github.com/logto-io/logto/compare/v0.1.1-alpha.0...v0.1.2-alpha.0) (2022-07-02)
|
||||
|
||||
**Note:** Version bump only for package @logto/ui
|
||||
|
||||
### [0.1.1-alpha.0](https://github.com/logto-io/logto/compare/v0.1.0-internal...v0.1.1-alpha.0) (2022-07-01)
|
||||
|
||||
### Features
|
||||
|
||||
- **connector:** apple ([#966](https://github.com/logto-io/logto/issues/966)) ([7400ed8](https://github.com/logto-io/logto/commit/7400ed8896fdceda6165a0540413efb4e3a47438))
|
||||
- **console,ui:** generate dark mode color in console ([#1231](https://github.com/logto-io/logto/issues/1231)) ([f72b21d](https://github.com/logto-io/logto/commit/f72b21d1602ab0fb35ef3e7d84f6c8ebd7e18b08))
|
||||
- **console:** add 404 page in admin console ([0d047fb](https://github.com/logto-io/logto/commit/0d047fbaf115f005615b5df06170e526283d9335))
|
||||
- **console:** add mobile web tab in preview ([#1214](https://github.com/logto-io/logto/issues/1214)) ([9b6fd4c](https://github.com/logto-io/logto/commit/9b6fd4c417f2ee53375e436c839b711c86403d58))
|
||||
- **console:** sie form reorg ([#1218](https://github.com/logto-io/logto/issues/1218)) ([2c41334](https://github.com/logto-io/logto/commit/2c413341d1c515049faa130416f7a5e591d10e8a))
|
||||
- **core,connectors:** update Aliyun logo and add logo_dark to Apple, Github ([#1194](https://github.com/logto-io/logto/issues/1194)) ([98f8083](https://github.com/logto-io/logto/commit/98f808320b1c79c51f8bd6f49e35ca44363ea560))
|
||||
- **core,console:** social connector targets ([#851](https://github.com/logto-io/logto/issues/851)) ([127664a](https://github.com/logto-io/logto/commit/127664a62f1b1c794569b7fe9d0bfceb7b97dc74))
|
||||
- **core:** add sign-in-mode ([#1132](https://github.com/logto-io/logto/issues/1132)) ([f640dad](https://github.com/logto-io/logto/commit/f640dad52f2e75620b392114673860138e1aca2c))
|
||||
- **core:** add socialConnectors details for get sign-in-settings ([#804](https://github.com/logto-io/logto/issues/804)) ([7a922cb](https://github.com/logto-io/logto/commit/7a922cbd331b45443f7f19a8af3dcd9156453079))
|
||||
- **core:** update connector db schema ([#732](https://github.com/logto-io/logto/issues/732)) ([8e1533a](https://github.com/logto-io/logto/commit/8e1533a70267d459feea4e5174296b17bef84d48))
|
||||
- **demo-app:** show notification in main flow ([#1038](https://github.com/logto-io/logto/issues/1038)) ([90ca76e](https://github.com/logto-io/logto/commit/90ca76eeb5460b66d2241f137f179bf4d5d6ae37))
|
||||
- **ui:** add bind social account flow ([#671](https://github.com/logto-io/logto/issues/671)) ([5e251bd](https://github.com/logto-io/logto/commit/5e251bdc0818195d7eb104488bdb8a3194205bdd))
|
||||
- **ui:** add darkmode logo ([#880](https://github.com/logto-io/logto/issues/880)) ([9fa13a2](https://github.com/logto-io/logto/commit/9fa13a24ae2e1b3024b3ef2169736d27847f04eb))
|
||||
- **ui:** add global primary color settings ([#871](https://github.com/logto-io/logto/issues/871)) ([0f2827c](https://github.com/logto-io/logto/commit/0f2827ccb873bf30e44209da39803ac6cc839af2))
|
||||
- **ui:** add mobile terms of use iframe modal ([#947](https://github.com/logto-io/logto/issues/947)) ([4abcda6](https://github.com/logto-io/logto/commit/4abcda6820f0d824d110ee3ddd6d457433dfbf26))
|
||||
- **ui:** add native sdk guard logic ([#1096](https://github.com/logto-io/logto/issues/1096)) ([147775a](https://github.com/logto-io/logto/commit/147775a8f45dbb5bbf05b3bf1b7c11c0a8acf4a4))
|
||||
- **ui:** add Notification component ([#994](https://github.com/logto-io/logto/issues/994)) ([8530e24](https://github.com/logto-io/logto/commit/8530e249aa6d63efe594a08f800be4bfb43ed77e))
|
||||
- **ui:** add social dropdown list for desktop ([#834](https://github.com/logto-io/logto/issues/834)) ([36922b3](https://github.com/logto-io/logto/commit/36922b343f06daa1c7d4125bd0066ec06962123d))
|
||||
- **ui:** app notification ([#999](https://github.com/logto-io/logto/issues/999)) ([f4e380f](https://github.com/logto-io/logto/commit/f4e380f0b1b815314b24cec1c9013d9f3bb806a7))
|
||||
- **ui:** display error message on social callback page ([#1097](https://github.com/logto-io/logto/issues/1097)) ([f3b8678](https://github.com/logto-io/logto/commit/f3b8678a8c5e938276208c222242c3fedf4d397a))
|
||||
- **ui:** implement preview mode ([#852](https://github.com/logto-io/logto/issues/852)) ([ef19fb3](https://github.com/logto-io/logto/commit/ef19fb3d27a84509613b1f1d47819c06e9a6e9d1))
|
||||
- **ui:** init destop styling foundation ([#787](https://github.com/logto-io/logto/issues/787)) ([5c02ec3](https://github.com/logto-io/logto/commit/5c02ec3bdae162bd83d26c56f7ae34ee6e505ca2))
|
||||
- **ui:** not found page ([#691](https://github.com/logto-io/logto/issues/691)) ([731ff1c](https://github.com/logto-io/logto/commit/731ff1cbdca76104845dcf3d1223953ce8e5af93))
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- `lint:report` script ([#730](https://github.com/logto-io/logto/issues/730)) ([3b17324](https://github.com/logto-io/logto/commit/3b17324d189b2fe47985d0bee8b37b4ef1dbdd2b))
|
||||
- **console:** socialConnectors in preview data ([#862](https://github.com/logto-io/logto/issues/862)) ([a2cd983](https://github.com/logto-io/logto/commit/a2cd983d97097f86a07f988031b76665958ac24b))
|
||||
- revert "chore(deps): update parcel monorepo to v2.6.0" ([877bbc0](https://github.com/logto-io/logto/commit/877bbc0d2c5c0559a3fc9a8e801a13ebff2292a6))
|
||||
- **ui:** add body background color ([#831](https://github.com/logto-io/logto/issues/831)) ([be8b862](https://github.com/logto-io/logto/commit/be8b8628ba345bd8f8832b2123a43e70c236406d))
|
||||
- **ui:** add default success true for no response api ([#842](https://github.com/logto-io/logto/issues/842)) ([88600c0](https://github.com/logto-io/logto/commit/88600c012c892c969f1e5df7ec5f46874513a058))
|
||||
- **ui:** add i18n formater for zh-CN list ([#1009](https://github.com/logto-io/logto/issues/1009)) ([ca5c8aa](https://github.com/logto-io/logto/commit/ca5c8aaec1db7ffc330f50fcdc14400e06ad6f54))
|
||||
- **ui:** catch request exceptions with no response body ([#790](https://github.com/logto-io/logto/issues/790)) ([48de9c0](https://github.com/logto-io/logto/commit/48de9c072bb060f3e5aeb785d7a765a66a0912fe))
|
||||
- **ui:** fix callback link params for apple ([#985](https://github.com/logto-io/logto/issues/985)) ([362c3a6](https://github.com/logto-io/logto/commit/362c3a6e6ed3cab24a85f9e268509d31430609e4))
|
||||
- **ui:** fix ci fail ([#708](https://github.com/logto-io/logto/issues/708)) ([da49812](https://github.com/logto-io/logto/commit/da4981216452ee11cf91c8f52a1d50ef18f9a37f))
|
||||
- **UI:** fix connector target and id used in UI ([#838](https://github.com/logto-io/logto/issues/838)) ([cd46505](https://github.com/logto-io/logto/commit/cd4650508f9b1b4d2051e600afdf1e157dcf0631))
|
||||
- **ui:** fix count down bug ([#874](https://github.com/logto-io/logto/issues/874)) ([9c1e9ef](https://github.com/logto-io/logto/commit/9c1e9ef7edb39d5d15dcbb21a8789fab78326de5))
|
||||
- **ui:** fix create account page reload issue ([#832](https://github.com/logto-io/logto/issues/832)) ([e221758](https://github.com/logto-io/logto/commit/e2217584a40098d6bfcd6a745e8e0d982e8936c0))
|
||||
- **ui:** fix drawer overflow bug ([#984](https://github.com/logto-io/logto/issues/984)) ([b9131e9](https://github.com/logto-io/logto/commit/b9131e97659dece341ba4dd0cb47686a24698dcb))
|
||||
- **ui:** fix social bug ([#939](https://github.com/logto-io/logto/issues/939)) ([7a17d41](https://github.com/logto-io/logto/commit/7a17d41acf7cc068d0ec5568bcd842db51aa8b39))
|
||||
- **ui:** fix social native interaction bug ([#772](https://github.com/logto-io/logto/issues/772)) ([2161856](https://github.com/logto-io/logto/commit/2161856bcd33b66c8390b343cc3591ff284be286))
|
||||
- **ui:** fix some of the bug bash issues ([#1053](https://github.com/logto-io/logto/issues/1053)) ([db1b6d2](https://github.com/logto-io/logto/commit/db1b6d247a3d07f81ff1284b1fdbd3e7ffcc97aa))
|
||||
- **ui:** fix typo ([#792](https://github.com/logto-io/logto/issues/792)) ([13cd2c1](https://github.com/logto-io/logto/commit/13cd2c100ed32b40da72364d1f4685edd7d6d25a))
|
||||
- **ui:** fix ui i18n package error ([#713](https://github.com/logto-io/logto/issues/713)) ([34d798b](https://github.com/logto-io/logto/commit/34d798b645f16aff05b3818797b7914b5d2bc9b3))
|
||||
- **ui:** fix undefined dark-primary-color bug ([#876](https://github.com/logto-io/logto/issues/876)) ([542d878](https://github.com/logto-io/logto/commit/542d878231b98710af6e5a8ba6a5a5f74eee73a3))
|
||||
- **ui:** hide social signin method if connectors are empty ([#909](https://github.com/logto-io/logto/issues/909)) ([5e0c39e](https://github.com/logto-io/logto/commit/5e0c39e5166072c2c8d729c2e0f714507fd93ba6))
|
||||
- **ui:** input fields ([#1125](https://github.com/logto-io/logto/issues/1125)) ([20f7ad9](https://github.com/logto-io/logto/commit/20f7ad986353eb0026cbec417eaed3c334279f86))
|
||||
- **ui:** relocate svg jest config ([#856](https://github.com/logto-io/logto/issues/856)) ([d8c62c1](https://github.com/logto-io/logto/commit/d8c62c14a677d9afa8ce4b2c78cdd8fc8b1ee6c1))
|
||||
- **ui:** social bind account should back to sign-in page ([#952](https://github.com/logto-io/logto/issues/952)) ([da41369](https://github.com/logto-io/logto/commit/da41369bfd0e444190d33edef6527b32b538dbee))
|
||||
- **ui:** ui design review fix ([#697](https://github.com/logto-io/logto/issues/697)) ([15dd1a7](https://github.com/logto-io/logto/commit/15dd1a767e9eddfd37a80b47775afbe327b76d5b))
|
||||
- **ui:** ui refinement ([#855](https://github.com/logto-io/logto/issues/855)) ([1661c81](https://github.com/logto-io/logto/commit/1661c8121a9ed1620a4d8fefd51523d2be261089))
|
||||
- **ut:** fix ut ([#683](https://github.com/logto-io/logto/issues/683)) ([b0138bd](https://github.com/logto-io/logto/commit/b0138bdc0f2c43f40e20e83b621f3de3d068c171))
|
3
packages/experience-legacy/README.md
Normal file
|
@ -0,0 +1,3 @@
|
|||
# @logto/experience
|
||||
|
||||
The register and sign-in experience for end-users.
|
20
packages/experience-legacy/index.html
Normal file
|
@ -0,0 +1,20 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">
|
||||
<title></title>
|
||||
<script>
|
||||
/* See {@link packages/schemas/src/types/ssr.ts} */
|
||||
window.logtoSsr = "__LOGTO_SSR__";
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||
<div id="app"></div>
|
||||
<script type="module" src="src/index.tsx"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
35
packages/experience-legacy/jest.config.ts
Normal file
|
@ -0,0 +1,35 @@
|
|||
import type { Config } from '@jest/types';
|
||||
|
||||
const config: Config.InitialOptions = {
|
||||
roots: ['<rootDir>/src'],
|
||||
testEnvironment: 'jsdom',
|
||||
setupFilesAfterEnv: ['<rootDir>/src/jest.setup.ts'],
|
||||
collectCoverageFrom: ['**/*.{js,jsx,ts,tsx}'],
|
||||
coveragePathIgnorePatterns: ['/node_modules/', '/src/__mocks__/', '/src/include.d/'],
|
||||
coverageReporters: ['text-summary', 'lcov'],
|
||||
transform: {
|
||||
'^.+\\.(t|j)sx?$': [
|
||||
'@swc/jest',
|
||||
{
|
||||
sourceMaps: true,
|
||||
jsc: {
|
||||
transform: {
|
||||
react: {
|
||||
runtime: 'automatic',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
'\\.(svg)$': 'jest-transformer-svg',
|
||||
'\\.(png)$': 'jest-transform-stub',
|
||||
},
|
||||
moduleNameMapper: {
|
||||
'^@/([^?]*)(\\?.*)?$': '<rootDir>/src/$1',
|
||||
'^@logto/shared/(.*)$': '<rootDir>/../shared/lib/$1',
|
||||
'\\.module\\.(css|sass|scss)$': 'identity-obj-proxy',
|
||||
},
|
||||
transformIgnorePatterns: ['node_modules/(?!(.*(nanoid|jose|ky|@logto|@silverhand))/)'],
|
||||
};
|
||||
|
||||
export default config;
|
99
packages/experience-legacy/package.json
Normal file
|
@ -0,0 +1,99 @@
|
|||
{
|
||||
"name": "@logto/experience-legacy",
|
||||
"version": "1.8.0",
|
||||
"license": "MPL-2.0",
|
||||
"type": "module",
|
||||
"private": true,
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
"scripts": {
|
||||
"precommit": "lint-staged",
|
||||
"start": "vite",
|
||||
"dev": "vite",
|
||||
"check": "tsc --noEmit",
|
||||
"build": "vite build",
|
||||
"lint": "eslint --ext .ts --ext .tsx src",
|
||||
"lint:report": "pnpm lint --format json --output-file report.json",
|
||||
"stylelint": "stylelint \"src/**/*.scss\"",
|
||||
"test:ci": "jest --coverage --silent",
|
||||
"test": "jest"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@jest/types": "^29.5.0",
|
||||
"@logto/connector-kit": "workspace:^4.0.0",
|
||||
"@logto/core-kit": "workspace:^2.5.0",
|
||||
"@logto/language-kit": "workspace:^1.1.0",
|
||||
"@logto/phrases": "workspace:^1.13.0",
|
||||
"@logto/phrases-experience": "workspace:^1.7.0",
|
||||
"@logto/schemas": "workspace:^1.19.0",
|
||||
"@react-spring/shared": "^9.6.1",
|
||||
"@react-spring/web": "^9.6.1",
|
||||
"@silverhand/eslint-config": "6.0.1",
|
||||
"@silverhand/eslint-config-react": "6.0.2",
|
||||
"@silverhand/essentials": "^2.9.1",
|
||||
"@silverhand/ts-config": "6.0.0",
|
||||
"@silverhand/ts-config-react": "6.0.0",
|
||||
"@simplewebauthn/browser": "^10.0.0",
|
||||
"@simplewebauthn/types": "^10.0.0",
|
||||
"@swc/core": "^1.3.52",
|
||||
"@swc/jest": "^0.2.26",
|
||||
"@testing-library/react": "^16.0.0",
|
||||
"@testing-library/react-hooks": "^8.0.1",
|
||||
"@types/color": "^3.0.3",
|
||||
"@types/jest": "^29.4.0",
|
||||
"@types/react": "^18.3.3",
|
||||
"@types/react-dom": "^18.3.0",
|
||||
"@types/react-helmet": "^6.1.6",
|
||||
"@types/react-modal": "^3.13.1",
|
||||
"@types/react-router-dom": "^5.3.2",
|
||||
"@vitejs/plugin-react": "^4.3.1",
|
||||
"browserslist": "^4.23.2",
|
||||
"browserslist-to-esbuild": "^2.1.1",
|
||||
"camelcase-keys": "^9.1.3",
|
||||
"classnames": "^2.3.1",
|
||||
"color": "^4.2.3",
|
||||
"core-js": "^3.34.0",
|
||||
"eslint": "^8.56.0",
|
||||
"i18next": "^22.4.15",
|
||||
"i18next-browser-languagedetector": "^8.0.0",
|
||||
"identity-obj-proxy": "^3.0.0",
|
||||
"jest": "^29.7.0",
|
||||
"jest-environment-jsdom": "^29.7.0",
|
||||
"jest-transform-stub": "^2.0.0",
|
||||
"jest-transformer-svg": "^2.0.0",
|
||||
"js-base64": "^3.7.5",
|
||||
"ky": "^1.2.3",
|
||||
"libphonenumber-js": "^1.10.51",
|
||||
"lint-staged": "^15.0.0",
|
||||
"postcss": "^8.4.31",
|
||||
"postcss-modules": "^4.3.0",
|
||||
"prettier": "^3.0.0",
|
||||
"react": "^18.3.1",
|
||||
"react-device-detect": "^2.2.3",
|
||||
"react-dom": "^18.3.1",
|
||||
"react-helmet": "^6.1.0",
|
||||
"react-hook-form": "^7.53.0",
|
||||
"react-i18next": "^12.3.1",
|
||||
"react-modal": "^3.15.1",
|
||||
"react-router-dom": "^6.10.0",
|
||||
"react-string-replace": "^1.0.0",
|
||||
"react-timer-hook": "^3.0.5",
|
||||
"react-top-loading-bar": "^2.3.1",
|
||||
"stylelint": "^15.0.0",
|
||||
"superstruct": "^2.0.0",
|
||||
"tiny-cookie": "^2.4.1",
|
||||
"typescript": "^5.5.3",
|
||||
"use-debounced-loader": "^0.1.1",
|
||||
"vite": "^5.3.4",
|
||||
"vite-plugin-compression": "^0.5.1",
|
||||
"vite-plugin-svgr": "^4.2.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^20.9.0"
|
||||
},
|
||||
"stylelint": {
|
||||
"extends": "@silverhand/eslint-config-react/.stylelintrc"
|
||||
},
|
||||
"prettier": "@silverhand/eslint-config/.prettierrc"
|
||||
}
|
168
packages/experience-legacy/src/App.tsx
Normal file
|
@ -0,0 +1,168 @@
|
|||
import { MfaFactor, experience } from '@logto/schemas';
|
||||
import { Route, Routes, BrowserRouter } from 'react-router-dom';
|
||||
|
||||
import AppLayout from './Layout/AppLayout';
|
||||
import AppBoundary from './Providers/AppBoundary';
|
||||
import LoadingLayerProvider from './Providers/LoadingLayerProvider';
|
||||
import PageContextProvider from './Providers/PageContextProvider';
|
||||
import SettingsProvider from './Providers/SettingsProvider';
|
||||
import UserInteractionContextProvider from './Providers/UserInteractionContextProvider';
|
||||
import Callback from './pages/Callback';
|
||||
import Consent from './pages/Consent';
|
||||
import Continue from './pages/Continue';
|
||||
import DirectSignIn from './pages/DirectSignIn';
|
||||
import ErrorPage from './pages/ErrorPage';
|
||||
import ForgotPassword from './pages/ForgotPassword';
|
||||
import IdentifierRegister from './pages/IdentifierRegister';
|
||||
import IdentifierSignIn from './pages/IdentifierSignIn';
|
||||
import MfaBinding from './pages/MfaBinding';
|
||||
import BackupCodeBinding from './pages/MfaBinding/BackupCodeBinding';
|
||||
import TotpBinding from './pages/MfaBinding/TotpBinding';
|
||||
import WebAuthnBinding from './pages/MfaBinding/WebAuthnBinding';
|
||||
import MfaVerification from './pages/MfaVerification';
|
||||
import BackupCodeVerification from './pages/MfaVerification/BackupCodeVerification';
|
||||
import TotpVerification from './pages/MfaVerification/TotpVerification';
|
||||
import WebAuthnVerification from './pages/MfaVerification/WebAuthnVerification';
|
||||
import Register from './pages/Register';
|
||||
import RegisterPassword from './pages/RegisterPassword';
|
||||
import ResetPassword from './pages/ResetPassword';
|
||||
import ResetPasswordLanding from './pages/ResetPasswordLanding';
|
||||
import SignIn from './pages/SignIn';
|
||||
import SignInPassword from './pages/SignInPassword';
|
||||
import SingleSignOnConnectors from './pages/SingleSignOnConnectors';
|
||||
import SingleSignOnEmail from './pages/SingleSignOnEmail';
|
||||
import SingleSignOnLanding from './pages/SingleSignOnLanding';
|
||||
import SocialLanding from './pages/SocialLanding';
|
||||
import SocialLinkAccount from './pages/SocialLinkAccount';
|
||||
import SocialSignInWebCallback from './pages/SocialSignInWebCallback';
|
||||
import Springboard from './pages/Springboard';
|
||||
import VerificationCode from './pages/VerificationCode';
|
||||
import { UserMfaFlow } from './types';
|
||||
import { handleSearchParametersData } from './utils/search-parameters';
|
||||
|
||||
import './scss/normalized.scss';
|
||||
|
||||
handleSearchParametersData();
|
||||
|
||||
const App = () => {
|
||||
return (
|
||||
<BrowserRouter>
|
||||
<PageContextProvider>
|
||||
<SettingsProvider>
|
||||
<UserInteractionContextProvider>
|
||||
<AppBoundary>
|
||||
<Routes>
|
||||
<Route element={<LoadingLayerProvider />}>
|
||||
<Route path="springboard" element={<Springboard />} />
|
||||
<Route path="callback/:connectorId" element={<Callback />} />
|
||||
<Route
|
||||
path="callback/social/:connectorId"
|
||||
element={<SocialSignInWebCallback />}
|
||||
/>
|
||||
<Route path="direct/:method/:target?" element={<DirectSignIn />} />
|
||||
|
||||
<Route element={<AppLayout />}>
|
||||
<Route
|
||||
path="unknown-session"
|
||||
element={<ErrorPage message="error.invalid_session" />}
|
||||
/>
|
||||
|
||||
{/* Sign-in */}
|
||||
<Route path={experience.routes.signIn}>
|
||||
<Route index element={<SignIn />} />
|
||||
<Route path="password" element={<SignInPassword />} />
|
||||
</Route>
|
||||
|
||||
{/* Register */}
|
||||
<Route path={experience.routes.register}>
|
||||
<Route index element={<Register />} />
|
||||
<Route path="password" element={<RegisterPassword />} />
|
||||
</Route>
|
||||
|
||||
{/* Forgot password */}
|
||||
<Route path="forgot-password">
|
||||
<Route index element={<ForgotPassword />} />
|
||||
<Route path="reset" element={<ResetPassword />} />
|
||||
</Route>
|
||||
|
||||
{/* Passwordless verification code */}
|
||||
<Route path=":flow/verification-code" element={<VerificationCode />} />
|
||||
|
||||
{/* Mfa binding */}
|
||||
<Route path={UserMfaFlow.MfaBinding}>
|
||||
<Route index element={<MfaBinding />} />
|
||||
<Route path={MfaFactor.TOTP} element={<TotpBinding />} />
|
||||
<Route path={MfaFactor.WebAuthn} element={<WebAuthnBinding />} />
|
||||
<Route path={MfaFactor.BackupCode} element={<BackupCodeBinding />} />
|
||||
</Route>
|
||||
|
||||
{/* Mfa verification */}
|
||||
<Route path={UserMfaFlow.MfaVerification}>
|
||||
<Route index element={<MfaVerification />} />
|
||||
<Route path={MfaFactor.TOTP} element={<TotpVerification />} />
|
||||
<Route path={MfaFactor.WebAuthn} element={<WebAuthnVerification />} />
|
||||
<Route path={MfaFactor.BackupCode} element={<BackupCodeVerification />} />
|
||||
</Route>
|
||||
|
||||
{/* Continue set up missing profile */}
|
||||
<Route path="continue">
|
||||
<Route path=":method" element={<Continue />} />
|
||||
</Route>
|
||||
|
||||
{/* Social sign-in pages */}
|
||||
<Route path="social">
|
||||
<Route path="link/:connectorId" element={<SocialLinkAccount />} />
|
||||
<Route path="landing/:connectorId" element={<SocialLanding />} />
|
||||
</Route>
|
||||
|
||||
{/* Single sign-on */}
|
||||
<Route path={experience.routes.sso}>
|
||||
{/* Single sign-on first screen landing page */}
|
||||
<Route index element={<SingleSignOnLanding />} />
|
||||
<Route path="email" element={<SingleSignOnEmail />} />
|
||||
<Route path="connectors" element={<SingleSignOnConnectors />} />
|
||||
</Route>
|
||||
|
||||
{/* Consent */}
|
||||
<Route path="consent" element={<Consent />} />
|
||||
|
||||
{/*
|
||||
* Identifier sign-in (first screen)
|
||||
* The first screen which only display specific identifier-based sign-in methods to users
|
||||
*/}
|
||||
<Route
|
||||
path={experience.routes.identifierSignIn}
|
||||
element={<IdentifierSignIn />}
|
||||
/>
|
||||
|
||||
{/*
|
||||
* Identifier register (first screen)
|
||||
* The first screen which only display specific identifier-based registration methods to users
|
||||
*/}
|
||||
<Route
|
||||
path={experience.routes.identifierRegister}
|
||||
element={<IdentifierRegister />}
|
||||
/>
|
||||
|
||||
{/*
|
||||
* Reset password (first screen)
|
||||
* The first screen which allow users to directly access the password reset page
|
||||
*/}
|
||||
<Route
|
||||
path={experience.routes.resetPassword}
|
||||
element={<ResetPasswordLanding />}
|
||||
/>
|
||||
|
||||
<Route path="*" element={<ErrorPage />} />
|
||||
</Route>
|
||||
</Route>
|
||||
</Routes>
|
||||
</AppBoundary>
|
||||
</UserInteractionContextProvider>
|
||||
</SettingsProvider>
|
||||
</PageContextProvider>
|
||||
</BrowserRouter>
|
||||
);
|
||||
};
|
||||
|
||||
export default App;
|
|
@ -0,0 +1,28 @@
|
|||
import { useLocation } from 'react-router-dom';
|
||||
|
||||
import { useSieMethods } from '@/hooks/use-sie';
|
||||
|
||||
type Props = {
|
||||
readonly className?: string;
|
||||
};
|
||||
|
||||
const CustomContent = ({ className }: Props) => {
|
||||
const { customContent } = useSieMethods();
|
||||
const { pathname } = useLocation();
|
||||
|
||||
const customHtml = customContent?.[pathname];
|
||||
|
||||
if (!customHtml) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
// Expected error; CustomContent content is load from Logto remote server
|
||||
// eslint-disable-next-line react/no-danger
|
||||
return <div dangerouslySetInnerHTML={{ __html: customHtml }} className={className} />;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
export default CustomContent;
|
|
@ -0,0 +1,66 @@
|
|||
@use '@/scss/underscore' as _;
|
||||
|
||||
/* Main Layout */
|
||||
.viewBox {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.container {
|
||||
min-height: 100%;
|
||||
@include _.flex_column(center, center);
|
||||
}
|
||||
|
||||
.main {
|
||||
@include _.flex_column;
|
||||
}
|
||||
|
||||
:global(body.mobile) {
|
||||
.container {
|
||||
padding-bottom: env(safe-area-inset-bottom);
|
||||
}
|
||||
|
||||
.main {
|
||||
flex: 1;
|
||||
align-self: stretch;
|
||||
padding: _.unit(4) _.unit(5);
|
||||
position: relative;
|
||||
background: var(--color-bg-body);
|
||||
}
|
||||
|
||||
.signature {
|
||||
margin: _.unit(10) 0 _.unit(2);
|
||||
}
|
||||
}
|
||||
|
||||
:global(body.desktop) {
|
||||
.container {
|
||||
padding: _.unit(5);
|
||||
}
|
||||
|
||||
.main {
|
||||
width: 540px;
|
||||
min-height: 540px;
|
||||
position: relative;
|
||||
padding: _.unit(6);
|
||||
border-radius: 16px;
|
||||
background: var(--color-bg-float);
|
||||
box-shadow: var(--color-shadow-2);
|
||||
}
|
||||
|
||||
.signature {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
transform: translateY(calc(100% + _.unit(7)));
|
||||
// Have to use padding instead of margin. Overflow margin spacing will be ignored by the browser.
|
||||
padding-bottom: _.unit(7);
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 580px) {
|
||||
.main {
|
||||
align-self: stretch;
|
||||
width: auto;
|
||||
}
|
||||
}
|
||||
}
|
29
packages/experience-legacy/src/Layout/AppLayout/index.tsx
Normal file
|
@ -0,0 +1,29 @@
|
|||
import classNames from 'classnames';
|
||||
import { Outlet } from 'react-router-dom';
|
||||
|
||||
import LogtoSignature from '@/components/LogtoSignature';
|
||||
import DevelopmentTenantNotification from '@/containers/DevelopmentTenantNotification';
|
||||
import usePlatform from '@/hooks/use-platform';
|
||||
import { layoutClassNames } from '@/utils/consts';
|
||||
|
||||
import CustomContent from './CustomContent';
|
||||
import styles from './index.module.scss';
|
||||
|
||||
const AppLayout = () => {
|
||||
const { isMobile } = usePlatform();
|
||||
|
||||
return (
|
||||
<div className={styles.viewBox}>
|
||||
<div className={classNames(styles.container, layoutClassNames.pageContainer)}>
|
||||
{!isMobile && <CustomContent className={layoutClassNames.customContent} />}
|
||||
<main className={classNames(styles.main, layoutClassNames.mainContent)}>
|
||||
<DevelopmentTenantNotification />
|
||||
<Outlet />
|
||||
<LogtoSignature className={classNames(styles.signature, layoutClassNames.signature)} />
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default AppLayout;
|
|
@ -0,0 +1,25 @@
|
|||
@use '@/scss/underscore' as _;
|
||||
|
||||
.wrapper {
|
||||
@include _.full-page;
|
||||
@include _.flex-column(normal, normal);
|
||||
@include _.full-width;
|
||||
|
||||
> *:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
:global(body.desktop) {
|
||||
.wrapper {
|
||||
padding: _.unit(6) 0;
|
||||
}
|
||||
|
||||
.placeholderTop {
|
||||
flex: 3;
|
||||
}
|
||||
|
||||
.placeholderBottom {
|
||||
flex: 5;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
import { type ReactNode, useContext } from 'react';
|
||||
|
||||
import PageContext from '@/Providers/PageContextProvider/PageContext';
|
||||
|
||||
import PageMeta from '../../components/PageMeta';
|
||||
import type { Props as PageMetaProps } from '../../components/PageMeta';
|
||||
|
||||
import styles from './index.module.scss';
|
||||
|
||||
type Props = {
|
||||
readonly children: ReactNode;
|
||||
readonly pageMeta: PageMetaProps;
|
||||
};
|
||||
|
||||
const FirstScreenLayout = ({ children, pageMeta }: Props) => {
|
||||
const { platform } = useContext(PageContext);
|
||||
|
||||
return (
|
||||
<>
|
||||
<PageMeta {...pageMeta} />
|
||||
{platform === 'web' && <div className={styles.placeholderTop} />}
|
||||
<div className={styles.wrapper}>{children}</div>
|
||||
{platform === 'web' && <div className={styles.placeholderBottom} />}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default FirstScreenLayout;
|
|
@ -0,0 +1,33 @@
|
|||
@use '@/scss/underscore' as _;
|
||||
|
||||
.header {
|
||||
margin: _.unit(6) 0;
|
||||
}
|
||||
|
||||
.description {
|
||||
margin-top: _.unit(2);
|
||||
@include _.text-hint;
|
||||
}
|
||||
|
||||
.terms {
|
||||
margin-top: _.unit(4);
|
||||
@include _.text-hint;
|
||||
text-align: center;
|
||||
font: var(--font-body-3);
|
||||
}
|
||||
|
||||
.link {
|
||||
margin-top: _.unit(7);
|
||||
}
|
||||
|
||||
:global(body.mobile) {
|
||||
.title {
|
||||
@include _.title;
|
||||
}
|
||||
}
|
||||
|
||||
:global(body.desktop) {
|
||||
.title {
|
||||
@include _.title_desktop;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
import { type AgreeToTermsPolicy } from '@logto/schemas';
|
||||
import { type TFuncKey } from 'i18next';
|
||||
import { useMemo, type ReactNode } from 'react';
|
||||
|
||||
import DynamicT from '@/components/DynamicT';
|
||||
import type { Props as PageMetaProps } from '@/components/PageMeta';
|
||||
import type { Props as TextLinkProps } from '@/components/TextLink';
|
||||
import TextLink from '@/components/TextLink';
|
||||
import TermsAndPrivacyLinks from '@/containers/TermsAndPrivacyLinks';
|
||||
import useTerms from '@/hooks/use-terms';
|
||||
|
||||
import FirstScreenLayout from '../FirstScreenLayout';
|
||||
|
||||
import styles from './index.module.scss';
|
||||
|
||||
type Props = {
|
||||
readonly children: ReactNode;
|
||||
readonly pageMeta: PageMetaProps;
|
||||
readonly title: TFuncKey;
|
||||
readonly description: string;
|
||||
readonly footerTermsDisplayPolicies?: AgreeToTermsPolicy[];
|
||||
readonly authOptionsLink: TextLinkProps;
|
||||
};
|
||||
|
||||
/**
|
||||
* FocusedAuthPageLayout Component
|
||||
*
|
||||
* This layout component is designed for focused authentication pages that serve as the first screen
|
||||
* for specific auth methods, such as identifier sign-in, identifier-register, and single sign-on landing pages.
|
||||
*/
|
||||
const FocusedAuthPageLayout = ({
|
||||
children,
|
||||
pageMeta,
|
||||
title,
|
||||
description,
|
||||
footerTermsDisplayPolicies = [],
|
||||
authOptionsLink,
|
||||
}: Props) => {
|
||||
const { agreeToTermsPolicy } = useTerms();
|
||||
|
||||
const shouldDisplayFooterTerms = useMemo(
|
||||
() => agreeToTermsPolicy && footerTermsDisplayPolicies.includes(agreeToTermsPolicy),
|
||||
[agreeToTermsPolicy, footerTermsDisplayPolicies]
|
||||
);
|
||||
|
||||
return (
|
||||
<FirstScreenLayout pageMeta={pageMeta}>
|
||||
<div className={styles.header}>
|
||||
<div className={styles.title}>
|
||||
<DynamicT forKey={title} />
|
||||
</div>
|
||||
<div className={styles.description}>{description}</div>
|
||||
</div>
|
||||
{children}
|
||||
{shouldDisplayFooterTerms && <TermsAndPrivacyLinks className={styles.terms} />}
|
||||
<TextLink {...authOptionsLink} className={styles.link} />
|
||||
</FirstScreenLayout>
|
||||
);
|
||||
};
|
||||
|
||||
export default FocusedAuthPageLayout;
|
|
@ -0,0 +1,36 @@
|
|||
@use '@/scss/underscore' as _;
|
||||
|
||||
.wrapper {
|
||||
@include _.full-page;
|
||||
@include _.flex-column(normal, normal);
|
||||
@include _.full-width;
|
||||
|
||||
> *:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
:global(body.mobile) {
|
||||
.header {
|
||||
margin-top: _.unit(3);
|
||||
padding-bottom: _.unit(7);
|
||||
}
|
||||
}
|
||||
|
||||
:global(body.desktop) {
|
||||
.wrapper {
|
||||
padding: _.unit(6) 0;
|
||||
}
|
||||
|
||||
.header {
|
||||
margin-bottom: _.unit(6);
|
||||
}
|
||||
|
||||
.placeholderTop {
|
||||
flex: 3;
|
||||
}
|
||||
|
||||
.placeholderBottom {
|
||||
flex: 5;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
import { type ConsentInfoResponse } from '@logto/schemas';
|
||||
import classNames from 'classnames';
|
||||
import type { TFuncKey } from 'i18next';
|
||||
import type { ReactNode } from 'react';
|
||||
import { useContext } from 'react';
|
||||
|
||||
import PageContext from '@/Providers/PageContextProvider/PageContext';
|
||||
import BrandingHeader from '@/components/BrandingHeader';
|
||||
import { layoutClassNames } from '@/utils/consts';
|
||||
import { getBrandingLogoUrl } from '@/utils/logo';
|
||||
|
||||
import FirstScreenLayout from '../FirstScreenLayout';
|
||||
|
||||
import styles from './index.module.scss';
|
||||
|
||||
type ThirdPartyBranding = ConsentInfoResponse['application']['branding'];
|
||||
|
||||
type Props = {
|
||||
readonly children: ReactNode;
|
||||
readonly title: TFuncKey;
|
||||
readonly titleInterpolation?: Record<string, unknown>;
|
||||
readonly thirdPartyBranding?: ThirdPartyBranding;
|
||||
};
|
||||
|
||||
const LandingPageLayout = ({ children, title, titleInterpolation, thirdPartyBranding }: Props) => {
|
||||
const { experienceSettings, theme } = useContext(PageContext);
|
||||
|
||||
if (!experienceSettings) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const {
|
||||
color: { isDarkModeEnabled },
|
||||
branding,
|
||||
} = experienceSettings;
|
||||
|
||||
return (
|
||||
<FirstScreenLayout pageMeta={{ titleKey: title, titleKeyInterpolation: titleInterpolation }}>
|
||||
<BrandingHeader
|
||||
className={classNames(styles.header, layoutClassNames.brandingHeader)}
|
||||
headline={title}
|
||||
headlineInterpolation={titleInterpolation}
|
||||
logo={getBrandingLogoUrl({ theme, branding, isDarkModeEnabled })}
|
||||
thirdPartyLogo={
|
||||
thirdPartyBranding &&
|
||||
getBrandingLogoUrl({ theme, branding: thirdPartyBranding, isDarkModeEnabled })
|
||||
}
|
||||
/>
|
||||
{children}
|
||||
</FirstScreenLayout>
|
||||
);
|
||||
};
|
||||
|
||||
export default LandingPageLayout;
|
|
@ -0,0 +1,53 @@
|
|||
@use '@/scss/underscore' as _;
|
||||
|
||||
.wrapper {
|
||||
@include _.full-page;
|
||||
}
|
||||
|
||||
.container {
|
||||
@include _.full-width;
|
||||
margin-top: _.unit(2);
|
||||
}
|
||||
|
||||
.header {
|
||||
margin-bottom: _.unit(6);
|
||||
}
|
||||
|
||||
.description {
|
||||
margin-top: _.unit(2);
|
||||
@include _.text-hint;
|
||||
}
|
||||
|
||||
:global(body.mobile) {
|
||||
.container {
|
||||
margin-top: _.unit(2);
|
||||
}
|
||||
|
||||
.title {
|
||||
@include _.title;
|
||||
}
|
||||
|
||||
.notification {
|
||||
margin: 0 _.unit(-5) _.unit(6);
|
||||
}
|
||||
}
|
||||
|
||||
:global(body.desktop) {
|
||||
.container {
|
||||
margin-top: _.unit(12);
|
||||
}
|
||||
|
||||
.header {
|
||||
margin-bottom: _.unit(4);
|
||||
}
|
||||
|
||||
.title {
|
||||
@include _.title_desktop;
|
||||
}
|
||||
|
||||
.notification {
|
||||
@include _.full-width;
|
||||
margin-top: _.unit(6);
|
||||
border-radius: var(--radius);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
import type { TFuncKey } from 'i18next';
|
||||
import { type ReactElement } from 'react';
|
||||
|
||||
import DynamicT from '@/components/DynamicT';
|
||||
import NavBar from '@/components/NavBar';
|
||||
import PageMeta from '@/components/PageMeta';
|
||||
import usePlatform from '@/hooks/use-platform';
|
||||
|
||||
import { InlineNotification } from '../../components/Notification';
|
||||
|
||||
import styles from './index.module.scss';
|
||||
|
||||
type Props = {
|
||||
readonly title: TFuncKey;
|
||||
readonly description?: TFuncKey | ReactElement | '';
|
||||
readonly titleProps?: Record<string, unknown>;
|
||||
readonly descriptionProps?: Record<string, unknown>;
|
||||
readonly notification?: TFuncKey;
|
||||
readonly onSkip?: () => void;
|
||||
readonly isNavBarHidden?: boolean;
|
||||
readonly children: React.ReactNode;
|
||||
};
|
||||
|
||||
const SecondaryPageLayout = ({
|
||||
title,
|
||||
description,
|
||||
titleProps,
|
||||
descriptionProps,
|
||||
notification,
|
||||
onSkip,
|
||||
isNavBarHidden,
|
||||
children,
|
||||
}: Props) => {
|
||||
const { isMobile } = usePlatform();
|
||||
|
||||
return (
|
||||
<div className={styles.wrapper}>
|
||||
<PageMeta titleKey={title} />
|
||||
<NavBar isHidden={isNavBarHidden} onSkip={onSkip} />
|
||||
{isMobile && notification && (
|
||||
<InlineNotification message={notification} className={styles.notification} />
|
||||
)}
|
||||
<div className={styles.container}>
|
||||
<div className={styles.header}>
|
||||
<div className={styles.title}>
|
||||
<DynamicT forKey={title} interpolation={titleProps} />
|
||||
</div>
|
||||
{description && (
|
||||
<div className={styles.description}>
|
||||
{typeof description === 'string' ? (
|
||||
<DynamicT forKey={description} interpolation={descriptionProps} />
|
||||
) : (
|
||||
description
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
{children}
|
||||
</div>
|
||||
{!isMobile && notification && (
|
||||
<InlineNotification message={notification} className={styles.notification} />
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default SecondaryPageLayout;
|
|
@ -0,0 +1,11 @@
|
|||
@use '@/scss/underscore' as _;
|
||||
|
||||
.title {
|
||||
font: var(--font-title-3);
|
||||
}
|
||||
|
||||
.description {
|
||||
font: var(--font-body-2);
|
||||
color: var(--color-type-secondary);
|
||||
margin-top: _.unit(1);
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
import { type TFuncKey } from 'i18next';
|
||||
import { type ReactNode } from 'react';
|
||||
|
||||
import DynamicT from '@/components/DynamicT';
|
||||
|
||||
import styles from './index.module.scss';
|
||||
|
||||
type Props = {
|
||||
readonly title: TFuncKey;
|
||||
readonly description: TFuncKey;
|
||||
readonly titleProps?: Record<string, unknown>;
|
||||
readonly descriptionProps?: Record<string, unknown>;
|
||||
readonly children: ReactNode;
|
||||
};
|
||||
|
||||
const SectionLayout = ({ title, description, titleProps, descriptionProps, children }: Props) => {
|
||||
return (
|
||||
<div>
|
||||
<div className={styles.title}>
|
||||
<DynamicT forKey={title} interpolation={titleProps} />
|
||||
</div>
|
||||
<div className={styles.description}>
|
||||
<DynamicT forKey={description} interpolation={descriptionProps} />
|
||||
</div>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default SectionLayout;
|
|
@ -0,0 +1,7 @@
|
|||
@use '@/scss/underscore' as _;
|
||||
|
||||
|
||||
.wrapper {
|
||||
@include _.full-page;
|
||||
@include _.flex-column;
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
import styles from './index.module.scss';
|
||||
|
||||
type Props = {
|
||||
readonly children: React.ReactNode;
|
||||
};
|
||||
|
||||
const StaticPageLayout = ({ children }: Props) => {
|
||||
return <div className={styles.wrapper}>{children}</div>;
|
||||
};
|
||||
|
||||
export default StaticPageLayout;
|
|
@ -0,0 +1,56 @@
|
|||
import { Theme } from '@logto/schemas';
|
||||
import { conditionalString } from '@silverhand/essentials';
|
||||
import classNames from 'classnames';
|
||||
import i18next from 'i18next';
|
||||
import { useContext } from 'react';
|
||||
import { Helmet } from 'react-helmet';
|
||||
|
||||
import PageContext from '@/Providers/PageContextProvider/PageContext';
|
||||
import defaultAppleTouchLogo from '@/assets/apple-touch-icon.png';
|
||||
import defaultFavicon from '@/assets/favicon.png';
|
||||
import { type SignInExperienceResponse } from '@/types';
|
||||
|
||||
import styles from './index.module.scss';
|
||||
|
||||
const themeToFavicon = Object.freeze({
|
||||
[Theme.Light]: 'favicon',
|
||||
[Theme.Dark]: 'darkFavicon',
|
||||
} as const satisfies Record<Theme, keyof SignInExperienceResponse['branding']>);
|
||||
|
||||
/**
|
||||
* User React Helmet to manage html and body attributes
|
||||
* @see https://github.com/nfl/react-helmet
|
||||
*
|
||||
* - lang: set html lang attribute
|
||||
* - data-theme: set html data-theme attribute
|
||||
* - favicon: set favicon
|
||||
* - apple-touch-icon: set apple touch icon
|
||||
* - body class: set preview body class
|
||||
* - body class: set platform body class
|
||||
* - body class: set theme body class
|
||||
* - custom css: set custom css style tag
|
||||
*/
|
||||
|
||||
const AppMeta = () => {
|
||||
const { experienceSettings, theme, platform, isPreview } = useContext(PageContext);
|
||||
const favicon =
|
||||
experienceSettings?.branding[themeToFavicon[theme]] ?? experienceSettings?.branding.favicon;
|
||||
|
||||
return (
|
||||
<Helmet>
|
||||
<html lang={i18next.language} data-theme={theme} />
|
||||
<link rel="shortcut icon" href={favicon ?? defaultFavicon} />
|
||||
<link rel="apple-touch-icon" href={favicon ?? defaultAppleTouchLogo} sizes="180x180" />
|
||||
{experienceSettings?.customCss && <style>{experienceSettings.customCss}</style>}
|
||||
<body
|
||||
className={classNames(
|
||||
conditionalString(isPreview && styles.preview),
|
||||
platform === 'mobile' ? 'mobile' : 'desktop',
|
||||
conditionalString(styles[theme])
|
||||
)}
|
||||
/>
|
||||
</Helmet>
|
||||
);
|
||||
};
|
||||
|
||||
export default AppMeta;
|
|
@ -0,0 +1,37 @@
|
|||
@use '@/scss/colors' as colors;
|
||||
@use '@/scss/underscore' as _;
|
||||
|
||||
body {
|
||||
&.light {
|
||||
@include colors.light;
|
||||
}
|
||||
|
||||
&.dark {
|
||||
@include colors.dark;
|
||||
}
|
||||
}
|
||||
|
||||
/* Preview Settings */
|
||||
.preview {
|
||||
pointer-events: none;
|
||||
user-select: none;
|
||||
|
||||
.viewBox::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
main {
|
||||
pointer-events: none;
|
||||
user-select: none;
|
||||
}
|
||||
}
|
||||
|
||||
:global(body.mobile) {
|
||||
--max-width: 360px;
|
||||
background: var(--color-bg-body);
|
||||
}
|
||||
|
||||
:global(body.desktop) {
|
||||
--max-width: 400px;
|
||||
background: var(--color-bg-float-base);
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
import type { ReactElement } from 'react';
|
||||
|
||||
import useColorTheme from '@/Providers/AppBoundary/use-color-theme';
|
||||
|
||||
import ConfirmModalProvider from '../ConfirmModalProvider';
|
||||
import IframeModalProvider from '../IframeModalProvider';
|
||||
import ToastProvider from '../ToastProvider';
|
||||
|
||||
import AppMeta from './AppMeta';
|
||||
|
||||
type Props = {
|
||||
readonly children: ReactElement;
|
||||
};
|
||||
|
||||
const AppBoundary = ({ children }: Props) => {
|
||||
useColorTheme();
|
||||
|
||||
return (
|
||||
<>
|
||||
<AppMeta />
|
||||
<IframeModalProvider>
|
||||
<ConfirmModalProvider>
|
||||
<ToastProvider>{children}</ToastProvider>
|
||||
</ConfirmModalProvider>
|
||||
</IframeModalProvider>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default AppBoundary;
|
|
@ -0,0 +1,62 @@
|
|||
import { absoluteDarken, absoluteLighten } from '@logto/core-kit';
|
||||
import { Theme } from '@logto/schemas';
|
||||
import color from 'color';
|
||||
import { useEffect, useContext } from 'react';
|
||||
|
||||
import PageContext from '@/Providers/PageContextProvider/PageContext';
|
||||
|
||||
const generateLightColorLibrary = (primaryColor: color) => ({
|
||||
[`--color-brand-default`]: primaryColor.hex(),
|
||||
[`--color-brand-hover`]: absoluteLighten(primaryColor, 10).string(),
|
||||
[`--color-brand-pressed`]: absoluteDarken(primaryColor, 10).string(),
|
||||
[`--color-brand-loading`]: absoluteLighten(primaryColor, 15).string(),
|
||||
[`--color-overlay-brand-focused`]: primaryColor.alpha(0.16).string(),
|
||||
[`--color-overlay-brand-hover`]: primaryColor.alpha(0.08).string(),
|
||||
[`--color-overlay-brand-pressed`]: primaryColor.alpha(0.12).string(),
|
||||
});
|
||||
|
||||
const generateDarkColorLibrary = (primaryColor: color) => ({
|
||||
[`--color-brand-default`]: primaryColor.hex(),
|
||||
[`--color-brand-hover`]: absoluteLighten(primaryColor, 10).string(),
|
||||
[`--color-brand-pressed`]: absoluteDarken(primaryColor, 10).string(),
|
||||
[`--color-brand-loading`]: absoluteDarken(primaryColor, 10).string(),
|
||||
[`--color-overlay-brand-focused`]: absoluteLighten(primaryColor, 30).rgb().alpha(0.16).string(),
|
||||
[`--color-overlay-brand-hover`]: absoluteLighten(primaryColor, 30).rgb().alpha(0.08).string(),
|
||||
[`--color-overlay-brand-pressed`]: absoluteLighten(primaryColor, 30).rgb().alpha(0.12).string(),
|
||||
});
|
||||
|
||||
const useColorTheme = () => {
|
||||
const { theme, experienceSettings } = useContext(PageContext);
|
||||
const primaryColor = experienceSettings?.color.primaryColor;
|
||||
const darkPrimaryColor = experienceSettings?.color.darkPrimaryColor;
|
||||
|
||||
useEffect(() => {
|
||||
if (!primaryColor) {
|
||||
return;
|
||||
}
|
||||
|
||||
const lightPrimary = color(primaryColor);
|
||||
|
||||
if (theme === Theme.Light) {
|
||||
const lightColorLibrary = generateLightColorLibrary(lightPrimary);
|
||||
|
||||
for (const [key, value] of Object.entries(lightColorLibrary)) {
|
||||
document.body.style.setProperty(key, value);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const darkPrimary = darkPrimaryColor
|
||||
? color(darkPrimaryColor)
|
||||
: absoluteLighten(lightPrimary, 10);
|
||||
|
||||
const darkColorLibrary = generateDarkColorLibrary(darkPrimary);
|
||||
|
||||
for (const [key, value] of Object.entries(darkColorLibrary)) {
|
||||
document.body.style.setProperty(key, value);
|
||||
}
|
||||
}, [darkPrimaryColor, primaryColor, theme]);
|
||||
};
|
||||
|
||||
export default useColorTheme;
|
|
@ -0,0 +1,161 @@
|
|||
import type { Nullable } from '@silverhand/essentials';
|
||||
import { noop } from '@silverhand/essentials';
|
||||
import { useState, useRef, useMemo, createContext, useCallback } from 'react';
|
||||
|
||||
import type { ModalProps } from '@/components/ConfirmModal';
|
||||
import { WebModal, MobileModal } from '@/components/ConfirmModal';
|
||||
import usePlatform from '@/hooks/use-platform';
|
||||
|
||||
type ConfirmModalType = 'alert' | 'confirm';
|
||||
|
||||
type ConfirmModalState = Omit<ModalProps, 'onClose' | 'onConfirm' | 'children'> & {
|
||||
ModalContent: string | (() => Nullable<JSX.Element>);
|
||||
type: ConfirmModalType;
|
||||
isConfirmLoading?: boolean;
|
||||
isCancelLoading?: boolean;
|
||||
};
|
||||
|
||||
/**
|
||||
* Props for promise-based modal usage
|
||||
*/
|
||||
type PromiseConfirmModalProps = Omit<ConfirmModalState, 'isOpen' | 'type' | 'isConfirmLoading'> & {
|
||||
type?: ConfirmModalType;
|
||||
};
|
||||
|
||||
/**
|
||||
* Props for callback-based modal usage
|
||||
*/
|
||||
export type CallbackConfirmModalProps = PromiseConfirmModalProps & {
|
||||
onConfirm?: () => Promise<void> | void;
|
||||
onCancel?: () => Promise<void> | void;
|
||||
};
|
||||
|
||||
type ConfirmModalContextType = {
|
||||
showPromise: (props: PromiseConfirmModalProps) => Promise<[boolean, unknown?]>;
|
||||
showCallback: (props: CallbackConfirmModalProps) => void;
|
||||
};
|
||||
|
||||
export const ConfirmModalContext = createContext<ConfirmModalContextType>({
|
||||
showPromise: async () => [true],
|
||||
showCallback: noop,
|
||||
});
|
||||
|
||||
type Props = {
|
||||
readonly children?: React.ReactNode;
|
||||
};
|
||||
|
||||
const defaultModalState: ConfirmModalState = {
|
||||
isOpen: false,
|
||||
type: 'confirm',
|
||||
ModalContent: () => null,
|
||||
isConfirmLoading: false,
|
||||
isCancelLoading: false,
|
||||
};
|
||||
|
||||
/**
|
||||
* ConfirmModalProvider component
|
||||
*
|
||||
* This component provides a context for managing confirm modals throughout the application.
|
||||
* It supports both promise-based and callback-based usage patterns. see `usePromiseConfirmModal` and `useConfirmModal` hooks.
|
||||
*/
|
||||
const ConfirmModalProvider = ({ children }: Props) => {
|
||||
const [modalState, setModalState] = useState<ConfirmModalState>(defaultModalState);
|
||||
|
||||
const resolver = useRef<(value: [result: boolean, data?: unknown]) => void>();
|
||||
const callbackRef = useRef<{
|
||||
onConfirm?: () => Promise<void> | void;
|
||||
onCancel?: () => Promise<void> | void;
|
||||
}>({});
|
||||
|
||||
const { isMobile } = usePlatform();
|
||||
|
||||
const ConfirmModal = isMobile ? MobileModal : WebModal;
|
||||
|
||||
const handleShowPromise = useCallback(
|
||||
async ({ type = 'confirm', ...props }: PromiseConfirmModalProps) => {
|
||||
resolver.current?.([false]);
|
||||
|
||||
setModalState({
|
||||
isOpen: true,
|
||||
type,
|
||||
isConfirmLoading: false,
|
||||
isCancelLoading: false,
|
||||
...props,
|
||||
});
|
||||
|
||||
return new Promise<[result: boolean, data?: unknown]>((resolve) => {
|
||||
// eslint-disable-next-line @silverhand/fp/no-mutation
|
||||
resolver.current = resolve;
|
||||
});
|
||||
},
|
||||
[]
|
||||
);
|
||||
|
||||
const handleShowCallback = useCallback(
|
||||
({ type = 'confirm', onConfirm, onCancel, ...props }: CallbackConfirmModalProps) => {
|
||||
resolver.current?.([false]);
|
||||
|
||||
setModalState({
|
||||
isOpen: true,
|
||||
type,
|
||||
isConfirmLoading: false,
|
||||
...props,
|
||||
});
|
||||
|
||||
// eslint-disable-next-line @silverhand/fp/no-mutation
|
||||
callbackRef.current = { onConfirm, onCancel };
|
||||
},
|
||||
[]
|
||||
);
|
||||
|
||||
const handleConfirm = useCallback(async (data?: unknown) => {
|
||||
if (callbackRef.current.onConfirm) {
|
||||
setModalState((previous) => ({ ...previous, isConfirmLoading: true }));
|
||||
await callbackRef.current.onConfirm();
|
||||
}
|
||||
resolver.current?.([true, data]);
|
||||
setModalState(defaultModalState);
|
||||
}, []);
|
||||
|
||||
const handleCancel = useCallback(async (data?: unknown) => {
|
||||
if (callbackRef.current.onCancel) {
|
||||
setModalState((previous) => ({ ...previous, isCancelLoading: true }));
|
||||
await callbackRef.current.onCancel();
|
||||
}
|
||||
resolver.current?.([false, data]);
|
||||
setModalState(defaultModalState);
|
||||
}, []);
|
||||
|
||||
const contextValue = useMemo(
|
||||
() => ({
|
||||
showPromise: handleShowPromise,
|
||||
showCallback: handleShowCallback,
|
||||
}),
|
||||
[handleShowPromise, handleShowCallback]
|
||||
);
|
||||
|
||||
const { ModalContent, type, ...restProps } = modalState;
|
||||
|
||||
return (
|
||||
<ConfirmModalContext.Provider value={contextValue}>
|
||||
{children}
|
||||
<ConfirmModal
|
||||
{...restProps}
|
||||
onConfirm={
|
||||
type === 'confirm'
|
||||
? () => {
|
||||
void handleConfirm();
|
||||
}
|
||||
: undefined
|
||||
}
|
||||
onClose={() => {
|
||||
void handleCancel();
|
||||
}}
|
||||
>
|
||||
{typeof ModalContent === 'string' ? ModalContent : <ModalContent />}
|
||||
</ConfirmModal>
|
||||
</ConfirmModalContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
export default ConfirmModalProvider;
|
|
@ -0,0 +1,203 @@
|
|||
import { render, fireEvent, waitFor } from '@testing-library/react';
|
||||
import { act } from 'react-dom/test-utils';
|
||||
|
||||
import { useConfirmModal, usePromiseConfirmModal } from '@/hooks/use-confirm-modal';
|
||||
|
||||
import ConfirmModalProvider from '.';
|
||||
|
||||
const confirmHandler = jest.fn();
|
||||
const cancelHandler = jest.fn();
|
||||
|
||||
const PromiseConfirmModalTestComponent = () => {
|
||||
const { show } = usePromiseConfirmModal();
|
||||
|
||||
const onClick = async () => {
|
||||
const [result] = await show({ ModalContent: 'confirm modal content' });
|
||||
|
||||
if (result) {
|
||||
confirmHandler();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
cancelHandler();
|
||||
};
|
||||
|
||||
return <button onClick={onClick}>show modal</button>;
|
||||
};
|
||||
|
||||
const CallbackConfirmModalTestComponent = () => {
|
||||
const { show } = useConfirmModal();
|
||||
|
||||
const onClick = () => {
|
||||
show({
|
||||
ModalContent: 'confirm modal content',
|
||||
onConfirm: confirmHandler,
|
||||
onCancel: cancelHandler,
|
||||
});
|
||||
};
|
||||
|
||||
return <button onClick={onClick}>show modal</button>;
|
||||
};
|
||||
|
||||
describe('confirm modal provider', () => {
|
||||
describe('promise confirm modal', () => {
|
||||
it('render confirm modal', async () => {
|
||||
const { queryByText, getByText } = render(
|
||||
<ConfirmModalProvider>
|
||||
<PromiseConfirmModalTestComponent />
|
||||
</ConfirmModalProvider>
|
||||
);
|
||||
|
||||
const trigger = getByText('show modal');
|
||||
|
||||
act(() => {
|
||||
fireEvent.click(trigger);
|
||||
});
|
||||
|
||||
await waitFor(() => {
|
||||
expect(queryByText('confirm modal content')).not.toBeNull();
|
||||
expect(queryByText('action.confirm')).not.toBeNull();
|
||||
expect(queryByText('action.cancel')).not.toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
it('confirm callback of confirm modal', async () => {
|
||||
const { queryByText, getByText } = render(
|
||||
<ConfirmModalProvider>
|
||||
<PromiseConfirmModalTestComponent />
|
||||
</ConfirmModalProvider>
|
||||
);
|
||||
|
||||
const trigger = getByText('show modal');
|
||||
|
||||
act(() => {
|
||||
fireEvent.click(trigger);
|
||||
});
|
||||
|
||||
await waitFor(() => {
|
||||
expect(queryByText('confirm modal content')).not.toBeNull();
|
||||
expect(queryByText('action.confirm')).not.toBeNull();
|
||||
});
|
||||
|
||||
const confirm = getByText('action.confirm');
|
||||
|
||||
act(() => {
|
||||
fireEvent.click(confirm);
|
||||
});
|
||||
|
||||
await waitFor(() => {
|
||||
expect(confirmHandler).toBeCalled();
|
||||
});
|
||||
});
|
||||
|
||||
it('cancel callback of confirm modal', async () => {
|
||||
const { queryByText, getByText } = render(
|
||||
<ConfirmModalProvider>
|
||||
<PromiseConfirmModalTestComponent />
|
||||
</ConfirmModalProvider>
|
||||
);
|
||||
|
||||
const trigger = getByText('show modal');
|
||||
|
||||
act(() => {
|
||||
fireEvent.click(trigger);
|
||||
});
|
||||
|
||||
await waitFor(() => {
|
||||
expect(queryByText('confirm modal content')).not.toBeNull();
|
||||
expect(queryByText('action.cancel')).not.toBeNull();
|
||||
});
|
||||
|
||||
const cancel = getByText('action.cancel');
|
||||
|
||||
act(() => {
|
||||
fireEvent.click(cancel);
|
||||
});
|
||||
|
||||
await waitFor(() => {
|
||||
expect(cancelHandler).toBeCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('callback confirm modal', () => {
|
||||
it('render confirm modal', async () => {
|
||||
const { queryByText, getByText } = render(
|
||||
<ConfirmModalProvider>
|
||||
<CallbackConfirmModalTestComponent />
|
||||
</ConfirmModalProvider>
|
||||
);
|
||||
|
||||
const trigger = getByText('show modal');
|
||||
|
||||
act(() => {
|
||||
fireEvent.click(trigger);
|
||||
});
|
||||
|
||||
await waitFor(() => {
|
||||
expect(queryByText('confirm modal content')).not.toBeNull();
|
||||
expect(queryByText('action.confirm')).not.toBeNull();
|
||||
expect(queryByText('action.cancel')).not.toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
it('confirm callback of confirm modal', async () => {
|
||||
const { queryByText, getByText } = render(
|
||||
<ConfirmModalProvider>
|
||||
<CallbackConfirmModalTestComponent />
|
||||
</ConfirmModalProvider>
|
||||
);
|
||||
|
||||
const trigger = getByText('show modal');
|
||||
|
||||
act(() => {
|
||||
fireEvent.click(trigger);
|
||||
});
|
||||
|
||||
await waitFor(() => {
|
||||
expect(queryByText('confirm modal content')).not.toBeNull();
|
||||
expect(queryByText('action.confirm')).not.toBeNull();
|
||||
});
|
||||
|
||||
const confirm = getByText('action.confirm');
|
||||
|
||||
act(() => {
|
||||
fireEvent.click(confirm);
|
||||
});
|
||||
|
||||
await waitFor(() => {
|
||||
expect(confirmHandler).toBeCalled();
|
||||
});
|
||||
});
|
||||
|
||||
it('cancel callback of confirm modal', async () => {
|
||||
const { queryByText, getByText } = render(
|
||||
<ConfirmModalProvider>
|
||||
<CallbackConfirmModalTestComponent />
|
||||
</ConfirmModalProvider>
|
||||
);
|
||||
|
||||
const trigger = getByText('show modal');
|
||||
|
||||
act(() => {
|
||||
fireEvent.click(trigger);
|
||||
});
|
||||
|
||||
await waitFor(() => {
|
||||
expect(queryByText('confirm modal content')).not.toBeNull();
|
||||
expect(queryByText('action.cancel')).not.toBeNull();
|
||||
});
|
||||
|
||||
const cancel = getByText('action.cancel');
|
||||
|
||||
act(() => {
|
||||
fireEvent.click(cancel);
|
||||
});
|
||||
|
||||
await waitFor(() => {
|
||||
expect(cancelHandler).toBeCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,71 @@
|
|||
@use '@/scss/underscore' as _;
|
||||
|
||||
|
||||
.overlay {
|
||||
z-index: 101;
|
||||
}
|
||||
|
||||
.modal {
|
||||
z-index: 101;
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.container {
|
||||
background: var(--color-bg-body);
|
||||
height: 100%;
|
||||
@include _.flex-column;
|
||||
align-items: stretch;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.modal,
|
||||
.container {
|
||||
&:focus-visible {
|
||||
outline: none;
|
||||
}
|
||||
}
|
||||
|
||||
.header {
|
||||
padding: _.unit(2) _.unit(5);
|
||||
}
|
||||
|
||||
.content {
|
||||
flex: 1;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.iframe {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border: none;
|
||||
background: var(--color-bg-body);
|
||||
opacity: 0%;
|
||||
transition: opacity 0.2s ease-in-out;
|
||||
|
||||
&.loaded {
|
||||
opacity: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.loader {
|
||||
background: var(--color-brand-default);
|
||||
}
|
||||
|
||||
/* stylelint-disable selector-class-pattern */
|
||||
:global {
|
||||
.ReactModal__Content[id='iframe-modal'] {
|
||||
transform: translateY(100%);
|
||||
transition: transform 0.3s ease-in-out;
|
||||
}
|
||||
|
||||
.ReactModal__Content--after-open[id='iframe-modal'] {
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
.ReactModal__Content--before-close[id='iframe-modal'] {
|
||||
transform: translateY(100%);
|
||||
}
|
||||
}
|
||||
/* stylelint-enable selector-class-pattern */
|
|
@ -0,0 +1,71 @@
|
|||
import classNames from 'classnames';
|
||||
import { useRef, useState } from 'react';
|
||||
import ReactModal from 'react-modal';
|
||||
import type { LoadingBarRef } from 'react-top-loading-bar';
|
||||
import LoadingBar from 'react-top-loading-bar';
|
||||
|
||||
import NavBar from '@/components/NavBar';
|
||||
|
||||
import styles from './index.module.scss';
|
||||
|
||||
type ModalProps = {
|
||||
readonly className?: string;
|
||||
readonly title?: string;
|
||||
readonly href?: string;
|
||||
readonly onClose: () => void;
|
||||
};
|
||||
|
||||
const IframeModal = ({ className, title = '', href = '', onClose }: ModalProps) => {
|
||||
const [isLoaded, setIsLoaded] = useState(false);
|
||||
const loadingBarRef = useRef<LoadingBarRef>(null);
|
||||
|
||||
const brandingColor = document.body.style.getPropertyValue('--color-brand-default') || '#5d34f2';
|
||||
|
||||
return (
|
||||
<ReactModal
|
||||
shouldCloseOnEsc
|
||||
id="iframe-modal"
|
||||
role="dialog"
|
||||
isOpen={Boolean(href)}
|
||||
className={classNames(styles.modal, className)}
|
||||
overlayClassName={styles.overlay}
|
||||
closeTimeoutMS={300}
|
||||
onAfterOpen={() => {
|
||||
loadingBarRef.current?.continuousStart();
|
||||
}}
|
||||
onRequestClose={onClose}
|
||||
>
|
||||
<div className={styles.container}>
|
||||
<div className={styles.header}>
|
||||
<NavBar type="close" title={title} onClose={onClose} />
|
||||
</div>
|
||||
<LoadingBar
|
||||
ref={loadingBarRef}
|
||||
containerStyle={{ position: 'relative' }}
|
||||
shadow={false}
|
||||
color={brandingColor}
|
||||
waitingTime={300}
|
||||
className={styles.loader}
|
||||
/>
|
||||
<div className={styles.content}>
|
||||
<iframe
|
||||
title={title}
|
||||
src={href}
|
||||
sandbox="allow-same-origin"
|
||||
className={classNames(styles.iframe, isLoaded && styles.loaded)}
|
||||
onLoad={() => {
|
||||
setIsLoaded(true);
|
||||
loadingBarRef.current?.complete();
|
||||
}}
|
||||
onError={() => {
|
||||
setIsLoaded(true);
|
||||
loadingBarRef.current?.complete();
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</ReactModal>
|
||||
);
|
||||
};
|
||||
|
||||
export default IframeModal;
|
|
@ -0,0 +1,55 @@
|
|||
import { noop } from '@silverhand/essentials';
|
||||
import { useState, useMemo, createContext, useContext } from 'react';
|
||||
|
||||
import usePlatform from '@/hooks/use-platform';
|
||||
|
||||
import IframeModal from './IframeModal';
|
||||
|
||||
type ModalState = {
|
||||
href?: string;
|
||||
title?: string;
|
||||
};
|
||||
|
||||
export const IframeModalContext = createContext<
|
||||
ModalState & { setModalState: (props: ModalState) => void }
|
||||
>({
|
||||
href: undefined,
|
||||
title: undefined,
|
||||
setModalState: noop,
|
||||
});
|
||||
|
||||
export const useIframeModal = () => useContext(IframeModalContext);
|
||||
|
||||
type Props = {
|
||||
readonly children: React.ReactNode;
|
||||
};
|
||||
|
||||
const IframeModalProvider = ({ children }: Props) => {
|
||||
const [modalState, setModalState] = useState<ModalState>();
|
||||
const { isMobile } = usePlatform();
|
||||
|
||||
const context = useMemo(
|
||||
() => ({
|
||||
...modalState,
|
||||
setModalState,
|
||||
}),
|
||||
[modalState]
|
||||
);
|
||||
|
||||
return (
|
||||
<IframeModalContext.Provider value={context}>
|
||||
{children}
|
||||
{isMobile && (
|
||||
<IframeModal
|
||||
href={modalState?.href}
|
||||
title={modalState?.title}
|
||||
onClose={() => {
|
||||
setModalState(undefined);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</IframeModalContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
export default IframeModalProvider;
|
|
@ -0,0 +1,18 @@
|
|||
import { useContext } from 'react';
|
||||
import { Outlet } from 'react-router-dom';
|
||||
|
||||
import PageContext from '@/Providers/PageContextProvider/PageContext';
|
||||
import LoadingMask from '@/components/LoadingMask';
|
||||
|
||||
const LoadingLayerProvider = () => {
|
||||
const { loading } = useContext(PageContext);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Outlet />
|
||||
{loading && <LoadingMask />}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default LoadingLayerProvider;
|
|
@ -0,0 +1,38 @@
|
|||
import { Theme } from '@logto/schemas';
|
||||
import { noop } from '@silverhand/essentials';
|
||||
import { createContext } from 'react';
|
||||
import { isMobile } from 'react-device-detect';
|
||||
|
||||
import type { SignInExperienceResponse, Platform } from '@/types';
|
||||
|
||||
export type PageContextType = {
|
||||
theme: Theme;
|
||||
toast: string;
|
||||
loading: boolean;
|
||||
platform: Platform;
|
||||
termsAgreement: boolean;
|
||||
experienceSettings: SignInExperienceResponse | undefined;
|
||||
isPreview: boolean;
|
||||
setTheme: React.Dispatch<React.SetStateAction<Theme>>;
|
||||
setToast: React.Dispatch<React.SetStateAction<string>>;
|
||||
setLoading: React.Dispatch<React.SetStateAction<boolean>>;
|
||||
setPlatform: React.Dispatch<React.SetStateAction<Platform>>;
|
||||
setTermsAgreement: React.Dispatch<React.SetStateAction<boolean>>;
|
||||
setExperienceSettings: React.Dispatch<React.SetStateAction<SignInExperienceResponse | undefined>>;
|
||||
};
|
||||
|
||||
export default createContext<PageContextType>({
|
||||
toast: '',
|
||||
theme: Theme.Light,
|
||||
loading: false,
|
||||
platform: isMobile ? 'mobile' : 'web',
|
||||
termsAgreement: false,
|
||||
experienceSettings: undefined,
|
||||
isPreview: false,
|
||||
setTheme: noop,
|
||||
setToast: noop,
|
||||
setLoading: noop,
|
||||
setPlatform: noop,
|
||||
setTermsAgreement: noop,
|
||||
setExperienceSettings: noop,
|
||||
});
|
|
@ -0,0 +1,66 @@
|
|||
import { Theme } from '@logto/schemas';
|
||||
import { useState, useMemo } from 'react';
|
||||
import { isMobile } from 'react-device-detect';
|
||||
import { useSearchParams } from 'react-router-dom';
|
||||
|
||||
import type { SignInExperienceResponse, Platform } from '@/types';
|
||||
|
||||
import type { PageContextType } from './PageContext';
|
||||
import MainContext from './PageContext';
|
||||
|
||||
type Props = {
|
||||
readonly children: React.ReactNode;
|
||||
readonly preset?: Partial<
|
||||
Pick<
|
||||
PageContextType,
|
||||
| 'theme'
|
||||
| 'toast'
|
||||
| 'loading'
|
||||
| 'platform'
|
||||
| 'termsAgreement'
|
||||
| 'experienceSettings'
|
||||
| 'isPreview'
|
||||
>
|
||||
>;
|
||||
};
|
||||
|
||||
const PageContextProvider = ({ children, preset }: Props) => {
|
||||
const [searchParameters] = useSearchParams();
|
||||
|
||||
const [loading, setLoading] = useState(preset?.loading ?? false);
|
||||
const [toast, setToast] = useState(preset?.toast ?? '');
|
||||
const [theme, setTheme] = useState<Theme>(preset?.theme ?? Theme.Light);
|
||||
|
||||
const [platform, setPlatform] = useState<Platform>(
|
||||
preset?.platform ?? (isMobile ? 'mobile' : 'web')
|
||||
);
|
||||
const [termsAgreement, setTermsAgreement] = useState(preset?.termsAgreement ?? false);
|
||||
const [experienceSettings, setExperienceSettings] = useState<
|
||||
SignInExperienceResponse | undefined
|
||||
>(preset?.experienceSettings ?? undefined);
|
||||
|
||||
const isPreview = searchParameters.get('preview') === 'true';
|
||||
|
||||
const pageContext = useMemo<PageContextType>(
|
||||
() => ({
|
||||
theme,
|
||||
toast,
|
||||
loading,
|
||||
platform,
|
||||
termsAgreement,
|
||||
experienceSettings,
|
||||
isPreview,
|
||||
setTheme,
|
||||
setLoading,
|
||||
setToast,
|
||||
setPlatform,
|
||||
setTermsAgreement,
|
||||
setExperienceSettings,
|
||||
}),
|
||||
[experienceSettings, isPreview, loading, platform, termsAgreement, theme, toast]
|
||||
);
|
||||
|
||||
return <MainContext.Provider value={pageContext}>{children}</MainContext.Provider>;
|
||||
};
|
||||
|
||||
export default PageContextProvider;
|
|
@ -0,0 +1,22 @@
|
|||
import { useContext, useMemo } from 'react';
|
||||
|
||||
import PageContext from '@/Providers/PageContextProvider/PageContext';
|
||||
|
||||
import usePreview from './use-preview';
|
||||
import useSignInExperience from './use-sign-in-experience';
|
||||
|
||||
type Props = {
|
||||
readonly children: React.ReactElement;
|
||||
};
|
||||
|
||||
const SettingsProvider = ({ children }: Props) => {
|
||||
const { isPreview, experienceSettings } = useContext(PageContext);
|
||||
|
||||
const usePageLoad = useMemo(() => (isPreview ? usePreview : useSignInExperience), [isPreview]);
|
||||
|
||||
usePageLoad();
|
||||
|
||||
return experienceSettings ? children : null;
|
||||
};
|
||||
|
||||
export default SettingsProvider;
|
|
@ -0,0 +1,83 @@
|
|||
import { ConnectorPlatform } from '@logto/schemas';
|
||||
import { useContext, useEffect, useState } from 'react';
|
||||
|
||||
import PageContext from '@/Providers/PageContextProvider/PageContext';
|
||||
import initI18n from '@/i18n/init';
|
||||
import { changeLanguage } from '@/i18n/utils';
|
||||
import type { PreviewConfig, SignInExperienceResponse } from '@/types';
|
||||
import { filterPreviewSocialConnectors } from '@/utils/social-connectors';
|
||||
|
||||
const usePreview = () => {
|
||||
const [previewConfig, setPreviewConfig] = useState<PreviewConfig>();
|
||||
const { setTheme, setPlatform, setExperienceSettings } = useContext(PageContext);
|
||||
|
||||
// Fetch the preview config
|
||||
useEffect(() => {
|
||||
// Listen to the message from the ancestor window
|
||||
const previewMessageHandler = async (event: MessageEvent) => {
|
||||
// #event.data should be guarded at the provider's side
|
||||
if (event.data.sender === 'ac_preview') {
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
const previewConfig = event.data.config as PreviewConfig;
|
||||
|
||||
// Wait for i18n to be initialized
|
||||
await initI18n(previewConfig.language);
|
||||
|
||||
setPreviewConfig(previewConfig);
|
||||
}
|
||||
};
|
||||
|
||||
window.addEventListener('message', previewMessageHandler);
|
||||
|
||||
return () => {
|
||||
window.removeEventListener('message', previewMessageHandler);
|
||||
};
|
||||
}, []);
|
||||
|
||||
// Set Experience settings
|
||||
useEffect(() => {
|
||||
if (!previewConfig) {
|
||||
return;
|
||||
}
|
||||
|
||||
const {
|
||||
signInExperience: { socialConnectors, ...rest },
|
||||
isNative,
|
||||
} = previewConfig;
|
||||
|
||||
const experienceSettings: SignInExperienceResponse = {
|
||||
...rest,
|
||||
socialConnectors: filterPreviewSocialConnectors(
|
||||
isNative ? ConnectorPlatform.Native : ConnectorPlatform.Web,
|
||||
socialConnectors
|
||||
),
|
||||
};
|
||||
|
||||
setExperienceSettings(experienceSettings);
|
||||
}, [previewConfig, setExperienceSettings]);
|
||||
|
||||
// Set Theme
|
||||
useEffect(() => {
|
||||
if (previewConfig?.mode) {
|
||||
setTheme(previewConfig.mode);
|
||||
}
|
||||
}, [previewConfig?.mode, setTheme]);
|
||||
|
||||
// Set Platform
|
||||
useEffect(() => {
|
||||
if (previewConfig?.platform) {
|
||||
setPlatform(previewConfig.platform);
|
||||
}
|
||||
}, [previewConfig?.platform, setPlatform]);
|
||||
|
||||
// Set Language
|
||||
useEffect(() => {
|
||||
if (previewConfig?.language) {
|
||||
(async () => {
|
||||
await changeLanguage(previewConfig.language);
|
||||
})();
|
||||
}
|
||||
}, [previewConfig?.language]);
|
||||
};
|
||||
|
||||
export default usePreview;
|
|
@ -0,0 +1,24 @@
|
|||
import { useContext, useEffect } from 'react';
|
||||
|
||||
import PageContext from '@/Providers/PageContextProvider/PageContext';
|
||||
import initI18n from '@/i18n/init';
|
||||
import { getSignInExperienceSettings } from '@/utils/sign-in-experience';
|
||||
|
||||
import useTheme from './use-theme';
|
||||
|
||||
const useSignInExperience = () => {
|
||||
const { isPreview, setExperienceSettings } = useContext(PageContext);
|
||||
|
||||
useTheme();
|
||||
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
const [settings] = await Promise.all([getSignInExperienceSettings(), initI18n()]);
|
||||
|
||||
// Init the page settings and render
|
||||
setExperienceSettings(settings);
|
||||
})();
|
||||
}, [isPreview, setExperienceSettings]);
|
||||
};
|
||||
|
||||
export default useSignInExperience;
|
|
@ -0,0 +1,30 @@
|
|||
import { Theme } from '@logto/schemas';
|
||||
import { useEffect, useContext } from 'react';
|
||||
|
||||
import PageContext from '@/Providers/PageContextProvider/PageContext';
|
||||
|
||||
const darkThemeWatchMedia = window.matchMedia('(prefers-color-scheme: dark)');
|
||||
const getThemeBySystemConfiguration = (): Theme =>
|
||||
darkThemeWatchMedia.matches ? Theme.Dark : Theme.Light;
|
||||
|
||||
export default function useTheme() {
|
||||
const { isPreview, experienceSettings, setTheme } = useContext(PageContext);
|
||||
|
||||
useEffect(() => {
|
||||
if (!experienceSettings?.color.isDarkModeEnabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
const changeTheme = () => {
|
||||
setTheme(getThemeBySystemConfiguration());
|
||||
};
|
||||
|
||||
changeTheme();
|
||||
|
||||
darkThemeWatchMedia.addEventListener('change', changeTheme);
|
||||
|
||||
return () => {
|
||||
darkThemeWatchMedia.removeEventListener('change', changeTheme);
|
||||
};
|
||||
}, [experienceSettings, isPreview, setTheme]);
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
import { noop } from '@silverhand/essentials';
|
||||
import { createContext } from 'react';
|
||||
|
||||
export type SingleSignOnFormModeContextType = {
|
||||
showSingleSignOnForm: boolean;
|
||||
setShowSingleSignOnForm: React.Dispatch<React.SetStateAction<boolean>>;
|
||||
};
|
||||
|
||||
/**
|
||||
* This context is used to share the single sign on identifier status cross the page and form components.
|
||||
* If the user has entered an identifier that is associated with a single sign on method, we will show the single sign on form.
|
||||
*/
|
||||
const SingleSignOnFormModeContext = createContext<SingleSignOnFormModeContextType>({
|
||||
showSingleSignOnForm: false,
|
||||
setShowSingleSignOnForm: noop,
|
||||
});
|
||||
|
||||
export default SingleSignOnFormModeContext;
|
|
@ -0,0 +1,23 @@
|
|||
import { useState, useMemo, type ReactNode } from 'react';
|
||||
|
||||
import SingleSignOnFormModeContext from './SingleSignOnFormModeContext';
|
||||
|
||||
const SingleSignOnFormModeContextProvider = ({ children }: { readonly children: ReactNode }) => {
|
||||
const [showSingleSignOnForm, setShowSingleSignOnForm] = useState<boolean>(false);
|
||||
|
||||
const contextValue = useMemo(
|
||||
() => ({
|
||||
showSingleSignOnForm,
|
||||
setShowSingleSignOnForm,
|
||||
}),
|
||||
[showSingleSignOnForm]
|
||||
);
|
||||
|
||||
return (
|
||||
<SingleSignOnFormModeContext.Provider value={contextValue}>
|
||||
{children}
|
||||
</SingleSignOnFormModeContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
export default SingleSignOnFormModeContextProvider;
|
|
@ -0,0 +1,27 @@
|
|||
import type { ReactNode } from 'react';
|
||||
import { useCallback, useContext } from 'react';
|
||||
|
||||
import PageContext from '@/Providers/PageContextProvider/PageContext';
|
||||
import Toast from '@/components/Toast';
|
||||
|
||||
type Props = {
|
||||
readonly children: ReactNode;
|
||||
};
|
||||
|
||||
const ToastProvider = ({ children }: Props) => {
|
||||
const { toast, setToast } = useContext(PageContext);
|
||||
|
||||
// Prevent internal eventListener rebind
|
||||
const hideToast = useCallback(() => {
|
||||
setToast('');
|
||||
}, [setToast]);
|
||||
|
||||
return (
|
||||
<>
|
||||
{children}
|
||||
<Toast message={toast} callback={hideToast} />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default ToastProvider;
|
|
@ -0,0 +1,58 @@
|
|||
import { type SsoConnectorMetadata } from '@logto/schemas';
|
||||
import { noop } from '@silverhand/essentials';
|
||||
import { createContext } from 'react';
|
||||
|
||||
import { type IdentifierInputValue } from '@/components/InputFields/SmartInputField';
|
||||
|
||||
export type UserInteractionContextType = {
|
||||
// All the enabled sso connectors
|
||||
availableSsoConnectorsMap: Map<string, SsoConnectorMetadata>;
|
||||
ssoEmail?: string;
|
||||
setSsoEmail: React.Dispatch<React.SetStateAction<string | undefined>>;
|
||||
// The sso connectors that are enabled for the current domain
|
||||
ssoConnectors: SsoConnectorMetadata[];
|
||||
setSsoConnectors: React.Dispatch<React.SetStateAction<SsoConnectorMetadata[]>>;
|
||||
/**
|
||||
* The cached identifier input value that the user has inputted.
|
||||
*/
|
||||
identifierInputValue?: IdentifierInputValue;
|
||||
/**
|
||||
* This method is used to cache the identifier input value.
|
||||
*/
|
||||
setIdentifierInputValue: React.Dispatch<React.SetStateAction<IdentifierInputValue | undefined>>;
|
||||
/**
|
||||
* The cached identifier input value that used in the 'ForgotPassword' flow.
|
||||
* The value will be used to pre-fill the identifier input field in the `ForgotPassword` page.
|
||||
*/
|
||||
forgotPasswordIdentifierInputValue?: IdentifierInputValue;
|
||||
/**
|
||||
* This method is used to cache the identifier input values for the 'ForgotPassword' flow.
|
||||
*/
|
||||
setForgotPasswordIdentifierInputValue: React.Dispatch<
|
||||
React.SetStateAction<IdentifierInputValue | undefined>
|
||||
>;
|
||||
/**
|
||||
* This method only clear the identifier input values from the session storage.
|
||||
*
|
||||
* The state of the identifier input values in the `UserInteractionContext` will
|
||||
* not be updated.
|
||||
*
|
||||
* Call this method after the user successfully signs in and before redirecting to
|
||||
* the application page to avoid triggering any side effects that depends on the
|
||||
* identifier input values.
|
||||
*/
|
||||
clearInteractionContextSessionStorage: () => void;
|
||||
};
|
||||
|
||||
export default createContext<UserInteractionContextType>({
|
||||
ssoEmail: undefined,
|
||||
availableSsoConnectorsMap: new Map(),
|
||||
ssoConnectors: [],
|
||||
setSsoEmail: noop,
|
||||
setSsoConnectors: noop,
|
||||
identifierInputValue: undefined,
|
||||
setIdentifierInputValue: noop,
|
||||
forgotPasswordIdentifierInputValue: undefined,
|
||||
setForgotPasswordIdentifierInputValue: noop,
|
||||
clearInteractionContextSessionStorage: noop,
|
||||
});
|
|
@ -0,0 +1,114 @@
|
|||
import { type SsoConnectorMetadata } from '@logto/schemas';
|
||||
import { type ReactNode, useEffect, useMemo, useState, useCallback } from 'react';
|
||||
|
||||
import { type IdentifierInputValue } from '@/components/InputFields/SmartInputField';
|
||||
import useSessionStorage, { StorageKeys } from '@/hooks/use-session-storages';
|
||||
import { useSieMethods } from '@/hooks/use-sie';
|
||||
|
||||
import UserInteractionContext, { type UserInteractionContextType } from './UserInteractionContext';
|
||||
|
||||
type Props = {
|
||||
readonly children: ReactNode;
|
||||
};
|
||||
|
||||
/**
|
||||
* UserInteractionContextProvider
|
||||
*
|
||||
* This component manages user interaction data during the sign-in process,
|
||||
* combining React's Context API with session storage to enable cross-page
|
||||
* data persistence and access.
|
||||
*
|
||||
* The cached data provided by this provider primarily helps improve the sign-in experience for end users.
|
||||
*/
|
||||
const UserInteractionContextProvider = ({ children }: Props) => {
|
||||
const { ssoConnectors } = useSieMethods();
|
||||
const { get, set, remove } = useSessionStorage();
|
||||
const [ssoEmail, setSsoEmail] = useState<string | undefined>(get(StorageKeys.SsoEmail));
|
||||
const [domainFilteredConnectors, setDomainFilteredConnectors] = useState<SsoConnectorMetadata[]>(
|
||||
get(StorageKeys.SsoConnectors) ?? []
|
||||
);
|
||||
const [identifierInputValue, setIdentifierInputValue] = useState<
|
||||
IdentifierInputValue | undefined
|
||||
>(get(StorageKeys.IdentifierInputValue));
|
||||
|
||||
const [forgotPasswordIdentifierInputValue, setForgotPasswordIdentifierInputValue] = useState<
|
||||
IdentifierInputValue | undefined
|
||||
>(get(StorageKeys.ForgotPasswordIdentifierInputValue));
|
||||
|
||||
useEffect(() => {
|
||||
if (!ssoEmail) {
|
||||
remove(StorageKeys.SsoEmail);
|
||||
return;
|
||||
}
|
||||
|
||||
set(StorageKeys.SsoEmail, ssoEmail);
|
||||
}, [ssoEmail, remove, set]);
|
||||
|
||||
useEffect(() => {
|
||||
if (domainFilteredConnectors.length === 0) {
|
||||
remove(StorageKeys.SsoConnectors);
|
||||
return;
|
||||
}
|
||||
|
||||
set(StorageKeys.SsoConnectors, domainFilteredConnectors);
|
||||
}, [domainFilteredConnectors, remove, set]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!identifierInputValue) {
|
||||
remove(StorageKeys.IdentifierInputValue);
|
||||
return;
|
||||
}
|
||||
|
||||
set(StorageKeys.IdentifierInputValue, identifierInputValue);
|
||||
}, [identifierInputValue, remove, set]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!forgotPasswordIdentifierInputValue) {
|
||||
remove(StorageKeys.ForgotPasswordIdentifierInputValue);
|
||||
return;
|
||||
}
|
||||
|
||||
set(StorageKeys.ForgotPasswordIdentifierInputValue, forgotPasswordIdentifierInputValue);
|
||||
}, [forgotPasswordIdentifierInputValue, remove, set]);
|
||||
|
||||
const ssoConnectorsMap = useMemo(
|
||||
() => new Map(ssoConnectors.map((connector) => [connector.id, connector])),
|
||||
[ssoConnectors]
|
||||
);
|
||||
|
||||
const clearInteractionContextSessionStorage = useCallback(() => {
|
||||
remove(StorageKeys.IdentifierInputValue);
|
||||
remove(StorageKeys.ForgotPasswordIdentifierInputValue);
|
||||
}, [remove]);
|
||||
|
||||
const userInteractionContext = useMemo<UserInteractionContextType>(
|
||||
() => ({
|
||||
ssoEmail,
|
||||
setSsoEmail,
|
||||
availableSsoConnectorsMap: ssoConnectorsMap,
|
||||
ssoConnectors: domainFilteredConnectors,
|
||||
setSsoConnectors: setDomainFilteredConnectors,
|
||||
identifierInputValue,
|
||||
setIdentifierInputValue,
|
||||
forgotPasswordIdentifierInputValue,
|
||||
setForgotPasswordIdentifierInputValue,
|
||||
clearInteractionContextSessionStorage,
|
||||
}),
|
||||
[
|
||||
ssoEmail,
|
||||
ssoConnectorsMap,
|
||||
domainFilteredConnectors,
|
||||
identifierInputValue,
|
||||
forgotPasswordIdentifierInputValue,
|
||||
clearInteractionContextSessionStorage,
|
||||
]
|
||||
);
|
||||
|
||||
return (
|
||||
<UserInteractionContext.Provider value={userInteractionContext}>
|
||||
{children}
|
||||
</UserInteractionContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
export default UserInteractionContextProvider;
|
|
@ -0,0 +1,29 @@
|
|||
import type { ReactElement } from 'react';
|
||||
import { useContext, useEffect } from 'react';
|
||||
|
||||
import PageContext from '@/Providers/PageContextProvider/PageContext';
|
||||
import type { SignInExperienceResponse } from '@/types';
|
||||
|
||||
import { mockSignInExperienceSettings } from '../logto';
|
||||
|
||||
type Props = {
|
||||
readonly settings?: SignInExperienceResponse;
|
||||
readonly children: ReactElement;
|
||||
};
|
||||
|
||||
const SettingsProvider = ({ settings = mockSignInExperienceSettings, children }: Props) => {
|
||||
const { setExperienceSettings, experienceSettings } = useContext(PageContext);
|
||||
|
||||
useEffect(() => {
|
||||
setExperienceSettings(settings);
|
||||
}, [setExperienceSettings, settings]);
|
||||
|
||||
// Don't render children until the settings are set to avoid false positives
|
||||
if (!experienceSettings) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return children;
|
||||
};
|
||||
|
||||
export default SettingsProvider;
|
|
@ -0,0 +1,24 @@
|
|||
import type { Queries, queries, RenderOptions } from '@testing-library/react';
|
||||
import { render } from '@testing-library/react';
|
||||
import type { ReactElement } from 'react';
|
||||
import { MemoryRouter } from 'react-router-dom';
|
||||
|
||||
import PageContextProvider from '@/Providers/PageContextProvider';
|
||||
|
||||
const renderWithPageContext = <
|
||||
Q extends Queries = typeof queries,
|
||||
Container extends Element | DocumentFragment = HTMLElement,
|
||||
>(
|
||||
ui: ReactElement,
|
||||
memoryRouterProps: Parameters<typeof MemoryRouter>[0] = {},
|
||||
options: RenderOptions<Q, Container> = {}
|
||||
) => {
|
||||
return render<Q, Container>(
|
||||
<MemoryRouter {...memoryRouterProps}>
|
||||
<PageContextProvider>{ui}</PageContextProvider>
|
||||
</MemoryRouter>,
|
||||
options
|
||||
);
|
||||
};
|
||||
|
||||
export default renderWithPageContext;
|
221
packages/experience-legacy/src/__mocks__/logto.tsx
Normal file
|
@ -0,0 +1,221 @@
|
|||
import type { SignInExperience, SignIn, SsoConnectorMetadata } from '@logto/schemas';
|
||||
import {
|
||||
AgreeToTermsPolicy,
|
||||
ConnectorPlatform,
|
||||
ConnectorType,
|
||||
MfaPolicy,
|
||||
SignInIdentifier,
|
||||
SignInMode,
|
||||
} from '@logto/schemas';
|
||||
|
||||
import type { SignInExperienceResponse } from '@/types';
|
||||
|
||||
import { socialConnectors } from './social-connectors';
|
||||
|
||||
export * from './social-connectors';
|
||||
|
||||
export const appLogo = 'https://avatars.githubusercontent.com/u/88327661?s=200&v=4';
|
||||
export const appHeadline = 'Build user identity in a modern way';
|
||||
|
||||
export const mockSocialConnectorData = {
|
||||
id: 'arbitrary-social-connector-data',
|
||||
target: 'google',
|
||||
platform: ConnectorPlatform.Web,
|
||||
type: ConnectorType.Social,
|
||||
logo: 'http://logto.dev/logto.png',
|
||||
logoDark: null,
|
||||
name: {
|
||||
en: 'Sign in with Xxx',
|
||||
'pt-PT': 'Entrar com Xxx',
|
||||
'zh-CN': '使用 Xxx 登录',
|
||||
'tr-TR': 'Xxx ile giriş yap',
|
||||
ko: 'Xxx 로그인',
|
||||
},
|
||||
description: {
|
||||
en: 'Sign in with Xxx',
|
||||
'pt-PT': 'Entrar com Xxx',
|
||||
'zh-CN': '使用 Xxx 登录',
|
||||
'tr-TR': 'Xxx ile giriş yap',
|
||||
ko: 'Xxx 로그인',
|
||||
},
|
||||
readme: '',
|
||||
configTemplate: '',
|
||||
};
|
||||
|
||||
export const mockSsoConnectors: SsoConnectorMetadata[] = [
|
||||
{
|
||||
id: 'arbitrary-sso-connector',
|
||||
connectorName: 'AzureAD',
|
||||
logo: 'http://logto.dev/logto.png',
|
||||
},
|
||||
{
|
||||
id: 'Google-sso-connector',
|
||||
connectorName: 'Google',
|
||||
logo: 'http://logto.dev/logto.png',
|
||||
},
|
||||
];
|
||||
|
||||
export const emailSignInMethod = {
|
||||
identifier: SignInIdentifier.Email,
|
||||
password: true,
|
||||
verificationCode: true,
|
||||
isPasswordPrimary: true,
|
||||
};
|
||||
|
||||
export const phoneSignInMethod = {
|
||||
identifier: SignInIdentifier.Phone,
|
||||
password: true,
|
||||
verificationCode: true,
|
||||
isPasswordPrimary: true,
|
||||
};
|
||||
|
||||
export const usernameSignInMethod = {
|
||||
identifier: SignInIdentifier.Username,
|
||||
password: true,
|
||||
verificationCode: false,
|
||||
isPasswordPrimary: true,
|
||||
};
|
||||
|
||||
export const mockSignInExperience: SignInExperience = {
|
||||
tenantId: 'default',
|
||||
id: 'foo',
|
||||
color: {
|
||||
primaryColor: '#000',
|
||||
isDarkModeEnabled: true,
|
||||
darkPrimaryColor: '#fff',
|
||||
},
|
||||
branding: {
|
||||
logoUrl: 'http://logto.png',
|
||||
},
|
||||
termsOfUseUrl: 'http://terms.of.use/',
|
||||
privacyPolicyUrl: 'http://privacy.policy/',
|
||||
languageInfo: {
|
||||
autoDetect: true,
|
||||
fallbackLanguage: 'en',
|
||||
},
|
||||
signUp: {
|
||||
identifiers: [SignInIdentifier.Username],
|
||||
password: true,
|
||||
verify: true,
|
||||
},
|
||||
signIn: {
|
||||
methods: [usernameSignInMethod, emailSignInMethod, phoneSignInMethod],
|
||||
},
|
||||
socialSignInConnectorTargets: ['BE8QXN0VsrOH7xdWFDJZ9', 'lcXT4o2GSjbV9kg2shZC7'],
|
||||
signInMode: SignInMode.SignInAndRegister,
|
||||
customCss: null,
|
||||
customContent: {},
|
||||
agreeToTermsPolicy: AgreeToTermsPolicy.ManualRegistrationOnly,
|
||||
customUiAssets: null,
|
||||
passwordPolicy: {},
|
||||
mfa: {
|
||||
policy: MfaPolicy.UserControlled,
|
||||
factors: [],
|
||||
},
|
||||
singleSignOnEnabled: true,
|
||||
socialSignIn: {},
|
||||
};
|
||||
|
||||
export const mockSignInExperienceSettings: SignInExperienceResponse = {
|
||||
tenantId: 'default',
|
||||
id: mockSignInExperience.id,
|
||||
color: mockSignInExperience.color,
|
||||
branding: mockSignInExperience.branding,
|
||||
termsOfUseUrl: mockSignInExperience.termsOfUseUrl,
|
||||
privacyPolicyUrl: mockSignInExperience.privacyPolicyUrl,
|
||||
languageInfo: mockSignInExperience.languageInfo,
|
||||
signIn: mockSignInExperience.signIn,
|
||||
signUp: {
|
||||
identifiers: [SignInIdentifier.Username],
|
||||
password: true,
|
||||
verify: true,
|
||||
},
|
||||
socialConnectors,
|
||||
ssoConnectors: [],
|
||||
signInMode: SignInMode.SignInAndRegister,
|
||||
forgotPassword: {
|
||||
email: true,
|
||||
phone: true,
|
||||
},
|
||||
customCss: null,
|
||||
customContent: {},
|
||||
agreeToTermsPolicy: mockSignInExperience.agreeToTermsPolicy,
|
||||
customUiAssets: null,
|
||||
passwordPolicy: {},
|
||||
mfa: {
|
||||
policy: MfaPolicy.UserControlled,
|
||||
factors: [],
|
||||
},
|
||||
isDevelopmentTenant: false,
|
||||
singleSignOnEnabled: true,
|
||||
socialSignIn: {},
|
||||
};
|
||||
|
||||
const usernameSettings = {
|
||||
identifier: SignInIdentifier.Username,
|
||||
password: true,
|
||||
verificationCode: false,
|
||||
isPasswordPrimary: true,
|
||||
};
|
||||
|
||||
export const mockSignInMethodSettingsTestCases: Array<SignIn['methods']> = [
|
||||
[
|
||||
usernameSettings,
|
||||
{
|
||||
identifier: SignInIdentifier.Email,
|
||||
password: true,
|
||||
verificationCode: true,
|
||||
isPasswordPrimary: true,
|
||||
},
|
||||
{
|
||||
identifier: SignInIdentifier.Phone,
|
||||
password: true,
|
||||
verificationCode: true,
|
||||
isPasswordPrimary: true,
|
||||
},
|
||||
],
|
||||
[
|
||||
usernameSettings,
|
||||
{
|
||||
identifier: SignInIdentifier.Email,
|
||||
password: true,
|
||||
verificationCode: true,
|
||||
isPasswordPrimary: false,
|
||||
},
|
||||
{
|
||||
identifier: SignInIdentifier.Phone,
|
||||
password: true,
|
||||
verificationCode: false,
|
||||
isPasswordPrimary: false,
|
||||
},
|
||||
],
|
||||
[
|
||||
usernameSettings,
|
||||
{
|
||||
identifier: SignInIdentifier.Email,
|
||||
password: false,
|
||||
verificationCode: true,
|
||||
isPasswordPrimary: false,
|
||||
},
|
||||
{
|
||||
identifier: SignInIdentifier.Phone,
|
||||
password: false,
|
||||
verificationCode: true,
|
||||
isPasswordPrimary: false,
|
||||
},
|
||||
],
|
||||
];
|
||||
|
||||
export const getBoundingClientRectMock = (mock: Partial<DOMRect>) =>
|
||||
jest.fn(() => ({
|
||||
width: 0,
|
||||
height: 0,
|
||||
x: 0,
|
||||
y: 0,
|
||||
top: 0,
|
||||
bottom: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
...mock,
|
||||
toJSON: jest.fn(),
|
||||
}));
|
124
packages/experience-legacy/src/__mocks__/social-connectors.tsx
Normal file
|
@ -0,0 +1,124 @@
|
|||
import { ConnectorPlatform, ConnectorType } from '@logto/connector-kit';
|
||||
|
||||
export const socialConnectors = [
|
||||
{
|
||||
id: 'BE8QXN0VsrOH7xdWFDJZ9',
|
||||
target: 'github',
|
||||
platform: ConnectorPlatform.Web,
|
||||
type: ConnectorType.Social,
|
||||
logo: 'https://user-images.githubusercontent.com/5717882/156983224-7ea0296b-38fa-419d-9515-67e8a9612e09.png',
|
||||
logoDark: null,
|
||||
name: {
|
||||
en: 'Sign in with GitHub',
|
||||
'pt-PT': 'Entrar com GitHub',
|
||||
'zh-CN': '使用 GitHub 登录',
|
||||
'tr-TR': 'Github ile giriş yap',
|
||||
ko: 'Github 로그인',
|
||||
},
|
||||
description: {
|
||||
en: 'Sign in with GitHub',
|
||||
'pt-PT': 'Entrar com GitHub',
|
||||
'zh-CN': '使用 GitHub 登录',
|
||||
'tr-TR': 'Github ile giriş yap',
|
||||
ko: 'Github 로그인',
|
||||
},
|
||||
readme: '',
|
||||
configTemplate: '',
|
||||
},
|
||||
{
|
||||
id: '24yt_xIUl5btN4UwvFokt',
|
||||
target: 'alipay',
|
||||
platform: ConnectorPlatform.Web,
|
||||
type: ConnectorType.Social,
|
||||
logo: 'https://user-images.githubusercontent.com/5717882/156983224-7ea0296b-38fa-419d-9515-67e8a9612e09.png',
|
||||
logoDark: null,
|
||||
name: {
|
||||
en: 'Sign in with Alipay',
|
||||
'pt-PT': 'Entrar com Alipay',
|
||||
'zh-CN': '使用 Alipay 登录',
|
||||
'tr-TR': 'Alipay ile giriş yap',
|
||||
ko: 'Alipay 로그인',
|
||||
},
|
||||
description: {
|
||||
en: 'Sign in with Alipay',
|
||||
'pt-PT': 'Entrar com Alipay',
|
||||
'zh-CN': '使用 Alipay 登录',
|
||||
'tr-TR': 'Alipay ile giriş yap',
|
||||
ko: 'Alipay 로그인',
|
||||
},
|
||||
readme: '',
|
||||
configTemplate: '',
|
||||
},
|
||||
{
|
||||
id: 'E5kb2gdq769qOEYaLg1V5',
|
||||
target: 'wechat',
|
||||
platform: ConnectorPlatform.Web,
|
||||
type: ConnectorType.Social,
|
||||
logo: 'https://user-images.githubusercontent.com/5717882/156983224-7ea0296b-38fa-419d-9515-67e8a9612e09.png',
|
||||
logoDark: null,
|
||||
name: {
|
||||
en: 'Sign in with WeChat',
|
||||
'pt-PT': 'Entrar com WeChat',
|
||||
'zh-CN': '使用 WeChat 登录',
|
||||
'tr-TR': 'WeChat ile giriş yap',
|
||||
ko: 'WeChat 로그인',
|
||||
},
|
||||
description: {
|
||||
en: 'Sign in with WeChat',
|
||||
'pt-PT': 'Entrar com WeChat',
|
||||
'zh-CN': '使用 WeChat 登录',
|
||||
'tr-TR': 'WeChat ile giriş yap',
|
||||
ko: 'WeChat 로그인',
|
||||
},
|
||||
readme: '',
|
||||
configTemplate: '',
|
||||
},
|
||||
{
|
||||
id: 'xY2YZEweMFPKxphngGHhy',
|
||||
target: 'google',
|
||||
platform: ConnectorPlatform.Web,
|
||||
type: ConnectorType.Social,
|
||||
logo: 'https://user-images.githubusercontent.com/5717882/156983224-7ea0296b-38fa-419d-9515-67e8a9612e09.png',
|
||||
logoDark: null,
|
||||
name: {
|
||||
en: 'Sign in with Google',
|
||||
'pt-PT': 'Entrar com Google',
|
||||
'zh-CN': '使用 Google 登录',
|
||||
'tr-TR': 'Google ile giriş yap',
|
||||
ko: 'Google 로그인',
|
||||
},
|
||||
description: {
|
||||
en: 'Sign in with Google',
|
||||
'pt-PT': 'Entrar com Google',
|
||||
'zh-CN': '使用 Google 登录',
|
||||
'tr-TR': 'Google ile giriş yap',
|
||||
ko: 'Google 로그인',
|
||||
},
|
||||
readme: '',
|
||||
configTemplate: '',
|
||||
},
|
||||
{
|
||||
id: 'lcXT4o2GSjbV9kg2shZC7',
|
||||
target: 'facebook',
|
||||
platform: ConnectorPlatform.Web,
|
||||
type: ConnectorType.Social,
|
||||
logo: 'https://user-images.githubusercontent.com/5717882/156983224-7ea0296b-38fa-419d-9515-67e8a9612e09.png',
|
||||
logoDark: null,
|
||||
name: {
|
||||
en: 'Sign in with Meta',
|
||||
'pt-PT': 'Entrar com Facebook',
|
||||
'zh-CN': '使用 Meta 登录',
|
||||
'tr-TR': 'Meta ile giriş yap',
|
||||
ko: 'Meta 로그인',
|
||||
},
|
||||
description: {
|
||||
en: 'Sign in with Meta',
|
||||
'pt-PT': 'Entrar com Facebook',
|
||||
'zh-CN': '使用 Meta 登录',
|
||||
'tr-TR': 'Meta ile giriş yap',
|
||||
ko: 'Meta 로그인',
|
||||
},
|
||||
readme: '',
|
||||
configTemplate: '',
|
||||
},
|
||||
];
|
12
packages/experience-legacy/src/apis/api.ts
Normal file
|
@ -0,0 +1,12 @@
|
|||
import i18next from 'i18next';
|
||||
import ky from 'ky';
|
||||
|
||||
export default ky.extend({
|
||||
hooks: {
|
||||
beforeRequest: [
|
||||
(request) => {
|
||||
request.headers.set('Accept-Language', i18next.language);
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
21
packages/experience-legacy/src/apis/consent.ts
Normal file
|
@ -0,0 +1,21 @@
|
|||
import { type ConsentInfoResponse } from '@logto/schemas';
|
||||
|
||||
import api from './api';
|
||||
|
||||
export const consent = async (organizationId?: string) => {
|
||||
type Response = {
|
||||
redirectTo: string;
|
||||
};
|
||||
|
||||
return api
|
||||
.post('/api/interaction/consent', {
|
||||
json: {
|
||||
organizationIds: organizationId && [organizationId],
|
||||
},
|
||||
})
|
||||
.json<Response>();
|
||||
};
|
||||
|
||||
export const getConsentInfo = async () => {
|
||||
return api.get('/api/interaction/consent').json<ConsentInfoResponse>();
|
||||
};
|
63
packages/experience-legacy/src/apis/settings.ts
Normal file
|
@ -0,0 +1,63 @@
|
|||
/**
|
||||
* Used to get and general sign-in experience settings.
|
||||
* The API will be deprecated in the future once SSR is implemented.
|
||||
*/
|
||||
|
||||
import type { Nullable, Optional } from '@silverhand/essentials';
|
||||
import { conditional } from '@silverhand/essentials';
|
||||
import ky from 'ky';
|
||||
|
||||
import type { SignInExperienceResponse } from '@/types';
|
||||
import { searchKeys } from '@/utils/search-parameters';
|
||||
|
||||
const buildSearchParameters = (record: Record<string, Nullable<Optional<string>>>) => {
|
||||
const entries = Object.entries(record).filter((entry): entry is [string, string] =>
|
||||
Boolean(entry[0] && entry[1])
|
||||
);
|
||||
|
||||
return conditional(entries.length > 0 && entries);
|
||||
};
|
||||
|
||||
// A simple camelCase utility to prevent the need to add a dependency.
|
||||
const camelCase = (string: string): string =>
|
||||
string.replaceAll(
|
||||
/_([^_])([^_]*)/g,
|
||||
(_, letter: string, rest: string) => letter.toUpperCase() + rest.toLowerCase()
|
||||
);
|
||||
|
||||
export const getSignInExperience = async <T extends SignInExperienceResponse>(): Promise<T> => {
|
||||
return ky
|
||||
.get('/api/.well-known/sign-in-exp', {
|
||||
searchParams: buildSearchParameters(
|
||||
Object.fromEntries(
|
||||
Object.values(searchKeys).map((key) => [camelCase(key), sessionStorage.getItem(key)])
|
||||
)
|
||||
),
|
||||
})
|
||||
.json<T>();
|
||||
};
|
||||
|
||||
export const getPhrases = async ({
|
||||
localLanguage,
|
||||
language,
|
||||
}: {
|
||||
localLanguage?: string;
|
||||
language?: string;
|
||||
}) =>
|
||||
ky
|
||||
.extend({
|
||||
hooks: {
|
||||
beforeRequest: [
|
||||
(request) => {
|
||||
if (localLanguage) {
|
||||
request.headers.set('Accept-Language', localLanguage);
|
||||
}
|
||||
},
|
||||
],
|
||||
},
|
||||
})
|
||||
.get('/api/.well-known/phrases', {
|
||||
searchParams: buildSearchParameters({
|
||||
lng: language,
|
||||
}),
|
||||
});
|
26
packages/experience-legacy/src/apis/utils.ts
Normal file
|
@ -0,0 +1,26 @@
|
|||
import { InteractionEvent } from '@logto/schemas';
|
||||
|
||||
import { UserFlow } from '@/types';
|
||||
|
||||
import type { SendVerificationCodePayload } from './interaction';
|
||||
import { putInteraction, sendVerificationCode } from './interaction';
|
||||
|
||||
/** Move to API */
|
||||
export const sendVerificationCodeApi = async (
|
||||
type: UserFlow,
|
||||
payload: SendVerificationCodePayload
|
||||
) => {
|
||||
if (type === UserFlow.ForgotPassword) {
|
||||
await putInteraction(InteractionEvent.ForgotPassword);
|
||||
}
|
||||
|
||||
if (type === UserFlow.SignIn) {
|
||||
await putInteraction(InteractionEvent.SignIn);
|
||||
}
|
||||
|
||||
if (type === UserFlow.Register) {
|
||||
await putInteraction(InteractionEvent.Register);
|
||||
}
|
||||
|
||||
return sendVerificationCode(payload);
|
||||
};
|
BIN
packages/experience-legacy/src/assets/apple-touch-icon.png
Normal file
After Width: | Height: | Size: 82 KiB |
BIN
packages/experience-legacy/src/assets/favicon.png
Normal file
After Width: | Height: | Size: 592 B |
|
@ -0,0 +1,3 @@
|
|||
<svg viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M10.5916 12.9499L15.2999 8.23328C15.378 8.15581 15.44 8.06364 15.4823 7.96209C15.5246 7.86054 15.5464 7.75162 15.5464 7.64161C15.5464 7.5316 15.5246 7.42268 15.4823 7.32113C15.44 7.21958 15.378 7.12741 15.2999 7.04994C15.1438 6.89474 14.9325 6.80762 14.7124 6.80762C14.4922 6.80762 14.281 6.89474 14.1249 7.04994L9.95822 11.1749L5.83322 7.04994C5.67709 6.89474 5.46588 6.80762 5.24572 6.80762C5.02557 6.80762 4.81436 6.89474 4.65822 7.04994C4.57948 7.12712 4.51684 7.21916 4.47393 7.32072C4.43101 7.42229 4.40868 7.53136 4.40822 7.64161C4.40868 7.75187 4.43101 7.86094 4.47393 7.9625C4.51684 8.06406 4.57948 8.1561 4.65822 8.23328L9.36655 12.9499C9.44459 13.0345 9.5393 13.102 9.64472 13.1482C9.75013 13.1944 9.86397 13.2182 9.97905 13.2182C10.0941 13.2182 10.208 13.1944 10.3134 13.1482C10.4188 13.102 10.5135 13.0345 10.5916 12.9499Z" fill="currentcolor"/>
|
||||
</svg>
|
After Width: | Height: | Size: 939 B |
|
@ -0,0 +1,3 @@
|
|||
<svg width="22" height="22" viewBox="0 0 22 22" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M14.2448 10.3488L9.05651 5.16959C8.97129 5.08367 8.86991 5.01547 8.7582 4.96894C8.6465 4.9224 8.52669 4.89844 8.40567 4.89844C8.28466 4.89844 8.16485 4.9224 8.05315 4.96894C7.94144 5.01547 7.84006 5.08367 7.75484 5.16959C7.58411 5.34133 7.48828 5.57367 7.48828 5.81584C7.48828 6.05801 7.58411 6.29034 7.75484 6.46209L12.2923 11.0454L7.75484 15.5829C7.58411 15.7547 7.48828 15.987 7.48828 16.2292C7.48828 16.4713 7.58411 16.7037 7.75484 16.8754C7.83974 16.962 7.94098 17.0309 8.0527 17.0781C8.16442 17.1253 8.28439 17.1499 8.40567 17.1504C8.52696 17.1499 8.64693 17.1253 8.75865 17.0781C8.87037 17.0309 8.97161 16.962 9.05651 16.8754L14.2448 11.6963C14.3379 11.6104 14.4121 11.5062 14.4629 11.3903C14.5137 11.2743 14.5399 11.1491 14.5399 11.0225C14.5399 10.8959 14.5137 10.7707 14.4629 10.6547C14.4121 10.5388 14.3379 10.4346 14.2448 10.3488Z" fill="currentcolor"/>
|
||||
</svg>
|
After Width: | Height: | Size: 977 B |
|
@ -0,0 +1,3 @@
|
|||
<svg width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M8.49054 12.7642L14.1505 18.4142C14.2435 18.5079 14.3541 18.5823 14.476 18.6331C14.5978 18.6838 14.7285 18.71 14.8605 18.71C14.9925 18.71 15.1233 18.6838 15.2451 18.6331C15.367 18.5823 15.4776 18.5079 15.5705 18.4142C15.7568 18.2268 15.8613 17.9733 15.8613 17.7092C15.8613 17.445 15.7568 17.1915 15.5705 17.0042L10.6205 12.0042L15.5705 7.05416C15.7568 6.8668 15.8613 6.61335 15.8613 6.34916C15.8613 6.08498 15.7568 5.83153 15.5705 5.64416C15.4779 5.54967 15.3675 5.4745 15.2456 5.42301C15.1237 5.37151 14.9928 5.34471 14.8605 5.34416C14.7282 5.34471 14.5973 5.37151 14.4755 5.42301C14.3536 5.4745 14.2432 5.54967 14.1505 5.64416L8.49054 11.2942C8.38903 11.3878 8.30802 11.5015 8.25261 11.628C8.19721 11.7545 8.1686 11.8911 8.1686 12.0292C8.1686 12.1673 8.19721 12.3039 8.25261 12.4304C8.30802 12.5569 8.38903 12.6705 8.49054 12.7642Z" fill="currentcolor"/>
|
||||
</svg>
|
After Width: | Height: | Size: 959 B |
|
@ -0,0 +1,3 @@
|
|||
<svg width="20" height="21" viewBox="0 0 20 21" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M15.5837 6.5C15.2503 6.16667 14.7503 6.16667 14.417 6.5L8.16699 12.75L5.58366 10.1667C5.25033 9.83333 4.75033 9.83333 4.41699 10.1667C4.08366 10.5 4.08366 11 4.41699 11.3333L7.58366 14.5C7.75033 14.6667 7.91699 14.75 8.16699 14.75C8.41699 14.75 8.58366 14.6667 8.75033 14.5L15.5837 7.66667C15.917 7.33333 15.917 6.83333 15.5837 6.5Z" fill="currentcolor"/>
|
||||
</svg>
|
After Width: | Height: | Size: 468 B |
|
@ -0,0 +1,5 @@
|
|||
<svg viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M14.2463 2.20996H3.75244C2.90015 2.20996 2.20923 2.90088 2.20923 3.75317V14.247C2.20923 15.0993 2.90015 15.7902 3.75244 15.7902H14.2463C15.0986 15.7902 15.7895 15.0993 15.7895 14.247V3.75317C15.7895 2.90088 15.0986 2.20996 14.2463 2.20996ZM3.75244 0.666748C2.04785 0.666748 0.666016 2.04859 0.666016 3.75317V14.247C0.666016 15.9516 2.04786 17.3334 3.75244 17.3334H14.2463C15.9508 17.3334 17.3327 15.9516 17.3327 14.247V3.75317C17.3327 2.04859 15.9508 0.666748 14.2463 0.666748H3.75244Z" fill="currentcolor"/>
|
||||
<rect width="18" height="18" rx="4" fill="currentcolor"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M7.31476 12.858L4.13295 9.441C3.95568 9.253 3.95568 8.947 4.13295 8.757L4.77568 8.074C4.95295 7.886 5.24113 7.886 5.4184 8.074L7.63657 10.466L12.5811 5.141C12.7584 4.953 13.0465 4.953 13.2238 5.141L13.8665 5.825C14.0438 6.013 14.0438 6.32 13.8665 6.507L7.95748 12.858C7.78021 13.046 7.49203 13.046 7.31476 12.858Z" fill="white"/>
|
||||
</svg>
|
After Width: | Height: | Size: 1.1 KiB |
|
@ -0,0 +1,4 @@
|
|||
<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M12 21C16.9706 21 21 16.9706 21 12C21 7.02944 16.9706 3 12 3C7.02944 3 3 7.02944 3 12C3 16.9706 7.02944 21 12 21ZM8.46447 9.87868C8.07394 9.48816 8.07394 8.85499 8.46447 8.46447C8.85499 8.07394 9.48816 8.07394 9.87868 8.46447L12 10.5858L14.1213 8.46447C14.5118 8.07394 15.145 8.07394 15.5355 8.46447C15.9261 8.85499 15.9261 9.48815 15.5355 9.87868L13.4142 12L15.5355 14.1213C15.9261 14.5118 15.9261 15.145 15.5355 15.5355C15.145 15.9261 14.5118 15.9261 14.1213 15.5355L12 13.4142L9.87868 15.5355C9.48816 15.9261 8.85499 15.9261 8.46447 15.5355C8.07394 15.145 8.07394 14.5118 8.46447 14.1213L10.5858 12L8.46447 9.87868Z" fill="currentcolor"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 772 B |
|
@ -0,0 +1,4 @@
|
|||
<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M13.4099 12.0002L19.7099 5.71019C19.8982 5.52188 20.004 5.26649 20.004 5.00019C20.004 4.73388 19.8982 4.47849 19.7099 4.29019C19.5216 4.10188 19.2662 3.99609 18.9999 3.99609C18.7336 3.99609 18.4782 4.10188 18.2899 4.29019L11.9999 10.5902L5.70994 4.29019C5.52164 4.10188 5.26624 3.99609 4.99994 3.99609C4.73364 3.99609 4.47824 4.10188 4.28994 4.29019C4.10164 4.47849 3.99585 4.73388 3.99585 5.00019C3.99585 5.26649 4.10164 5.52188 4.28994 5.71019L10.5899 12.0002L4.28994 18.2902C4.19621 18.3831 4.12182 18.4937 4.07105 18.6156C4.02028 18.7375 3.99414 18.8682 3.99414 19.0002C3.99414 19.1322 4.02028 19.2629 4.07105 19.3848C4.12182 19.5066 4.19621 19.6172 4.28994 19.7102C4.3829 19.8039 4.4935 19.8783 4.61536 19.9291C4.73722 19.9798 4.86793 20.006 4.99994 20.006C5.13195 20.006 5.26266 19.9798 5.38452 19.9291C5.50638 19.8783 5.61698 19.8039 5.70994 19.7102L11.9999 13.4102L18.2899 19.7102C18.3829 19.8039 18.4935 19.8783 18.6154 19.9291C18.7372 19.9798 18.8679 20.006 18.9999 20.006C19.132 20.006 19.2627 19.9798 19.3845 19.9291C19.5064 19.8783 19.617 19.8039 19.7099 19.7102C19.8037 19.6172 19.8781 19.5066 19.9288 19.3848C19.9796 19.2629 20.0057 19.1322 20.0057 19.0002C20.0057 18.8682 19.9796 18.7375 19.9288 18.6156C19.8781 18.4937 19.8037 18.3831 19.7099 18.2902L13.4099 12.0002Z" fill="currentcolor"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.4 KiB |
|
@ -0,0 +1,6 @@
|
|||
<svg width="21" height="4" viewBox="0 0 21 4" fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<circle cx="2.5" cy="2" r="2" fill="currentcolor"/>
|
||||
<circle cx="10.5" cy="2" r="2" fill="currentcolor"/>
|
||||
<circle cx="18.5" cy="2" r="2" fill="currentcolor"/>
|
||||
</svg>
|
After Width: | Height: | Size: 267 B |
|
@ -0,0 +1,7 @@
|
|||
<svg width="40" height="40" viewBox="0 0 40 40" fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<rect width="40" height="40" rx="6" fill="#F7F8F8"/>
|
||||
<rect width="40" height="40" rx="6" fill="#78767F" fill-opacity="0.02"/>
|
||||
<rect width="40" height="40" rx="6" fill="#5D34F2" fill-opacity="0.16"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M20.1449 8.3335C17.6236 8.3335 15.5796 10.3774 15.5796 12.8987V13.9132C15.5796 16.4345 17.6236 18.4784 20.1449 18.4784C22.6662 18.4784 24.7101 16.4345 24.7101 13.9132V12.8987C24.7101 10.3774 22.6662 8.3335 20.1449 8.3335ZM20.1449 31.6668C30.2899 31.6668 30.2899 28.369 30.2899 28.369C30.2899 24.0916 28.1669 20.1045 22.6812 20.0002C22.6579 19.9997 22.4995 20.1538 22.2699 20.3772C21.6671 20.9635 20.5736 22.0272 20.1449 22.0272C19.7162 22.0272 18.6227 20.9635 18.02 20.3772C17.7904 20.1538 17.6319 19.9997 17.6087 20.0002C12.123 20.1045 10 24.0916 10 28.369C10 28.369 10 31.6668 20.1449 31.6668Z" fill="#947DFF"/>
|
||||
</svg>
|
After Width: | Height: | Size: 975 B |
5
packages/experience-legacy/src/assets/icons/dev-icon.svg
Normal file
|
@ -0,0 +1,5 @@
|
|||
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M12.4096 6.7392C12.5744 6.34657 12.3898 5.89463 11.9971 5.72978C11.6045 5.56493 11.1526 5.74959 10.9877 6.14222L7.58131 13.215C7.41646 13.6076 7.60112 14.0595 7.99375 14.2244C8.38638 14.3892 8.83832 14.2046 9.00317 13.8119L12.4096 6.7392Z" fill="currentColor"/>
|
||||
<path d="M3.66797 10.0003L6.58464 7.08366C6.91797 6.75033 6.91797 6.25033 6.58464 5.91699C6.2513 5.58366 5.7513 5.58366 5.41797 5.91699L1.91797 9.41699C1.58464 9.75033 1.58464 10.2503 1.91797 10.5837L5.41797 14.0837C5.58464 14.2503 5.7513 14.3337 6.0013 14.3337C6.2513 14.3337 6.41797 14.2503 6.58464 14.0837C6.91797 13.7503 6.91797 13.2503 6.58464 12.917L3.66797 10.0003Z" fill="currentColor"/>
|
||||
<path d="M16.3346 10.0003L13.418 7.08366C13.0846 6.75033 13.0846 6.25033 13.418 5.91699C13.7513 5.58366 14.2513 5.58366 14.5846 5.91699L18.0846 9.41699C18.418 9.75033 18.418 10.2503 18.0846 10.5837L14.5846 14.0837C14.418 14.2503 14.2513 14.3337 14.0013 14.3337C13.7513 14.3337 13.5846 14.2503 13.418 14.0837C13.0846 13.7503 13.0846 13.2503 13.418 12.917L16.3346 10.0003Z" fill="currentColor"/>
|
||||
</svg>
|
After Width: | Height: | Size: 1.1 KiB |
|
@ -0,0 +1,58 @@
|
|||
<svg width="194" height="196" viewBox="0 0 194 196" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect x="34" y="46" width="140" height="108" rx="12" fill="#928F9A"/>
|
||||
<mask id="mask0_1266_17280" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="34" y="46" width="140" height="108">
|
||||
<rect x="34" y="46" width="140" height="108" rx="12.1905" fill="#928F9A"/>
|
||||
</mask>
|
||||
<g mask="url(#mask0_1266_17280)">
|
||||
</g>
|
||||
<path d="M34 58C34 51.3726 39.3726 46 46 46H162C168.627 46 174 51.3726 174 58V62H34V58Z" fill="#78767F"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M77.6858 96.686C76.1238 98.2481 76.1238 100.781 77.6858 102.343L83.3434 108L77.6872 113.657C76.1251 115.219 76.1251 117.751 77.6872 119.313C79.2493 120.876 81.782 120.876 83.3441 119.313L89.0002 113.657L94.6564 119.313C96.2185 120.875 98.7512 120.875 100.313 119.313C101.875 117.751 101.875 115.219 100.313 113.657L94.6571 108L100.315 102.343C101.877 100.781 101.877 98.2481 100.315 96.686C98.7525 95.1239 96.2199 95.1239 94.6578 96.686L89.0002 102.344L83.3427 96.686C81.7806 95.1239 79.2479 95.1239 77.6858 96.686Z" fill="#CABEFF"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M125.686 96.686C124.124 98.2481 124.124 100.781 125.686 102.343L131.343 108L125.687 113.657C124.125 115.219 124.125 117.751 125.687 119.313C127.249 120.876 129.782 120.876 131.344 119.313L137 113.657L142.656 119.313C144.219 120.875 146.751 120.875 148.313 119.313C149.875 117.751 149.875 115.219 148.313 113.657L142.657 108L148.315 102.343C149.877 100.781 149.877 98.2481 148.315 96.686C146.753 95.1239 144.22 95.1239 142.658 96.686L137 102.344L131.343 96.686C129.781 95.1239 127.248 95.1239 125.686 96.686Z" fill="#CABEFF"/>
|
||||
<circle cx="48" cy="54" r="2" fill="#5F5D67"/>
|
||||
<circle cx="58" cy="54" r="2" fill="#ADAAB4"/>
|
||||
<circle cx="68" cy="54" r="2" fill="#ADAAB4"/>
|
||||
<rect x="50" y="74" width="64" height="4" rx="2" fill="#ADAAB4"/>
|
||||
<rect x="50" y="81" width="14" height="4" rx="2" fill="#ADAAB4"/>
|
||||
<rect x="148" y="81" width="10" height="4" rx="2" fill="#ADAAB4"/>
|
||||
<rect x="68" y="81" width="74" height="4" rx="2" fill="#ADAAB4"/>
|
||||
<rect x="122" y="74" width="10" height="4" rx="2" fill="#ADAAB4"/>
|
||||
<rect x="135" y="74" width="23" height="4" rx="2" fill="#ADAAB4"/>
|
||||
<mask id="mask1_1266_17280" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="1" y="65" width="92" height="99">
|
||||
<path d="M92 70.5V66H1.5V163.5H39C52.2548 163.5 63 152.755 63 139.5V99.5C63 91.4919 69.4919 85 77.5 85C85.5081 85 92 78.5081 92 70.5Z" fill="white" stroke="#F7F8F8" stroke-opacity="0.16" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</mask>
|
||||
<g mask="url(#mask1_1266_17280)">
|
||||
<path d="M-28 62L-24 64C-21.4819 65.2591 -18.5181 65.259 -16 64V64C-13.482 62.7409 -10.518 62.7409 -7.99999 64V64C-5.48195 65.259 -2.51804 65.259 8.58307e-06 64V64C2.51805 62.7409 5.48197 62.7409 8.00001 64V64C10.518 65.259 13.482 65.2591 16 64V64C18.5181 62.741 21.4951 62.7476 24.0131 64.0066V64.0066C26.5181 65.2591 29.4764 65.281 31.9943 64.0547L32.3036 63.9041C34.7646 62.7055 37.6464 62.7363 40.0813 63.987V63.987C42.5446 65.2524 45.4634 65.2683 47.9404 64.0298L48.0271 63.9865C50.5281 62.736 53.4854 62.7427 55.9864 63.9932V63.9932C58.5045 65.2522 61.4849 65.2576 64.0029 63.9986V63.9986C66.5181 62.741 69.5108 62.751 72.0289 64.0027V64.0027C74.5398 65.2509 77.522 65.2603 80.0284 64.0034V64.0034C82.5424 62.7427 85.5043 62.7416 88.019 64.0008V64.0008C90.5321 65.2591 93.4913 65.2591 96.0044 64.0008L100 62" stroke="#F7F8F8" stroke-opacity="0.16" stroke-width="0.8"/>
|
||||
<path d="M-28 66L-24 68C-21.4819 69.2591 -18.5181 69.259 -16 68V68C-13.482 66.7409 -10.518 66.7409 -7.99999 68V68C-5.48195 69.259 -2.51804 69.259 8.58307e-06 68V68C2.51805 66.7409 5.48197 66.7409 8.00001 68V68C10.518 69.259 13.482 69.2591 16 68V68C18.5181 66.741 21.4951 66.7476 24.0131 68.0066V68.0066C26.5181 69.2591 29.4764 69.281 31.9943 68.0547L32.3036 67.9041C34.7646 66.7055 37.6464 66.7363 40.0813 67.987V67.987C42.5446 69.2524 45.4634 69.2683 47.9404 68.0298L48.0271 67.9865C50.5281 66.736 53.4854 66.7427 55.9864 67.9932V67.9932C58.5045 69.2522 61.4849 69.2576 64.0029 67.9986V67.9986C66.5181 66.741 69.5108 66.751 72.0289 68.0027V68.0027C74.5398 69.2509 77.522 69.2603 80.0284 68.0034V68.0034C82.5424 66.7427 85.5043 66.7416 88.019 68.0008V68.0008C90.5321 69.2591 93.4913 69.2591 96.0044 68.0008L100 66" stroke="#F7F8F8" stroke-opacity="0.16" stroke-width="0.8"/>
|
||||
<path d="M-28 70L-24 72C-21.4819 73.2591 -18.5181 73.259 -16 72V72C-13.482 70.7409 -10.518 70.7409 -7.99999 72V72C-5.48195 73.259 -2.51804 73.259 8.58307e-06 72V72C2.51805 70.7409 5.48197 70.7409 8.00001 72V72C10.518 73.259 13.482 73.2591 16 72V72C18.5181 70.741 21.4951 70.7476 24.0131 72.0066V72.0066C26.5181 73.2591 29.4764 73.281 31.9943 72.0547L32.3036 71.9041C34.7646 70.7055 37.6464 70.7363 40.0813 71.987V71.987C42.5446 73.2524 45.4634 73.2683 47.9404 72.0298L48.0271 71.9865C50.5281 70.736 53.4854 70.7427 55.9864 71.9932V71.9932C58.5045 73.2522 61.4849 73.2576 64.0029 71.9986V71.9986C66.5181 70.741 69.5108 70.751 72.0289 72.0027V72.0027C74.5398 73.2509 77.522 73.2603 80.0284 72.0034V72.0034C82.5424 70.7427 85.5043 70.7416 88.019 72.0008V72.0008C90.5321 73.2591 93.4913 73.2591 96.0044 72.0008L100 70" stroke="#F7F8F8" stroke-opacity="0.16" stroke-width="0.8"/>
|
||||
<path d="M-28 74L-24 76C-21.4819 77.2591 -18.5181 77.259 -16 76V76C-13.482 74.7409 -10.518 74.7409 -7.99999 76V76C-5.48195 77.259 -2.51804 77.259 8.58307e-06 76V76C2.51805 74.7409 5.48197 74.7409 8.00001 76V76C10.518 77.259 13.482 77.2591 16 76V76C18.5181 74.741 21.4951 74.7476 24.0131 76.0066V76.0066C26.5181 77.2591 29.4764 77.281 31.9943 76.0547L32.3036 75.9041C34.7646 74.7055 37.6464 74.7363 40.0813 75.987V75.987C42.5446 77.2524 45.4634 77.2683 47.9404 76.0298L48.0271 75.9865C50.5281 74.736 53.4854 74.7427 55.9864 75.9932V75.9932C58.5045 77.2522 61.4849 77.2576 64.0029 75.9986V75.9986C66.5181 74.741 69.5108 74.751 72.0289 76.0027V76.0027C74.5398 77.2509 77.522 77.2603 80.0284 76.0034V76.0034C82.5424 74.7427 85.5043 74.7416 88.019 76.0008V76.0008C90.5321 77.2591 93.4913 77.2591 96.0044 76.0008L100 74" stroke="#F7F8F8" stroke-opacity="0.16" stroke-width="0.8"/>
|
||||
<path d="M-28 78L-24 80C-21.4819 81.2591 -18.5181 81.259 -16 80V80C-13.482 78.7409 -10.518 78.7409 -7.99999 80V80C-5.48195 81.259 -2.51804 81.259 8.58307e-06 80V80C2.51805 78.7409 5.48197 78.7409 8.00001 80V80C10.518 81.259 13.482 81.2591 16 80V80C18.5181 78.741 21.4951 78.7476 24.0131 80.0066V80.0066C26.5181 81.2591 29.4764 81.281 31.9943 80.0547L32.3036 79.9041C34.7646 78.7055 37.6464 78.7363 40.0813 79.987V79.987C42.5446 81.2524 45.4634 81.2683 47.9404 80.0298L48.0271 79.9865C50.5281 78.736 53.4854 78.7427 55.9864 79.9932V79.9932C58.5045 81.2522 61.4849 81.2576 64.0029 79.9986V79.9986C66.5181 78.741 69.5108 78.751 72.0289 80.0027V80.0027C74.5398 81.2509 77.522 81.2603 80.0284 80.0034V80.0034C82.5424 78.7427 85.5043 78.7416 88.019 80.0008V80.0008C90.5321 81.2591 93.4913 81.2591 96.0044 80.0008L100 78" stroke="#F7F8F8" stroke-opacity="0.16" stroke-width="0.8"/>
|
||||
<path d="M-28 82L-24 84C-21.4819 85.2591 -18.5181 85.259 -16 84V84C-13.482 82.7409 -10.518 82.7409 -7.99999 84V84C-5.48195 85.259 -2.51804 85.259 8.58307e-06 84V84C2.51805 82.7409 5.48197 82.7409 8.00001 84V84C10.518 85.259 13.482 85.2591 16 84V84C18.5181 82.741 21.4951 82.7476 24.0131 84.0066V84.0066C26.5181 85.2591 29.4764 85.281 31.9943 84.0547L32.3036 83.9041C34.7646 82.7055 37.6464 82.7363 40.0813 83.987V83.987C42.5446 85.2524 45.4634 85.2683 47.9404 84.0298L48.0271 83.9865C50.5281 82.736 53.4854 82.7427 55.9864 83.9932V83.9932C58.5045 85.2522 61.4849 85.2576 64.0029 83.9986V83.9986C66.5181 82.741 69.5108 82.751 72.0289 84.0027V84.0027C74.5398 85.2509 77.522 85.2603 80.0284 84.0034V84.0034C82.5424 82.7427 85.5043 82.7416 88.019 84.0008V84.0008C90.5321 85.2591 93.4913 85.2591 96.0044 84.0008L100 82" stroke="#F7F8F8" stroke-opacity="0.16" stroke-width="0.8"/>
|
||||
<path d="M-28 86L-24 88C-21.4819 89.2591 -18.5181 89.259 -16 88V88C-13.482 86.7409 -10.518 86.7409 -7.99999 88V88C-5.48195 89.259 -2.51804 89.259 8.58307e-06 88V88C2.51805 86.7409 5.48197 86.7409 8.00001 88V88C10.518 89.259 13.482 89.2591 16 88V88C18.5181 86.741 21.4951 86.7476 24.0131 88.0066V88.0066C26.5181 89.2591 29.4764 89.281 31.9943 88.0547L32.3036 87.9041C34.7646 86.7055 37.6464 86.7363 40.0813 87.987V87.987C42.5446 89.2524 45.4634 89.2683 47.9404 88.0298L48.0271 87.9865C50.5281 86.736 53.4854 86.7427 55.9864 87.9932V87.9932C58.5045 89.2522 61.4849 89.2576 64.0029 87.9986V87.9986C66.5181 86.741 69.5108 86.751 72.0289 88.0027V88.0027C74.5398 89.2509 77.522 89.2603 80.0284 88.0034V88.0034C82.5424 86.7427 85.5043 86.7416 88.019 88.0008V88.0008C90.5321 89.2591 93.4913 89.2591 96.0044 88.0008L100 86" stroke="#F7F8F8" stroke-opacity="0.16" stroke-width="0.8"/>
|
||||
<path d="M-28 90L-24 92C-21.4819 93.2591 -18.5181 93.259 -16 92V92C-13.482 90.7409 -10.518 90.7409 -7.99999 92V92C-5.48195 93.259 -2.51804 93.259 8.58307e-06 92V92C2.51805 90.7409 5.48197 90.7409 8.00001 92V92C10.518 93.259 13.482 93.2591 16 92V92C18.5181 90.741 21.4951 90.7476 24.0131 92.0066V92.0066C26.5181 93.2591 29.4764 93.281 31.9943 92.0547L32.3036 91.9041C34.7646 90.7055 37.6464 90.7363 40.0813 91.987V91.987C42.5446 93.2524 45.4634 93.2683 47.9404 92.0298L48.0271 91.9865C50.5281 90.736 53.4854 90.7427 55.9864 91.9932V91.9932C58.5045 93.2522 61.4849 93.2576 64.0029 91.9986V91.9986C66.5181 90.741 69.5108 90.751 72.0289 92.0027V92.0027C74.5398 93.2509 77.522 93.2603 80.0284 92.0034V92.0034C82.5424 90.7427 85.5043 90.7416 88.019 92.0008V92.0008C90.5321 93.2591 93.4913 93.2591 96.0044 92.0008L100 90" stroke="#F7F8F8" stroke-opacity="0.16" stroke-width="0.8"/>
|
||||
<path d="M-28 94L-24 96C-21.4819 97.2591 -18.5181 97.259 -16 96V96C-13.482 94.7409 -10.518 94.7409 -7.99999 96V96C-5.48195 97.259 -2.51804 97.259 8.58307e-06 96V96C2.51805 94.7409 5.48197 94.7409 8.00001 96V96C10.518 97.259 13.482 97.2591 16 96V96C18.5181 94.741 21.4951 94.7476 24.0131 96.0066V96.0066C26.5181 97.2591 29.4764 97.281 31.9943 96.0547L32.3036 95.9041C34.7646 94.7055 37.6464 94.7363 40.0813 95.987V95.987C42.5446 97.2524 45.4634 97.2683 47.9404 96.0298L48.0271 95.9865C50.5281 94.736 53.4854 94.7427 55.9864 95.9932V95.9932C58.5045 97.2522 61.4849 97.2576 64.0029 95.9986V95.9986C66.5181 94.741 69.5108 94.751 72.0289 96.0027V96.0027C74.5398 97.2509 77.522 97.2603 80.0284 96.0034V96.0034C82.5424 94.7427 85.5043 94.7416 88.019 96.0008V96.0008C90.5321 97.2591 93.4913 97.2591 96.0044 96.0008L100 94" stroke="#F7F8F8" stroke-opacity="0.16" stroke-width="0.8"/>
|
||||
<path d="M-28 98L-24 100C-21.4819 101.259 -18.5181 101.259 -16 100V100C-13.482 98.7409 -10.518 98.7409 -7.99999 100V100C-5.48195 101.259 -2.51804 101.259 8.58307e-06 100V100C2.51805 98.7409 5.48197 98.7409 8.00001 100V100C10.518 101.259 13.482 101.259 16 100V100C18.5181 98.741 21.4951 98.7476 24.0131 100.007V100.007C26.5181 101.259 29.4764 101.281 31.9943 100.055L32.3036 99.9041C34.7646 98.7055 37.6464 98.7363 40.0813 99.987V99.987C42.5446 101.252 45.4634 101.268 47.9404 100.03L48.0271 99.9865C50.5281 98.736 53.4854 98.7427 55.9864 99.9932V99.9932C58.5045 101.252 61.4849 101.258 64.0029 99.9986V99.9986C66.5181 98.741 69.5108 98.751 72.0289 100.003V100.003C74.5398 101.251 77.522 101.26 80.0284 100.003V100.003C82.5424 98.7427 85.5043 98.7416 88.019 100.001V100.001C90.5321 101.259 93.4913 101.259 96.0044 100.001L100 98" stroke="#F7F8F8" stroke-opacity="0.16" stroke-width="0.8"/>
|
||||
<path d="M-28 102L-24 104C-21.4819 105.259 -18.5181 105.259 -16 104V104C-13.482 102.741 -10.518 102.741 -7.99999 104V104C-5.48195 105.259 -2.51804 105.259 8.58307e-06 104V104C2.51805 102.741 5.48197 102.741 8.00001 104V104C10.518 105.259 13.482 105.259 16 104V104C18.5181 102.741 21.4951 102.748 24.0131 104.007V104.007C26.5181 105.259 29.4764 105.281 31.9943 104.055L32.3036 103.904C34.7646 102.706 37.6464 102.736 40.0813 103.987V103.987C42.5446 105.252 45.4634 105.268 47.9404 104.03L48.0271 103.986C50.5281 102.736 53.4854 102.743 55.9864 103.993V103.993C58.5045 105.252 61.4849 105.258 64.0029 103.999V103.999C66.5181 102.741 69.5108 102.751 72.0289 104.003V104.003C74.5398 105.251 77.522 105.26 80.0284 104.003V104.003C82.5424 102.743 85.5043 102.742 88.019 104.001V104.001C90.5321 105.259 93.4913 105.259 96.0044 104.001L100 102" stroke="#F7F8F8" stroke-opacity="0.16" stroke-width="0.8"/>
|
||||
<path d="M-28 106L-24 108C-21.4819 109.259 -18.5181 109.259 -16 108V108C-13.482 106.741 -10.518 106.741 -7.99999 108V108C-5.48195 109.259 -2.51804 109.259 8.58307e-06 108V108C2.51805 106.741 5.48197 106.741 8.00001 108V108C10.518 109.259 13.482 109.259 16 108V108C18.5181 106.741 21.4951 106.748 24.0131 108.007V108.007C26.5181 109.259 29.4764 109.281 31.9943 108.055L32.3036 107.904C34.7646 106.706 37.6464 106.736 40.0813 107.987V107.987C42.5446 109.252 45.4634 109.268 47.9404 108.03L48.0271 107.986C50.5281 106.736 53.4854 106.743 55.9864 107.993V107.993C58.5045 109.252 61.4849 109.258 64.0029 107.999V107.999C66.5181 106.741 69.5108 106.751 72.0289 108.003V108.003C74.5398 109.251 77.522 109.26 80.0284 108.003V108.003C82.5424 106.743 85.5043 106.742 88.019 108.001V108.001C90.5321 109.259 93.4913 109.259 96.0044 108.001L100 106" stroke="#F7F8F8" stroke-opacity="0.16" stroke-width="0.8"/>
|
||||
<path d="M-28 110L-24 112C-21.4819 113.259 -18.5181 113.259 -16 112V112C-13.482 110.741 -10.518 110.741 -7.99999 112V112C-5.48195 113.259 -2.51804 113.259 8.58307e-06 112V112C2.51805 110.741 5.48197 110.741 8.00001 112V112C10.518 113.259 13.482 113.259 16 112V112C18.5181 110.741 21.4951 110.748 24.0131 112.007V112.007C26.5181 113.259 29.4764 113.281 31.9943 112.055L32.3036 111.904C34.7646 110.706 37.6464 110.736 40.0813 111.987V111.987C42.5446 113.252 45.4634 113.268 47.9404 112.03L48.0271 111.986C50.5281 110.736 53.4854 110.743 55.9864 111.993V111.993C58.5045 113.252 61.4849 113.258 64.0029 111.999V111.999C66.5181 110.741 69.5108 110.751 72.0289 112.003V112.003C74.5398 113.251 77.522 113.26 80.0284 112.003V112.003C82.5424 110.743 85.5043 110.742 88.019 112.001V112.001C90.5321 113.259 93.4913 113.259 96.0044 112.001L100 110" stroke="#F7F8F8" stroke-opacity="0.16" stroke-width="0.8"/>
|
||||
<path d="M-28 114L-24 116C-21.4819 117.259 -18.5181 117.259 -16 116V116C-13.482 114.741 -10.518 114.741 -7.99999 116V116C-5.48195 117.259 -2.51804 117.259 8.58307e-06 116V116C2.51805 114.741 5.48197 114.741 8.00001 116V116C10.518 117.259 13.482 117.259 16 116V116C18.5181 114.741 21.4951 114.748 24.0131 116.007V116.007C26.5181 117.259 29.4764 117.281 31.9943 116.055L32.3036 115.904C34.7646 114.706 37.6464 114.736 40.0813 115.987V115.987C42.5446 117.252 45.4634 117.268 47.9404 116.03L48.0271 115.986C50.5281 114.736 53.4854 114.743 55.9864 115.993V115.993C58.5045 117.252 61.4849 117.258 64.0029 115.999V115.999C66.5181 114.741 69.5108 114.751 72.0289 116.003V116.003C74.5398 117.251 77.522 117.26 80.0284 116.003V116.003C82.5424 114.743 85.5043 114.742 88.019 116.001V116.001C90.5321 117.259 93.4913 117.259 96.0044 116.001L100 114" stroke="#F7F8F8" stroke-opacity="0.16" stroke-width="0.8"/>
|
||||
<path d="M-28 118L-24 120C-21.4819 121.259 -18.5181 121.259 -16 120V120C-13.482 118.741 -10.518 118.741 -7.99999 120V120C-5.48195 121.259 -2.51804 121.259 8.58307e-06 120V120C2.51805 118.741 5.48197 118.741 8.00001 120V120C10.518 121.259 13.482 121.259 16 120V120C18.5181 118.741 21.4951 118.748 24.0131 120.007V120.007C26.5181 121.259 29.4764 121.281 31.9943 120.055L32.3036 119.904C34.7646 118.706 37.6464 118.736 40.0813 119.987V119.987C42.5446 121.252 45.4634 121.268 47.9404 120.03L48.0271 119.986C50.5281 118.736 53.4854 118.743 55.9864 119.993V119.993C58.5045 121.252 61.4849 121.258 64.0029 119.999V119.999C66.5181 118.741 69.5108 118.751 72.0289 120.003V120.003C74.5398 121.251 77.522 121.26 80.0284 120.003V120.003C82.5424 118.743 85.5043 118.742 88.019 120.001V120.001C90.5321 121.259 93.4913 121.259 96.0044 120.001L100 118" stroke="#F7F8F8" stroke-opacity="0.16" stroke-width="0.8"/>
|
||||
<path d="M-28 122L-24 124C-21.4819 125.259 -18.5181 125.259 -16 124V124C-13.482 122.741 -10.518 122.741 -7.99999 124V124C-5.48195 125.259 -2.51804 125.259 8.58307e-06 124V124C2.51805 122.741 5.48197 122.741 8.00001 124V124C10.518 125.259 13.482 125.259 16 124V124C18.5181 122.741 21.4951 122.748 24.0131 124.007V124.007C26.5181 125.259 29.4764 125.281 31.9943 124.055L32.3036 123.904C34.7646 122.706 37.6464 122.736 40.0813 123.987V123.987C42.5446 125.252 45.4634 125.268 47.9404 124.03L48.0271 123.986C50.5281 122.736 53.4854 122.743 55.9864 123.993V123.993C58.5045 125.252 61.4849 125.258 64.0029 123.999V123.999C66.5181 122.741 69.5108 122.751 72.0289 124.003V124.003C74.5398 125.251 77.522 125.26 80.0284 124.003V124.003C82.5424 122.743 85.5043 122.742 88.019 124.001V124.001C90.5321 125.259 93.4913 125.259 96.0044 124.001L100 122" stroke="#F7F8F8" stroke-opacity="0.16" stroke-width="0.8"/>
|
||||
<path d="M-28 126L-24 128C-21.4819 129.259 -18.5181 129.259 -16 128V128C-13.482 126.741 -10.518 126.741 -7.99999 128V128C-5.48195 129.259 -2.51804 129.259 8.58307e-06 128V128C2.51805 126.741 5.48197 126.741 8.00001 128V128C10.518 129.259 13.482 129.259 16 128V128C18.5181 126.741 21.4951 126.748 24.0131 128.007V128.007C26.5181 129.259 29.4764 129.281 31.9943 128.055L32.3036 127.904C34.7646 126.706 37.6464 126.736 40.0813 127.987V127.987C42.5446 129.252 45.4634 129.268 47.9404 128.03L48.0271 127.986C50.5281 126.736 53.4854 126.743 55.9864 127.993V127.993C58.5045 129.252 61.4849 129.258 64.0029 127.999V127.999C66.5181 126.741 69.5108 126.751 72.0289 128.003V128.003C74.5398 129.251 77.522 129.26 80.0284 128.003V128.003C82.5424 126.743 85.5043 126.742 88.019 128.001V128.001C90.5321 129.259 93.4913 129.259 96.0044 128.001L100 126" stroke="#F7F8F8" stroke-opacity="0.16" stroke-width="0.8"/>
|
||||
<path d="M-28 130L-24 132C-21.4819 133.259 -18.5181 133.259 -16 132V132C-13.482 130.741 -10.518 130.741 -7.99999 132V132C-5.48195 133.259 -2.51804 133.259 8.58307e-06 132V132C2.51805 130.741 5.48197 130.741 8.00001 132V132C10.518 133.259 13.482 133.259 16 132V132C18.5181 130.741 21.4951 130.748 24.0131 132.007V132.007C26.5181 133.259 29.4764 133.281 31.9943 132.055L32.3036 131.904C34.7646 130.706 37.6464 130.736 40.0813 131.987V131.987C42.5446 133.252 45.4634 133.268 47.9404 132.03L48.0271 131.986C50.5281 130.736 53.4854 130.743 55.9864 131.993V131.993C58.5045 133.252 61.4849 133.258 64.0029 131.999V131.999C66.5181 130.741 69.5108 130.751 72.0289 132.003V132.003C74.5398 133.251 77.522 133.26 80.0284 132.003V132.003C82.5424 130.743 85.5043 130.742 88.019 132.001V132.001C90.5321 133.259 93.4913 133.259 96.0044 132.001L100 130" stroke="#F7F8F8" stroke-opacity="0.16" stroke-width="0.8"/>
|
||||
<path d="M-28 134L-24 136C-21.4819 137.259 -18.5181 137.259 -16 136V136C-13.482 134.741 -10.518 134.741 -7.99999 136V136C-5.48195 137.259 -2.51804 137.259 8.58307e-06 136V136C2.51805 134.741 5.48197 134.741 8.00001 136V136C10.518 137.259 13.482 137.259 16 136V136C18.5181 134.741 21.4951 134.748 24.0131 136.007V136.007C26.5181 137.259 29.4764 137.281 31.9943 136.055L32.3036 135.904C34.7646 134.706 37.6464 134.736 40.0813 135.987V135.987C42.5446 137.252 45.4634 137.268 47.9404 136.03L48.0271 135.986C50.5281 134.736 53.4854 134.743 55.9864 135.993V135.993C58.5045 137.252 61.4849 137.258 64.0029 135.999V135.999C66.5181 134.741 69.5108 134.751 72.0289 136.003V136.003C74.5398 137.251 77.522 137.26 80.0284 136.003V136.003C82.5424 134.743 85.5043 134.742 88.019 136.001V136.001C90.5321 137.259 93.4913 137.259 96.0044 136.001L100 134" stroke="#F7F8F8" stroke-opacity="0.16" stroke-width="0.8"/>
|
||||
<path d="M-28 138L-24 140C-21.4819 141.259 -18.5181 141.259 -16 140V140C-13.482 138.741 -10.518 138.741 -7.99999 140V140C-5.48195 141.259 -2.51804 141.259 8.58307e-06 140V140C2.51805 138.741 5.48197 138.741 8.00001 140V140C10.518 141.259 13.482 141.259 16 140V140C18.5181 138.741 21.4951 138.748 24.0131 140.007V140.007C26.5181 141.259 29.4764 141.281 31.9943 140.055L32.3036 139.904C34.7646 138.706 37.6464 138.736 40.0813 139.987V139.987C42.5446 141.252 45.4634 141.268 47.9404 140.03L48.0271 139.986C50.5281 138.736 53.4854 138.743 55.9864 139.993V139.993C58.5045 141.252 61.4849 141.258 64.0029 139.999V139.999C66.5181 138.741 69.5108 138.751 72.0289 140.003V140.003C74.5398 141.251 77.522 141.26 80.0284 140.003V140.003C82.5424 138.743 85.5043 138.742 88.019 140.001V140.001C90.5321 141.259 93.4913 141.259 96.0044 140.001L100 138" stroke="#F7F8F8" stroke-opacity="0.16" stroke-width="0.8"/>
|
||||
<path d="M-28 142L-24 144C-21.4819 145.259 -18.5181 145.259 -16 144V144C-13.482 142.741 -10.518 142.741 -7.99999 144V144C-5.48195 145.259 -2.51804 145.259 8.58307e-06 144V144C2.51805 142.741 5.48197 142.741 8.00001 144V144C10.518 145.259 13.482 145.259 16 144V144C18.5181 142.741 21.4951 142.748 24.0131 144.007V144.007C26.5181 145.259 29.4764 145.281 31.9943 144.055L32.3036 143.904C34.7646 142.706 37.6464 142.736 40.0813 143.987V143.987C42.5446 145.252 45.4634 145.268 47.9404 144.03L48.0271 143.986C50.5281 142.736 53.4854 142.743 55.9864 143.993V143.993C58.5045 145.252 61.4849 145.258 64.0029 143.999V143.999C66.5181 142.741 69.5108 142.751 72.0289 144.003V144.003C74.5398 145.251 77.522 145.26 80.0284 144.003V144.003C82.5424 142.743 85.5043 142.742 88.019 144.001V144.001C90.5321 145.259 93.4913 145.259 96.0044 144.001L100 142" stroke="#F7F8F8" stroke-opacity="0.16" stroke-width="0.8"/>
|
||||
<path d="M-28 146L-24 148C-21.4819 149.259 -18.5181 149.259 -16 148V148C-13.482 146.741 -10.518 146.741 -7.99999 148V148C-5.48195 149.259 -2.51804 149.259 8.58307e-06 148V148C2.51805 146.741 5.48197 146.741 8.00001 148V148C10.518 149.259 13.482 149.259 16 148V148C18.5181 146.741 21.4951 146.748 24.0131 148.007V148.007C26.5181 149.259 29.4764 149.281 31.9943 148.055L32.3036 147.904C34.7646 146.706 37.6464 146.736 40.0813 147.987V147.987C42.5446 149.252 45.4634 149.268 47.9404 148.03L48.0271 147.986C50.5281 146.736 53.4854 146.743 55.9864 147.993V147.993C58.5045 149.252 61.4849 149.258 64.0029 147.999V147.999C66.5181 146.741 69.5108 146.751 72.0289 148.003V148.003C74.5398 149.251 77.522 149.26 80.0284 148.003V148.003C82.5424 146.743 85.5043 146.742 88.019 148.001V148.001C90.5321 149.259 93.4913 149.259 96.0044 148.001L100 146" stroke="#F7F8F8" stroke-opacity="0.16" stroke-width="0.8"/>
|
||||
<path d="M-28 150L-24 152C-21.4819 153.259 -18.5181 153.259 -16 152V152C-13.482 150.741 -10.518 150.741 -7.99999 152V152C-5.48195 153.259 -2.51804 153.259 8.58307e-06 152V152C2.51805 150.741 5.48197 150.741 8.00001 152V152C10.518 153.259 13.482 153.259 16 152V152C18.5181 150.741 21.4951 150.748 24.0131 152.007V152.007C26.5181 153.259 29.4764 153.281 31.9943 152.055L32.3036 151.904C34.7646 150.706 37.6464 150.736 40.0813 151.987V151.987C42.5446 153.252 45.4634 153.268 47.9404 152.03L48.0271 151.986C50.5281 150.736 53.4854 150.743 55.9864 151.993V151.993C58.5045 153.252 61.4849 153.258 64.0029 151.999V151.999C66.5181 150.741 69.5108 150.751 72.0289 152.003V152.003C74.5398 153.251 77.522 153.26 80.0284 152.003V152.003C82.5424 150.743 85.5043 150.742 88.019 152.001V152.001C90.5321 153.259 93.4913 153.259 96.0044 152.001L100 150" stroke="#F7F8F8" stroke-opacity="0.16" stroke-width="0.8"/>
|
||||
<path d="M-28 154L-24 156C-21.4819 157.259 -18.5181 157.259 -16 156V156C-13.482 154.741 -10.518 154.741 -7.99999 156V156C-5.48195 157.259 -2.51804 157.259 8.58307e-06 156V156C2.51805 154.741 5.48197 154.741 8.00001 156V156C10.518 157.259 13.482 157.259 16 156V156C18.5181 154.741 21.4951 154.748 24.0131 156.007V156.007C26.5181 157.259 29.4764 157.281 31.9943 156.055L32.3036 155.904C34.7646 154.706 37.6464 154.736 40.0813 155.987V155.987C42.5446 157.252 45.4634 157.268 47.9404 156.03L48.0271 155.986C50.5281 154.736 53.4854 154.743 55.9864 155.993V155.993C58.5045 157.252 61.4849 157.258 64.0029 155.999V155.999C66.5181 154.741 69.5108 154.751 72.0289 156.003V156.003C74.5398 157.251 77.522 157.26 80.0284 156.003V156.003C82.5424 154.743 85.5043 154.742 88.019 156.001V156.001C90.5321 157.259 93.4913 157.259 96.0044 156.001L100 154" stroke="#F7F8F8" stroke-opacity="0.16" stroke-width="0.8"/>
|
||||
<path d="M-28 158L-24 160C-21.4819 161.259 -18.5181 161.259 -16 160V160C-13.482 158.741 -10.518 158.741 -7.99999 160V160C-5.48195 161.259 -2.51804 161.259 8.58307e-06 160V160C2.51805 158.741 5.48197 158.741 8.00001 160V160C10.518 161.259 13.482 161.259 16 160V160C18.5181 158.741 21.4951 158.748 24.0131 160.007V160.007C26.5181 161.259 29.4764 161.281 31.9943 160.055L32.3036 159.904C34.7646 158.706 37.6464 158.736 40.0813 159.987V159.987C42.5446 161.252 45.4634 161.268 47.9404 160.03L48.0271 159.986C50.5281 158.736 53.4854 158.743 55.9864 159.993V159.993C58.5045 161.252 61.4849 161.258 64.0029 159.999V159.999C66.5181 158.741 69.5108 158.751 72.0289 160.003V160.003C74.5398 161.251 77.522 161.26 80.0284 160.003V160.003C82.5424 158.743 85.5043 158.742 88.019 160.001V160.001C90.5321 161.259 93.4913 161.259 96.0044 160.001L100 158" stroke="#F7F8F8" stroke-opacity="0.16" stroke-width="0.8"/>
|
||||
<path d="M-28 162L-24 164C-21.4819 165.259 -18.5181 165.259 -16 164V164C-13.482 162.741 -10.518 162.741 -7.99999 164V164C-5.48195 165.259 -2.51804 165.259 8.58307e-06 164V164C2.51805 162.741 5.48197 162.741 8.00001 164V164C10.518 165.259 13.482 165.259 16 164V164C18.5181 162.741 21.4951 162.748 24.0131 164.007V164.007C26.5181 165.259 29.4764 165.281 31.9943 164.055L32.3036 163.904C34.7646 162.706 37.6464 162.736 40.0813 163.987V163.987C42.5446 165.252 45.4634 165.268 47.9404 164.03L48.0271 163.986C50.5281 162.736 53.4854 162.743 55.9864 163.993V163.993C58.5045 165.252 61.4849 165.258 64.0029 163.999V163.999C66.5181 162.741 69.5108 162.751 72.0289 164.003V164.003C74.5398 165.251 77.522 165.26 80.0284 164.003V164.003C82.5424 162.743 85.5043 162.742 88.019 164.001V164.001C90.5321 165.259 93.4913 165.259 96.0044 164.001L100 162" stroke="#F7F8F8" stroke-opacity="0.16" stroke-width="0.8"/>
|
||||
</g>
|
||||
<rect x="143.453" y="24" width="24" height="24" rx="4" transform="rotate(50.249 143.453 24)" fill="#F7F8F8" fill-opacity="0.16"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M181.914 0.208615C181.914 0.0934007 182.008 0 182.123 0H185.878C185.993 0 186.087 0.0933997 186.087 0.208614V6.81728L191.81 3.513C191.91 3.45539 192.037 3.48958 192.095 3.58936L193.972 6.84133C194.03 6.94111 193.996 7.06869 193.896 7.1263L188.172 10.4308L193.896 13.7351C193.995 13.7927 194.03 13.9203 193.972 14.0201L192.094 17.272C192.037 17.3718 191.909 17.406 191.81 17.3484L186.087 14.0443V20.6528C186.087 20.768 185.993 20.8614 185.878 20.8614H182.123C182.008 20.8614 181.914 20.768 181.914 20.6528V14.0439L176.191 17.3484C176.091 17.406 175.963 17.3718 175.906 17.272L174.028 14.0201C173.971 13.9203 174.005 13.7927 174.105 13.7351L179.828 10.4308L174.104 7.1263C174.005 7.06869 173.97 6.94111 174.028 6.84133L175.906 3.58936C175.963 3.48958 176.091 3.45539 176.19 3.513L181.914 6.8177V0.208615Z" fill="#CABEFF" fill-opacity="0.16"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M8 25C12.4183 25 16 21.4183 16 17C16 12.5817 12.4183 9 8 9C3.58172 9 0 12.5817 0 17C0 21.4183 3.58172 25 8 25ZM8 21C10.2091 21 12 19.2091 12 17C12 14.7909 10.2091 13 8 13C5.79086 13 4 14.7909 4 17C4 19.2091 5.79086 21 8 21Z" fill="#F7F8F8" fill-opacity="0.16"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M170 162C176.627 162 182 156.627 182 150C182 143.373 176.627 138 170 138C163.373 138 158 143.373 158 150C158 156.627 163.373 162 170 162ZM170 156C173.314 156 176 153.314 176 150C176 146.686 173.314 144 170 144C166.686 144 164 146.686 164 150C164 153.314 166.686 156 170 156Z" fill="#ADAAB4"/>
|
||||
<path d="M52.3049 25.602C51.2391 22.7131 53.7004 19.7538 56.7351 20.2753L61.2872 21.0576C64.3219 21.5791 65.6541 25.1902 63.6851 27.5576L60.7316 31.1087C58.7626 33.4761 54.9692 32.8242 53.9034 29.9353L52.3049 25.602Z" fill="#F7F8F8" fill-opacity="0.12"/>
|
||||
<rect x="51" y="192" width="80" height="4" rx="2" fill="#CABEFF" fill-opacity="0.12"/>
|
||||
<rect x="143" y="192" width="19" height="4" rx="2" fill="#CABEFF" fill-opacity="0.12"/>
|
||||
</svg>
|
After Width: | Height: | Size: 27 KiB |
61
packages/experience-legacy/src/assets/icons/empty-state.svg
Normal file
|
@ -0,0 +1,61 @@
|
|||
<svg width="194" height="196" viewBox="0 0 194 196" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect x="34" y="46" width="140" height="108" rx="12" fill="#C9C5D0"/>
|
||||
<mask id="mask0_1266_17177" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="34" y="46" width="140" height="108">
|
||||
<rect x="34" y="46" width="140" height="108" rx="12" fill="#D5CFF1"/>
|
||||
</mask>
|
||||
<g mask="url(#mask0_1266_17177)">
|
||||
</g>
|
||||
<path d="M34 58C34 51.3726 39.3726 46 46 46H162C168.627 46 174 51.3726 174 58V62H34V58Z" fill="#78767F"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M77.6858 96.6863C76.1237 98.2484 76.1237 100.781 77.6858 102.343L83.3433 108.001L77.6871 113.657C76.125 115.219 76.125 117.752 77.6871 119.314C79.2492 120.876 81.7819 120.876 83.344 119.314L89.0001 113.658L94.6564 119.314C96.2184 120.876 98.7511 120.876 100.313 119.314C101.875 117.752 101.875 115.219 100.313 113.657L94.657 108.001L100.315 102.343C101.877 100.781 101.877 98.2483 100.315 96.6862C98.7525 95.1241 96.2198 95.1241 94.6577 96.6862L89.0001 102.344L83.3426 96.6863C81.7805 95.1242 79.2479 95.1242 77.6858 96.6863Z" fill="#947DFF"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M125.686 96.6863C124.124 98.2484 124.124 100.781 125.686 102.343L131.343 108.001L125.687 113.657C124.125 115.219 124.125 117.752 125.687 119.314C127.249 120.876 129.782 120.876 131.344 119.314L137 113.658L142.656 119.314C144.218 120.876 146.751 120.876 148.313 119.314C149.875 117.752 149.875 115.219 148.313 113.657L142.657 108.001L148.315 102.343C149.877 100.781 149.877 98.2483 148.315 96.6862C146.752 95.1241 144.22 95.1241 142.658 96.6862L137 102.344L131.343 96.6863C129.781 95.1242 127.248 95.1242 125.686 96.6863Z" fill="#947DFF"/>
|
||||
<circle cx="48" cy="54" r="2" fill="#78767F"/>
|
||||
<circle cx="58" cy="54" r="2" fill="#C9C5D0"/>
|
||||
<circle cx="68" cy="54" r="2" fill="#C9C5D0"/>
|
||||
<rect x="50" y="74" width="64" height="4" rx="2" fill="#ADAAB4"/>
|
||||
<rect x="50" y="81" width="14" height="4" rx="2" fill="#ADAAB4"/>
|
||||
<rect x="148" y="81" width="10" height="4" rx="2" fill="#ADAAB4"/>
|
||||
<rect x="68" y="81" width="74" height="4" rx="2" fill="#ADAAB4"/>
|
||||
<rect x="122" y="74" width="10" height="4" rx="2" fill="#ADAAB4"/>
|
||||
<rect x="135" y="74" width="23" height="4" rx="2" fill="#ADAAB4"/>
|
||||
<mask id="mask1_1266_17177" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="1" y="66" width="91" height="98">
|
||||
<path d="M92 70.5V66H1.5V163.5H39C52.2548 163.5 63 152.755 63 139.5V99.5C63 91.4919 69.4919 85 77.5 85C85.5081 85 92 78.5081 92 70.5Z" fill="white"/>
|
||||
</mask>
|
||||
<g mask="url(#mask1_1266_17177)">
|
||||
<path d="M-28 66L-24 68C-21.4819 69.2591 -18.5181 69.259 -16 68V68C-13.482 66.7409 -10.518 66.7409 -7.99999 68V68C-5.48195 69.259 -2.51804 69.259 8.58307e-06 68V68C2.51805 66.7409 5.48197 66.7409 8.00001 68V68C10.518 69.259 13.482 69.2591 16 68V68C18.5181 66.741 21.4951 66.7476 24.0131 68.0066V68.0066C26.5181 69.2591 29.4764 69.281 31.9943 68.0547L32.3036 67.9041C34.7646 66.7055 37.6464 66.7363 40.0813 67.987V67.987C42.5446 69.2524 45.4634 69.2683 47.9404 68.0298L48.0271 67.9865C50.5281 66.736 53.4854 66.7427 55.9864 67.9932V67.9932C58.5045 69.2522 61.4849 69.2576 64.0029 67.9986V67.9986C66.5181 66.741 69.5108 66.751 72.0289 68.0027V68.0027C74.5398 69.2509 77.522 69.2603 80.0284 68.0034V68.0034C82.5424 66.7427 85.5043 66.7416 88.019 68.0008V68.0008C90.5321 69.2591 93.4913 69.2591 96.0044 68.0008L100 66" stroke="#C9C5D0" stroke-width="0.8"/>
|
||||
<path d="M-28 70L-24 72C-21.4819 73.2591 -18.5181 73.259 -16 72V72C-13.482 70.7409 -10.518 70.7409 -7.99999 72V72C-5.48195 73.259 -2.51804 73.259 8.58307e-06 72V72C2.51805 70.7409 5.48197 70.7409 8.00001 72V72C10.518 73.259 13.482 73.2591 16 72V72C18.5181 70.741 21.4951 70.7476 24.0131 72.0066V72.0066C26.5181 73.2591 29.4764 73.281 31.9943 72.0547L32.3036 71.9041C34.7646 70.7055 37.6464 70.7363 40.0813 71.987V71.987C42.5446 73.2524 45.4634 73.2683 47.9404 72.0298L48.0271 71.9865C50.5281 70.736 53.4854 70.7427 55.9864 71.9932V71.9932C58.5045 73.2522 61.4849 73.2576 64.0029 71.9986V71.9986C66.5181 70.741 69.5108 70.751 72.0289 72.0027V72.0027C74.5398 73.2509 77.522 73.2603 80.0284 72.0034V72.0034C82.5424 70.7427 85.5043 70.7416 88.019 72.0008V72.0008C90.5321 73.2591 93.4913 73.2591 96.0044 72.0008L100 70" stroke="#C9C5D0" stroke-width="0.8"/>
|
||||
<path d="M-28 74L-24 76C-21.4819 77.2591 -18.5181 77.259 -16 76V76C-13.482 74.7409 -10.518 74.7409 -7.99999 76V76C-5.48195 77.259 -2.51804 77.259 8.58307e-06 76V76C2.51805 74.7409 5.48197 74.7409 8.00001 76V76C10.518 77.259 13.482 77.2591 16 76V76C18.5181 74.741 21.4951 74.7476 24.0131 76.0066V76.0066C26.5181 77.2591 29.4764 77.281 31.9943 76.0547L32.3036 75.9041C34.7646 74.7055 37.6464 74.7363 40.0813 75.987V75.987C42.5446 77.2524 45.4634 77.2683 47.9404 76.0298L48.0271 75.9865C50.5281 74.736 53.4854 74.7427 55.9864 75.9932V75.9932C58.5045 77.2522 61.4849 77.2576 64.0029 75.9986V75.9986C66.5181 74.741 69.5108 74.751 72.0289 76.0027V76.0027C74.5398 77.2509 77.522 77.2603 80.0284 76.0034V76.0034C82.5424 74.7427 85.5043 74.7416 88.019 76.0008V76.0008C90.5321 77.2591 93.4913 77.2591 96.0044 76.0008L100 74" stroke="#C9C5D0" stroke-width="0.8"/>
|
||||
<path d="M-28 78L-24 80C-21.4819 81.2591 -18.5181 81.259 -16 80V80C-13.482 78.7409 -10.518 78.7409 -7.99999 80V80C-5.48195 81.259 -2.51804 81.259 8.58307e-06 80V80C2.51805 78.7409 5.48197 78.7409 8.00001 80V80C10.518 81.259 13.482 81.2591 16 80V80C18.5181 78.741 21.4951 78.7476 24.0131 80.0066V80.0066C26.5181 81.2591 29.4764 81.281 31.9943 80.0547L32.3036 79.9041C34.7646 78.7055 37.6464 78.7363 40.0813 79.987V79.987C42.5446 81.2524 45.4634 81.2683 47.9404 80.0298L48.0271 79.9865C50.5281 78.736 53.4854 78.7427 55.9864 79.9932V79.9932C58.5045 81.2522 61.4849 81.2576 64.0029 79.9986V79.9986C66.5181 78.741 69.5108 78.751 72.0289 80.0027V80.0027C74.5398 81.2509 77.522 81.2603 80.0284 80.0034V80.0034C82.5424 78.7427 85.5043 78.7416 88.019 80.0008V80.0008C90.5321 81.2591 93.4913 81.2591 96.0044 80.0008L100 78" stroke="#C9C5D0" stroke-width="0.8"/>
|
||||
<path d="M-28 82L-24 84C-21.4819 85.2591 -18.5181 85.259 -16 84V84C-13.482 82.7409 -10.518 82.7409 -7.99999 84V84C-5.48195 85.259 -2.51804 85.259 8.58307e-06 84V84C2.51805 82.7409 5.48197 82.7409 8.00001 84V84C10.518 85.259 13.482 85.2591 16 84V84C18.5181 82.741 21.4951 82.7476 24.0131 84.0066V84.0066C26.5181 85.2591 29.4764 85.281 31.9943 84.0547L32.3036 83.9041C34.7646 82.7055 37.6464 82.7363 40.0813 83.987V83.987C42.5446 85.2524 45.4634 85.2683 47.9404 84.0298L48.0271 83.9865C50.5281 82.736 53.4854 82.7427 55.9864 83.9932V83.9932C58.5045 85.2522 61.4849 85.2576 64.0029 83.9986V83.9986C66.5181 82.741 69.5108 82.751 72.0289 84.0027V84.0027C74.5398 85.2509 77.522 85.2603 80.0284 84.0034V84.0034C82.5424 82.7427 85.5043 82.7416 88.019 84.0008V84.0008C90.5321 85.2591 93.4913 85.2591 96.0044 84.0008L100 82" stroke="#C9C5D0" stroke-width="0.8"/>
|
||||
<path d="M-28 86L-24 88C-21.4819 89.2591 -18.5181 89.259 -16 88V88C-13.482 86.7409 -10.518 86.7409 -7.99999 88V88C-5.48195 89.259 -2.51804 89.259 8.58307e-06 88V88C2.51805 86.7409 5.48197 86.7409 8.00001 88V88C10.518 89.259 13.482 89.2591 16 88V88C18.5181 86.741 21.4951 86.7476 24.0131 88.0066V88.0066C26.5181 89.2591 29.4764 89.281 31.9943 88.0547L32.3036 87.9041C34.7646 86.7055 37.6464 86.7363 40.0813 87.987V87.987C42.5446 89.2524 45.4634 89.2683 47.9404 88.0298L48.0271 87.9865C50.5281 86.736 53.4854 86.7427 55.9864 87.9932V87.9932C58.5045 89.2522 61.4849 89.2576 64.0029 87.9986V87.9986C66.5181 86.741 69.5108 86.751 72.0289 88.0027V88.0027C74.5398 89.2509 77.522 89.2603 80.0284 88.0034V88.0034C82.5424 86.7427 85.5043 86.7416 88.019 88.0008V88.0008C90.5321 89.2591 93.4913 89.2591 96.0044 88.0008L100 86" stroke="#C9C5D0" stroke-width="0.8"/>
|
||||
<path d="M-28 90L-24 92C-21.4819 93.2591 -18.5181 93.259 -16 92V92C-13.482 90.7409 -10.518 90.7409 -7.99999 92V92C-5.48195 93.259 -2.51804 93.259 8.58307e-06 92V92C2.51805 90.7409 5.48197 90.7409 8.00001 92V92C10.518 93.259 13.482 93.2591 16 92V92C18.5181 90.741 21.4951 90.7476 24.0131 92.0066V92.0066C26.5181 93.2591 29.4764 93.281 31.9943 92.0547L32.3036 91.9041C34.7646 90.7055 37.6464 90.7363 40.0813 91.987V91.987C42.5446 93.2524 45.4634 93.2683 47.9404 92.0298L48.0271 91.9865C50.5281 90.736 53.4854 90.7427 55.9864 91.9932V91.9932C58.5045 93.2522 61.4849 93.2576 64.0029 91.9986V91.9986C66.5181 90.741 69.5108 90.751 72.0289 92.0027V92.0027C74.5398 93.2509 77.522 93.2603 80.0284 92.0034V92.0034C82.5424 90.7427 85.5043 90.7416 88.019 92.0008V92.0008C90.5321 93.2591 93.4913 93.2591 96.0044 92.0008L100 90" stroke="#C9C5D0" stroke-width="0.8"/>
|
||||
<path d="M-28 94L-24 96C-21.4819 97.2591 -18.5181 97.259 -16 96V96C-13.482 94.7409 -10.518 94.7409 -7.99999 96V96C-5.48195 97.259 -2.51804 97.259 8.58307e-06 96V96C2.51805 94.7409 5.48197 94.7409 8.00001 96V96C10.518 97.259 13.482 97.2591 16 96V96C18.5181 94.741 21.4951 94.7476 24.0131 96.0066V96.0066C26.5181 97.2591 29.4764 97.281 31.9943 96.0547L32.3036 95.9041C34.7646 94.7055 37.6464 94.7363 40.0813 95.987V95.987C42.5446 97.2524 45.4634 97.2683 47.9404 96.0298L48.0271 95.9865C50.5281 94.736 53.4854 94.7427 55.9864 95.9932V95.9932C58.5045 97.2522 61.4849 97.2576 64.0029 95.9986V95.9986C66.5181 94.741 69.5108 94.751 72.0289 96.0027V96.0027C74.5398 97.2509 77.522 97.2603 80.0284 96.0034V96.0034C82.5424 94.7427 85.5043 94.7416 88.019 96.0008V96.0008C90.5321 97.2591 93.4913 97.2591 96.0044 96.0008L100 94" stroke="#C9C5D0" stroke-width="0.8"/>
|
||||
<path d="M-28 98L-24 100C-21.4819 101.259 -18.5181 101.259 -16 100V100C-13.482 98.7409 -10.518 98.7409 -7.99999 100V100C-5.48195 101.259 -2.51804 101.259 8.58307e-06 100V100C2.51805 98.7409 5.48197 98.7409 8.00001 100V100C10.518 101.259 13.482 101.259 16 100V100C18.5181 98.741 21.4951 98.7476 24.0131 100.007V100.007C26.5181 101.259 29.4764 101.281 31.9943 100.055L32.3036 99.9041C34.7646 98.7055 37.6464 98.7363 40.0813 99.987V99.987C42.5446 101.252 45.4634 101.268 47.9404 100.03L48.0271 99.9865C50.5281 98.736 53.4854 98.7427 55.9864 99.9932V99.9932C58.5045 101.252 61.4849 101.258 64.0029 99.9986V99.9986C66.5181 98.741 69.5108 98.751 72.0289 100.003V100.003C74.5398 101.251 77.522 101.26 80.0284 100.003V100.003C82.5424 98.7427 85.5043 98.7416 88.019 100.001V100.001C90.5321 101.259 93.4913 101.259 96.0044 100.001L100 98" stroke="#C9C5D0" stroke-width="0.8"/>
|
||||
<path d="M-28 102L-24 104C-21.4819 105.259 -18.5181 105.259 -16 104V104C-13.482 102.741 -10.518 102.741 -7.99999 104V104C-5.48195 105.259 -2.51804 105.259 8.58307e-06 104V104C2.51805 102.741 5.48197 102.741 8.00001 104V104C10.518 105.259 13.482 105.259 16 104V104C18.5181 102.741 21.4951 102.748 24.0131 104.007V104.007C26.5181 105.259 29.4764 105.281 31.9943 104.055L32.3036 103.904C34.7646 102.706 37.6464 102.736 40.0813 103.987V103.987C42.5446 105.252 45.4634 105.268 47.9404 104.03L48.0271 103.986C50.5281 102.736 53.4854 102.743 55.9864 103.993V103.993C58.5045 105.252 61.4849 105.258 64.0029 103.999V103.999C66.5181 102.741 69.5108 102.751 72.0289 104.003V104.003C74.5398 105.251 77.522 105.26 80.0284 104.003V104.003C82.5424 102.743 85.5043 102.742 88.019 104.001V104.001C90.5321 105.259 93.4913 105.259 96.0044 104.001L100 102" stroke="#C9C5D0" stroke-width="0.8"/>
|
||||
<path d="M-28 106L-24 108C-21.4819 109.259 -18.5181 109.259 -16 108V108C-13.482 106.741 -10.518 106.741 -7.99999 108V108C-5.48195 109.259 -2.51804 109.259 8.58307e-06 108V108C2.51805 106.741 5.48197 106.741 8.00001 108V108C10.518 109.259 13.482 109.259 16 108V108C18.5181 106.741 21.4951 106.748 24.0131 108.007V108.007C26.5181 109.259 29.4764 109.281 31.9943 108.055L32.3036 107.904C34.7646 106.706 37.6464 106.736 40.0813 107.987V107.987C42.5446 109.252 45.4634 109.268 47.9404 108.03L48.0271 107.986C50.5281 106.736 53.4854 106.743 55.9864 107.993V107.993C58.5045 109.252 61.4849 109.258 64.0029 107.999V107.999C66.5181 106.741 69.5108 106.751 72.0289 108.003V108.003C74.5398 109.251 77.522 109.26 80.0284 108.003V108.003C82.5424 106.743 85.5043 106.742 88.019 108.001V108.001C90.5321 109.259 93.4913 109.259 96.0044 108.001L100 106" stroke="#C9C5D0" stroke-width="0.8"/>
|
||||
<path d="M-28 110L-24 112C-21.4819 113.259 -18.5181 113.259 -16 112V112C-13.482 110.741 -10.518 110.741 -7.99999 112V112C-5.48195 113.259 -2.51804 113.259 8.58307e-06 112V112C2.51805 110.741 5.48197 110.741 8.00001 112V112C10.518 113.259 13.482 113.259 16 112V112C18.5181 110.741 21.4951 110.748 24.0131 112.007V112.007C26.5181 113.259 29.4764 113.281 31.9943 112.055L32.3036 111.904C34.7646 110.706 37.6464 110.736 40.0813 111.987V111.987C42.5446 113.252 45.4634 113.268 47.9404 112.03L48.0271 111.986C50.5281 110.736 53.4854 110.743 55.9864 111.993V111.993C58.5045 113.252 61.4849 113.258 64.0029 111.999V111.999C66.5181 110.741 69.5108 110.751 72.0289 112.003V112.003C74.5398 113.251 77.522 113.26 80.0284 112.003V112.003C82.5424 110.743 85.5043 110.742 88.019 112.001V112.001C90.5321 113.259 93.4913 113.259 96.0044 112.001L100 110" stroke="#C9C5D0" stroke-width="0.8"/>
|
||||
<path d="M-28 114L-24 116C-21.4819 117.259 -18.5181 117.259 -16 116V116C-13.482 114.741 -10.518 114.741 -7.99999 116V116C-5.48195 117.259 -2.51804 117.259 8.58307e-06 116V116C2.51805 114.741 5.48197 114.741 8.00001 116V116C10.518 117.259 13.482 117.259 16 116V116C18.5181 114.741 21.4951 114.748 24.0131 116.007V116.007C26.5181 117.259 29.4764 117.281 31.9943 116.055L32.3036 115.904C34.7646 114.706 37.6464 114.736 40.0813 115.987V115.987C42.5446 117.252 45.4634 117.268 47.9404 116.03L48.0271 115.986C50.5281 114.736 53.4854 114.743 55.9864 115.993V115.993C58.5045 117.252 61.4849 117.258 64.0029 115.999V115.999C66.5181 114.741 69.5108 114.751 72.0289 116.003V116.003C74.5398 117.251 77.522 117.26 80.0284 116.003V116.003C82.5424 114.743 85.5043 114.742 88.019 116.001V116.001C90.5321 117.259 93.4913 117.259 96.0044 116.001L100 114" stroke="#C9C5D0" stroke-width="0.8"/>
|
||||
<path d="M-28 118L-24 120C-21.4819 121.259 -18.5181 121.259 -16 120V120C-13.482 118.741 -10.518 118.741 -7.99999 120V120C-5.48195 121.259 -2.51804 121.259 8.58307e-06 120V120C2.51805 118.741 5.48197 118.741 8.00001 120V120C10.518 121.259 13.482 121.259 16 120V120C18.5181 118.741 21.4951 118.748 24.0131 120.007V120.007C26.5181 121.259 29.4764 121.281 31.9943 120.055L32.3036 119.904C34.7646 118.706 37.6464 118.736 40.0813 119.987V119.987C42.5446 121.252 45.4634 121.268 47.9404 120.03L48.0271 119.986C50.5281 118.736 53.4854 118.743 55.9864 119.993V119.993C58.5045 121.252 61.4849 121.258 64.0029 119.999V119.999C66.5181 118.741 69.5108 118.751 72.0289 120.003V120.003C74.5398 121.251 77.522 121.26 80.0284 120.003V120.003C82.5424 118.743 85.5043 118.742 88.019 120.001V120.001C90.5321 121.259 93.4913 121.259 96.0044 120.001L100 118" stroke="#C9C5D0" stroke-width="0.8"/>
|
||||
<path d="M-28 122L-24 124C-21.4819 125.259 -18.5181 125.259 -16 124V124C-13.482 122.741 -10.518 122.741 -7.99999 124V124C-5.48195 125.259 -2.51804 125.259 8.58307e-06 124V124C2.51805 122.741 5.48197 122.741 8.00001 124V124C10.518 125.259 13.482 125.259 16 124V124C18.5181 122.741 21.4951 122.748 24.0131 124.007V124.007C26.5181 125.259 29.4764 125.281 31.9943 124.055L32.3036 123.904C34.7646 122.706 37.6464 122.736 40.0813 123.987V123.987C42.5446 125.252 45.4634 125.268 47.9404 124.03L48.0271 123.986C50.5281 122.736 53.4854 122.743 55.9864 123.993V123.993C58.5045 125.252 61.4849 125.258 64.0029 123.999V123.999C66.5181 122.741 69.5108 122.751 72.0289 124.003V124.003C74.5398 125.251 77.522 125.26 80.0284 124.003V124.003C82.5424 122.743 85.5043 122.742 88.019 124.001V124.001C90.5321 125.259 93.4913 125.259 96.0044 124.001L100 122" stroke="#C9C5D0" stroke-width="0.8"/>
|
||||
<path d="M-28 126L-24 128C-21.4819 129.259 -18.5181 129.259 -16 128V128C-13.482 126.741 -10.518 126.741 -7.99999 128V128C-5.48195 129.259 -2.51804 129.259 8.58307e-06 128V128C2.51805 126.741 5.48197 126.741 8.00001 128V128C10.518 129.259 13.482 129.259 16 128V128C18.5181 126.741 21.4951 126.748 24.0131 128.007V128.007C26.5181 129.259 29.4764 129.281 31.9943 128.055L32.3036 127.904C34.7646 126.706 37.6464 126.736 40.0813 127.987V127.987C42.5446 129.252 45.4634 129.268 47.9404 128.03L48.0271 127.986C50.5281 126.736 53.4854 126.743 55.9864 127.993V127.993C58.5045 129.252 61.4849 129.258 64.0029 127.999V127.999C66.5181 126.741 69.5108 126.751 72.0289 128.003V128.003C74.5398 129.251 77.522 129.26 80.0284 128.003V128.003C82.5424 126.743 85.5043 126.742 88.019 128.001V128.001C90.5321 129.259 93.4913 129.259 96.0044 128.001L100 126" stroke="#C9C5D0" stroke-width="0.8"/>
|
||||
<path d="M-28 130L-24 132C-21.4819 133.259 -18.5181 133.259 -16 132V132C-13.482 130.741 -10.518 130.741 -7.99999 132V132C-5.48195 133.259 -2.51804 133.259 8.58307e-06 132V132C2.51805 130.741 5.48197 130.741 8.00001 132V132C10.518 133.259 13.482 133.259 16 132V132C18.5181 130.741 21.4951 130.748 24.0131 132.007V132.007C26.5181 133.259 29.4764 133.281 31.9943 132.055L32.3036 131.904C34.7646 130.706 37.6464 130.736 40.0813 131.987V131.987C42.5446 133.252 45.4634 133.268 47.9404 132.03L48.0271 131.986C50.5281 130.736 53.4854 130.743 55.9864 131.993V131.993C58.5045 133.252 61.4849 133.258 64.0029 131.999V131.999C66.5181 130.741 69.5108 130.751 72.0289 132.003V132.003C74.5398 133.251 77.522 133.26 80.0284 132.003V132.003C82.5424 130.743 85.5043 130.742 88.019 132.001V132.001C90.5321 133.259 93.4913 133.259 96.0044 132.001L100 130" stroke="#C9C5D0" stroke-width="0.8"/>
|
||||
<path d="M-28 134L-24 136C-21.4819 137.259 -18.5181 137.259 -16 136V136C-13.482 134.741 -10.518 134.741 -7.99999 136V136C-5.48195 137.259 -2.51804 137.259 8.58307e-06 136V136C2.51805 134.741 5.48197 134.741 8.00001 136V136C10.518 137.259 13.482 137.259 16 136V136C18.5181 134.741 21.4951 134.748 24.0131 136.007V136.007C26.5181 137.259 29.4764 137.281 31.9943 136.055L32.3036 135.904C34.7646 134.706 37.6464 134.736 40.0813 135.987V135.987C42.5446 137.252 45.4634 137.268 47.9404 136.03L48.0271 135.986C50.5281 134.736 53.4854 134.743 55.9864 135.993V135.993C58.5045 137.252 61.4849 137.258 64.0029 135.999V135.999C66.5181 134.741 69.5108 134.751 72.0289 136.003V136.003C74.5398 137.251 77.522 137.26 80.0284 136.003V136.003C82.5424 134.743 85.5043 134.742 88.019 136.001V136.001C90.5321 137.259 93.4913 137.259 96.0044 136.001L100 134" stroke="#C9C5D0" stroke-width="0.8"/>
|
||||
<path d="M-28 138L-24 140C-21.4819 141.259 -18.5181 141.259 -16 140V140C-13.482 138.741 -10.518 138.741 -7.99999 140V140C-5.48195 141.259 -2.51804 141.259 8.58307e-06 140V140C2.51805 138.741 5.48197 138.741 8.00001 140V140C10.518 141.259 13.482 141.259 16 140V140C18.5181 138.741 21.4951 138.748 24.0131 140.007V140.007C26.5181 141.259 29.4764 141.281 31.9943 140.055L32.3036 139.904C34.7646 138.706 37.6464 138.736 40.0813 139.987V139.987C42.5446 141.252 45.4634 141.268 47.9404 140.03L48.0271 139.986C50.5281 138.736 53.4854 138.743 55.9864 139.993V139.993C58.5045 141.252 61.4849 141.258 64.0029 139.999V139.999C66.5181 138.741 69.5108 138.751 72.0289 140.003V140.003C74.5398 141.251 77.522 141.26 80.0284 140.003V140.003C82.5424 138.743 85.5043 138.742 88.019 140.001V140.001C90.5321 141.259 93.4913 141.259 96.0044 140.001L100 138" stroke="#C9C5D0" stroke-width="0.8"/>
|
||||
<path d="M-28 142L-24 144C-21.4819 145.259 -18.5181 145.259 -16 144V144C-13.482 142.741 -10.518 142.741 -7.99999 144V144C-5.48195 145.259 -2.51804 145.259 8.58307e-06 144V144C2.51805 142.741 5.48197 142.741 8.00001 144V144C10.518 145.259 13.482 145.259 16 144V144C18.5181 142.741 21.4951 142.748 24.0131 144.007V144.007C26.5181 145.259 29.4764 145.281 31.9943 144.055L32.3036 143.904C34.7646 142.706 37.6464 142.736 40.0813 143.987V143.987C42.5446 145.252 45.4634 145.268 47.9404 144.03L48.0271 143.986C50.5281 142.736 53.4854 142.743 55.9864 143.993V143.993C58.5045 145.252 61.4849 145.258 64.0029 143.999V143.999C66.5181 142.741 69.5108 142.751 72.0289 144.003V144.003C74.5398 145.251 77.522 145.26 80.0284 144.003V144.003C82.5424 142.743 85.5043 142.742 88.019 144.001V144.001C90.5321 145.259 93.4913 145.259 96.0044 144.001L100 142" stroke="#C9C5D0" stroke-width="0.8"/>
|
||||
<path d="M-28 146L-24 148C-21.4819 149.259 -18.5181 149.259 -16 148V148C-13.482 146.741 -10.518 146.741 -7.99999 148V148C-5.48195 149.259 -2.51804 149.259 8.58307e-06 148V148C2.51805 146.741 5.48197 146.741 8.00001 148V148C10.518 149.259 13.482 149.259 16 148V148C18.5181 146.741 21.4951 146.748 24.0131 148.007V148.007C26.5181 149.259 29.4764 149.281 31.9943 148.055L32.3036 147.904C34.7646 146.706 37.6464 146.736 40.0813 147.987V147.987C42.5446 149.252 45.4634 149.268 47.9404 148.03L48.0271 147.986C50.5281 146.736 53.4854 146.743 55.9864 147.993V147.993C58.5045 149.252 61.4849 149.258 64.0029 147.999V147.999C66.5181 146.741 69.5108 146.751 72.0289 148.003V148.003C74.5398 149.251 77.522 149.26 80.0284 148.003V148.003C82.5424 146.743 85.5043 146.742 88.019 148.001V148.001C90.5321 149.259 93.4913 149.259 96.0044 148.001L100 146" stroke="#C9C5D0" stroke-width="0.8"/>
|
||||
<path d="M-28 150L-24 152C-21.4819 153.259 -18.5181 153.259 -16 152V152C-13.482 150.741 -10.518 150.741 -7.99999 152V152C-5.48195 153.259 -2.51804 153.259 8.58307e-06 152V152C2.51805 150.741 5.48197 150.741 8.00001 152V152C10.518 153.259 13.482 153.259 16 152V152C18.5181 150.741 21.4951 150.748 24.0131 152.007V152.007C26.5181 153.259 29.4764 153.281 31.9943 152.055L32.3036 151.904C34.7646 150.706 37.6464 150.736 40.0813 151.987V151.987C42.5446 153.252 45.4634 153.268 47.9404 152.03L48.0271 151.986C50.5281 150.736 53.4854 150.743 55.9864 151.993V151.993C58.5045 153.252 61.4849 153.258 64.0029 151.999V151.999C66.5181 150.741 69.5108 150.751 72.0289 152.003V152.003C74.5398 153.251 77.522 153.26 80.0284 152.003V152.003C82.5424 150.743 85.5043 150.742 88.019 152.001V152.001C90.5321 153.259 93.4913 153.259 96.0044 152.001L100 150" stroke="#C9C5D0" stroke-width="0.8"/>
|
||||
<path d="M-28 154L-24 156C-21.4819 157.259 -18.5181 157.259 -16 156V156C-13.482 154.741 -10.518 154.741 -7.99999 156V156C-5.48195 157.259 -2.51804 157.259 8.58307e-06 156V156C2.51805 154.741 5.48197 154.741 8.00001 156V156C10.518 157.259 13.482 157.259 16 156V156C18.5181 154.741 21.4951 154.748 24.0131 156.007V156.007C26.5181 157.259 29.4764 157.281 31.9943 156.055L32.3036 155.904C34.7646 154.706 37.6464 154.736 40.0813 155.987V155.987C42.5446 157.252 45.4634 157.268 47.9404 156.03L48.0271 155.986C50.5281 154.736 53.4854 154.743 55.9864 155.993V155.993C58.5045 157.252 61.4849 157.258 64.0029 155.999V155.999C66.5181 154.741 69.5108 154.751 72.0289 156.003V156.003C74.5398 157.251 77.522 157.26 80.0284 156.003V156.003C82.5424 154.743 85.5043 154.742 88.019 156.001V156.001C90.5321 157.259 93.4913 157.259 96.0044 156.001L100 154" stroke="#C9C5D0" stroke-width="0.8"/>
|
||||
<path d="M-28 158L-24 160C-21.4819 161.259 -18.5181 161.259 -16 160V160C-13.482 158.741 -10.518 158.741 -7.99999 160V160C-5.48195 161.259 -2.51804 161.259 8.58307e-06 160V160C2.51805 158.741 5.48197 158.741 8.00001 160V160C10.518 161.259 13.482 161.259 16 160V160C18.5181 158.741 21.4951 158.748 24.0131 160.007V160.007C26.5181 161.259 29.4764 161.281 31.9943 160.055L32.3036 159.904C34.7646 158.706 37.6464 158.736 40.0813 159.987V159.987C42.5446 161.252 45.4634 161.268 47.9404 160.03L48.0271 159.986C50.5281 158.736 53.4854 158.743 55.9864 159.993V159.993C58.5045 161.252 61.4849 161.258 64.0029 159.999V159.999C66.5181 158.741 69.5108 158.751 72.0289 160.003V160.003C74.5398 161.251 77.522 161.26 80.0284 160.003V160.003C82.5424 158.743 85.5043 158.742 88.019 160.001V160.001C90.5321 161.259 93.4913 161.259 96.0044 160.001L100 158" stroke="#C9C5D0" stroke-width="0.8"/>
|
||||
<path d="M-28 162L-24 164C-21.4819 165.259 -18.5181 165.259 -16 164V164C-13.482 162.741 -10.518 162.741 -7.99999 164V164C-5.48195 165.259 -2.51804 165.259 8.58307e-06 164V164C2.51805 162.741 5.48197 162.741 8.00001 164V164C10.518 165.259 13.482 165.259 16 164V164C18.5181 162.741 21.4951 162.748 24.0131 164.007V164.007C26.5181 165.259 29.4764 165.281 31.9943 164.055L32.3036 163.904C34.7646 162.706 37.6464 162.736 40.0813 163.987V163.987C42.5446 165.252 45.4634 165.268 47.9404 164.03L48.0271 163.986C50.5281 162.736 53.4854 162.743 55.9864 163.993V163.993C58.5045 165.252 61.4849 165.258 64.0029 163.999V163.999C66.5181 162.741 69.5108 162.751 72.0289 164.003V164.003C74.5398 165.251 77.522 165.26 80.0284 164.003V164.003C82.5424 162.743 85.5043 162.742 88.019 164.001V164.001C90.5321 165.259 93.4913 165.259 96.0044 164.001L100 162" stroke="#C9C5D0" stroke-width="0.8"/>
|
||||
</g>
|
||||
<g style="mix-blend-mode:multiply">
|
||||
<rect x="143.453" y="24" width="24" height="24" rx="6" transform="rotate(50.249 143.453 24)" fill="#C9C5D0"/>
|
||||
</g>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M181.914 0.208615C181.914 0.0934007 182.008 0 182.123 0H185.878C185.993 0 186.087 0.0933997 186.087 0.208614V6.81728L191.81 3.513C191.91 3.45539 192.037 3.48958 192.095 3.58936L193.972 6.84133C194.03 6.94111 193.996 7.06869 193.896 7.1263L188.172 10.4308L193.896 13.7351C193.995 13.7927 194.03 13.9203 193.972 14.0201L192.094 17.272C192.037 17.3718 191.909 17.406 191.81 17.3484L186.087 14.0443V20.6528C186.087 20.768 185.993 20.8614 185.878 20.8614H182.123C182.008 20.8614 181.914 20.768 181.914 20.6528V14.0439L176.191 17.3484C176.091 17.406 175.963 17.3718 175.906 17.272L174.028 14.0201C173.971 13.9203 174.005 13.7927 174.105 13.7351L179.828 10.4308L174.104 7.1263C174.005 7.06869 173.97 6.94111 174.028 6.84133L175.906 3.58936C175.963 3.48958 176.091 3.45539 176.19 3.513L181.914 6.8177V0.208615Z" fill="#E5E1EC"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M8 25C12.4183 25 16 21.4183 16 17C16 12.5817 12.4183 9 8 9C3.58172 9 0 12.5817 0 17C0 21.4183 3.58172 25 8 25ZM8 21C10.2091 21 12 19.2091 12 17C12 14.7909 10.2091 13 8 13C5.79086 13 4 14.7909 4 17C4 19.2091 5.79086 21 8 21Z" fill="#F3EFFA"/>
|
||||
<g style="mix-blend-mode:multiply">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M170 162C176.627 162 182 156.627 182 150C182 143.373 176.627 138 170 138C163.373 138 158 143.373 158 150C158 156.627 163.373 162 170 162ZM170 156C173.314 156 176 153.314 176 150C176 146.686 173.314 144 170 144C166.686 144 164 146.686 164 150C164 153.314 166.686 156 170 156Z" fill="#E5E1EC"/>
|
||||
</g>
|
||||
<path d="M52.3049 25.602C51.2391 22.7131 53.7004 19.7538 56.7351 20.2753L61.2872 21.0576C64.3219 21.5791 65.6541 25.1902 63.6851 27.5576L60.7316 31.1087C58.7626 33.4761 54.9692 32.8242 53.9034 29.9353L52.3049 25.602Z" fill="#F3EFFA"/>
|
||||
<rect x="51" y="192" width="80" height="4" rx="2" fill="#C9C5D0"/>
|
||||
<rect x="143" y="192" width="19" height="4" rx="2" fill="#C9C5D0"/>
|
||||
</svg>
|
After Width: | Height: | Size: 26 KiB |
|
@ -0,0 +1,4 @@
|
|||
<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M16.9507 10.293C16.5602 9.90248 15.927 9.90248 15.5365 10.293L12.001 13.8285L8.46544 10.293C8.07492 9.90248 7.44175 9.90248 7.05123 10.293C6.6607 10.6835 6.6607 11.3167 7.05123 11.7072L11.2939 15.9499C11.6844 16.3404 12.3176 16.3404 12.7081 15.9499L16.9507 11.7072C17.3412 11.3167 17.3412 10.6835 16.9507 10.293Z" fill="currentcolor"/>
|
||||
<circle cx="12" cy="12" r="11" stroke="currentcolor" stroke-width="2"/>
|
||||
</svg>
|
After Width: | Height: | Size: 541 B |
|
@ -0,0 +1,4 @@
|
|||
<svg width="20" height="20" viewBox="0 0 20 20" fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M13.575 11.9083L9.99999 15.4916L6.42499 11.9083C6.26807 11.7514 6.05524 11.6632 5.83333 11.6632C5.61141 11.6632 5.39858 11.7514 5.24166 11.9083C5.08474 12.0652 4.99658 12.278 4.99658 12.4999C4.99658 12.7219 5.08474 12.9347 5.24166 13.0916L9.40833 17.2583C9.48579 17.3364 9.57796 17.3984 9.67951 17.4407C9.78106 17.483 9.88998 17.5048 9.99999 17.5048C10.11 17.5048 10.2189 17.483 10.3205 17.4407C10.422 17.3984 10.5142 17.3364 10.5917 17.2583L14.7583 13.0916C14.836 13.0139 14.8977 12.9217 14.9397 12.8202C14.9818 12.7186 15.0034 12.6098 15.0034 12.4999C15.0034 12.3901 14.9818 12.2813 14.9397 12.1797C14.8977 12.0782 14.836 11.986 14.7583 11.9083C14.6806 11.8306 14.5884 11.7689 14.4869 11.7269C14.3853 11.6848 14.2765 11.6632 14.1667 11.6632C14.0568 11.6632 13.948 11.6848 13.8465 11.7269C13.7449 11.7689 13.6527 11.8306 13.575 11.9083ZM6.42499 8.09162L9.99999 4.50828L13.575 8.09162C13.6525 8.16972 13.7446 8.23172 13.8462 8.27402C13.9477 8.31633 14.0566 8.33811 14.1667 8.33811C14.2767 8.33811 14.3856 8.31633 14.4871 8.27402C14.5887 8.23172 14.6809 8.16972 14.7583 8.09162C14.8364 8.01415 14.8984 7.92198 14.9407 7.82043C14.983 7.71888 15.0048 7.60996 15.0048 7.49995C15.0048 7.38994 14.983 7.28102 14.9407 7.17947C14.8984 7.07792 14.8364 6.98575 14.7583 6.90828L10.5917 2.74162C10.5142 2.66351 10.422 2.60151 10.3205 2.55921C10.2189 2.5169 10.11 2.49512 9.99999 2.49512C9.88998 2.49512 9.78106 2.5169 9.67951 2.55921C9.57796 2.60151 9.48579 2.66351 9.40833 2.74162L5.24166 6.90828C5.08474 7.0652 4.99658 7.27803 4.99658 7.49995C4.99658 7.72187 5.08474 7.9347 5.24166 8.09162C5.39858 8.24854 5.61141 8.33669 5.83333 8.33669C6.05524 8.33669 6.26807 8.24854 6.42499 8.09162Z" fill="currentcolor" />
|
||||
</svg>
|
After Width: | Height: | Size: 1.8 KiB |
|
@ -0,0 +1,3 @@
|
|||
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M10 16.6666H4.16666C3.94565 16.6666 3.73369 16.5788 3.57741 16.4225C3.42113 16.2663 3.33333 16.0543 3.33333 15.8333V4.16663C3.33333 3.94561 3.42113 3.73365 3.57741 3.57737C3.73369 3.42109 3.94565 3.33329 4.16666 3.33329H8.33333V5.83329C8.33333 6.49633 8.59672 7.13222 9.06556 7.60106C9.5344 8.0699 10.1703 8.33329 10.8333 8.33329H13.3333V9.16663C13.3333 9.38764 13.4211 9.5996 13.5774 9.75588C13.7337 9.91216 13.9457 9.99996 14.1667 9.99996C14.3877 9.99996 14.5996 9.91216 14.7559 9.75588C14.9122 9.5996 15 9.38764 15 9.16663V7.49996C15 7.49996 15 7.49996 15 7.44996C14.9913 7.3734 14.9746 7.29799 14.95 7.22496V7.14996C14.9099 7.06428 14.8565 6.98551 14.7917 6.91663L9.79166 1.91663C9.72278 1.85181 9.64401 1.79836 9.55833 1.75829C9.53346 1.75476 9.50821 1.75476 9.48333 1.75829C9.39868 1.70974 9.30518 1.67858 9.20833 1.66663H4.16666C3.50362 1.66663 2.86774 1.93002 2.3989 2.39886C1.93006 2.8677 1.66666 3.50358 1.66666 4.16663V15.8333C1.66666 16.4963 1.93006 17.1322 2.3989 17.6011C2.86774 18.0699 3.50362 18.3333 4.16666 18.3333H10C10.221 18.3333 10.433 18.2455 10.5893 18.0892C10.7455 17.9329 10.8333 17.721 10.8333 17.5C10.8333 17.2789 10.7455 17.067 10.5893 16.9107C10.433 16.7544 10.221 16.6666 10 16.6666ZM10 4.50829L12.1583 6.66663H10.8333C10.6123 6.66663 10.4004 6.57883 10.2441 6.42255C10.0878 6.26627 10 6.05431 10 5.83329V4.50829ZM5.83333 6.66663C5.61232 6.66663 5.40036 6.75442 5.24408 6.9107C5.0878 7.06698 5 7.27895 5 7.49996C5 7.72097 5.0878 7.93293 5.24408 8.08922C5.40036 8.2455 5.61232 8.33329 5.83333 8.33329H6.66666C6.88768 8.33329 7.09964 8.2455 7.25592 8.08922C7.4122 7.93293 7.5 7.72097 7.5 7.49996C7.5 7.27895 7.4122 7.06698 7.25592 6.9107C7.09964 6.75442 6.88768 6.66663 6.66666 6.66663H5.83333ZM18.0917 16.9083L17.1167 15.9416C17.4283 15.3977 17.553 14.7666 17.4718 14.1449C17.3905 13.5233 17.1077 12.9455 16.6667 12.5C16.2609 12.0797 15.7379 11.7914 15.1659 11.6726C14.5938 11.5538 13.9993 11.61 13.4597 11.8339C12.9201 12.0579 12.4605 12.4391 12.1406 12.928C11.8208 13.4169 11.6557 13.9908 11.6667 14.575C11.6638 15.0776 11.7924 15.5723 12.0397 16.0099C12.287 16.4475 12.6444 16.8129 13.0764 17.0698C13.5085 17.3267 14.0002 17.4661 14.5028 17.4744C15.0054 17.4826 15.5014 17.3593 15.9417 17.1166L16.9083 18.0916C16.9858 18.1697 17.078 18.2317 17.1795 18.274C17.2811 18.3163 17.39 18.3381 17.5 18.3381C17.61 18.3381 17.7189 18.3163 17.8205 18.274C17.922 18.2317 18.0142 18.1697 18.0917 18.0916C18.1698 18.0142 18.2318 17.922 18.2741 17.8204C18.3164 17.7189 18.3382 17.61 18.3382 17.5C18.3382 17.3899 18.3164 17.281 18.2741 17.1795C18.2318 17.0779 18.1698 16.9858 18.0917 16.9083ZM15.45 15.45C15.212 15.6738 14.8976 15.7984 14.5708 15.7984C14.2441 15.7984 13.9297 15.6738 13.6917 15.45C13.4623 15.2165 13.3336 14.9023 13.3333 14.575C13.3316 14.4106 13.3632 14.2476 13.4262 14.0958C13.4892 13.9439 13.5824 13.8065 13.7 13.6916C13.9222 13.4707 14.2201 13.3425 14.5333 13.3333C14.7018 13.3229 14.8706 13.3475 15.0291 13.4055C15.1877 13.4634 15.3325 13.5535 15.4546 13.6701C15.5766 13.7867 15.6733 13.9273 15.7385 14.083C15.8037 14.2387 15.8359 14.4062 15.8333 14.575C15.8264 14.9059 15.6886 15.2205 15.45 15.45ZM10.8333 9.99996H5.83333C5.61232 9.99996 5.40036 10.0878 5.24408 10.244C5.0878 10.4003 5 10.6123 5 10.8333C5 11.0543 5.0878 11.2663 5.24408 11.4225C5.40036 11.5788 5.61232 11.6666 5.83333 11.6666H10.8333C11.0543 11.6666 11.2663 11.5788 11.4226 11.4225C11.5789 11.2663 11.6667 11.0543 11.6667 10.8333C11.6667 10.6123 11.5789 10.4003 11.4226 10.244C11.2663 10.0878 11.0543 9.99996 10.8333 9.99996ZM9.16666 15C9.38768 15 9.59964 14.9122 9.75592 14.7559C9.9122 14.5996 10 14.3876 10 14.1666C10 13.9456 9.9122 13.7337 9.75592 13.5774C9.59964 13.4211 9.38768 13.3333 9.16666 13.3333H5.83333C5.61232 13.3333 5.40036 13.4211 5.24408 13.5774C5.0878 13.7337 5 13.9456 5 14.1666C5 14.3876 5.0878 14.5996 5.24408 14.7559C5.40036 14.9122 5.61232 15 5.83333 15H9.16666Z" fill="currentColor"/>
|
||||
</svg>
|
After Width: | Height: | Size: 3.9 KiB |
|
@ -0,0 +1,3 @@
|
|||
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M17.5001 1.66663H12.5001C12.2791 1.66663 12.0671 1.75442 11.9108 1.9107C11.7545 2.06698 11.6667 2.27895 11.6667 2.49996C11.6667 2.72097 11.7545 2.93293 11.9108 3.08922C12.0671 3.2455 12.2791 3.33329 12.5001 3.33329H16.6667V7.49996C16.6667 7.72097 16.7545 7.93293 16.9108 8.08922C17.0671 8.2455 17.2791 8.33329 17.5001 8.33329C17.7211 8.33329 17.9331 8.2455 18.0893 8.08922C18.2456 7.93293 18.3334 7.72097 18.3334 7.49996V2.49996C18.3334 2.27895 18.2456 2.06698 18.0893 1.9107C17.9331 1.75442 17.7211 1.66663 17.5001 1.66663ZM17.5001 11.6666C17.2791 11.6666 17.0671 11.7544 16.9108 11.9107C16.7545 12.067 16.6667 12.2789 16.6667 12.5V16.6666H12.5001C12.2791 16.6666 12.0671 16.7544 11.9108 16.9107C11.7545 17.067 11.6667 17.2789 11.6667 17.5C11.6667 17.721 11.7545 17.9329 11.9108 18.0892C12.0671 18.2455 12.2791 18.3333 12.5001 18.3333H17.5001C17.7211 18.3333 17.9331 18.2455 18.0893 18.0892C18.2456 17.9329 18.3334 17.721 18.3334 17.5V12.5C18.3334 12.2789 18.2456 12.067 18.0893 11.9107C17.9331 11.7544 17.7211 11.6666 17.5001 11.6666ZM10.0001 4.99996C9.33704 4.99996 8.70116 5.26335 8.23231 5.73219C7.76347 6.20103 7.50008 6.83692 7.50008 7.49996V8.33329C7.05805 8.33329 6.63413 8.50889 6.32157 8.82145C6.00901 9.13401 5.83342 9.55793 5.83342 9.99996V13.3333C5.83342 13.7753 6.00901 14.1992 6.32157 14.5118C6.63413 14.8244 7.05805 15 7.50008 15H12.5001C12.9421 15 13.366 14.8244 13.6786 14.5118C13.9912 14.1992 14.1667 13.7753 14.1667 13.3333V9.99996C14.1667 9.55793 13.9912 9.13401 13.6786 8.82145C13.366 8.50889 12.9421 8.33329 12.5001 8.33329V7.49996C12.5001 6.83692 12.2367 6.20103 11.7678 5.73219C11.299 5.26335 10.6631 4.99996 10.0001 4.99996ZM9.16675 7.49996C9.16675 7.27895 9.25455 7.06698 9.41083 6.9107C9.56711 6.75442 9.77907 6.66663 10.0001 6.66663C10.2211 6.66663 10.4331 6.75442 10.5893 6.9107C10.7456 7.06698 10.8334 7.27895 10.8334 7.49996V8.33329H9.16675V7.49996ZM12.5001 13.3333H7.50008V9.99996H12.5001V13.3333ZM2.50008 8.33329C2.7211 8.33329 2.93306 8.2455 3.08934 8.08922C3.24562 7.93293 3.33341 7.72097 3.33341 7.49996V3.33329H7.50008C7.7211 3.33329 7.93306 3.2455 8.08934 3.08922C8.24562 2.93293 8.33342 2.72097 8.33342 2.49996C8.33342 2.27895 8.24562 2.06698 8.08934 1.9107C7.93306 1.75442 7.7211 1.66663 7.50008 1.66663H2.50008C2.27907 1.66663 2.06711 1.75442 1.91083 1.9107C1.75455 2.06698 1.66675 2.27895 1.66675 2.49996V7.49996C1.66675 7.72097 1.75455 7.93293 1.91083 8.08922C2.06711 8.2455 2.27907 8.33329 2.50008 8.33329ZM7.50008 16.6666H3.33341V12.5C3.33341 12.2789 3.24562 12.067 3.08934 11.9107C2.93306 11.7544 2.7211 11.6666 2.50008 11.6666C2.27907 11.6666 2.06711 11.7544 1.91083 11.9107C1.75455 12.067 1.66675 12.2789 1.66675 12.5V17.5C1.66675 17.721 1.75455 17.9329 1.91083 18.0892C2.06711 18.2455 2.27907 18.3333 2.50008 18.3333H7.50008C7.7211 18.3333 7.93306 18.2455 8.08934 18.0892C8.24562 17.9329 8.33342 17.721 8.33342 17.5C8.33342 17.2789 8.24562 17.067 8.08934 16.9107C7.93306 16.7544 7.7211 16.6666 7.50008 16.6666Z" fill="currentColor"/>
|
||||
</svg>
|
After Width: | Height: | Size: 3 KiB |
|
@ -0,0 +1,19 @@
|
|||
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_1158_5594)">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M10 2.91659C10 2.68647 9.81345 2.49992 9.58333 2.49992H4.58333C4.35321 2.49992 4.16667 2.68647 4.16667 2.91659V5.83325H10V2.91659ZM4.16667 0.833252C3.24619 0.833252 2.5 1.57944 2.5 2.49992V5.83325C2.5 6.75373 3.24619 6.66658 4.16667 6.66658H10C10.9205 6.66658 11.6667 6.75373 11.6667 5.83325V2.49992C11.6667 1.57944 10.9205 0.833252 10 0.833252H4.16667Z" fill="currentColor"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M0.833336 7.49992C0.833336 6.57944 1.57953 5.83325 2.5 5.83325H11.6667C12.5871 5.83325 13.3333 6.57944 13.3333 7.49992L2.91667 7.49992C2.68655 7.49992 2.5 7.68647 2.5 7.91659V17.0833C2.5 17.3134 2.68655 17.4999 2.91667 17.4999H5C5.46024 17.4999 5.83334 17.873 5.83334 18.3333C5.83334 18.7935 5.46024 19.1666 5 19.1666H2.5C1.57953 19.1666 0.833336 18.4204 0.833336 17.4999V7.49992Z" fill="currentColor"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M5.83334 4.99992C5.3731 4.99992 5.00001 4.62682 5.00001 4.16659C5.00001 3.70635 5.3731 3.33325 5.83334 3.33325C6.29358 3.33325 6.66667 3.70635 6.66667 4.16659C6.66667 4.62682 6.29358 4.99992 5.83334 4.99992Z" fill="currentColor"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M8.33334 4.99992C7.8731 4.99992 7.5 4.62682 7.5 4.16659C7.5 3.70635 7.8731 3.33325 8.33334 3.33325C8.79358 3.33325 9.16667 3.70635 9.16667 4.16659C9.16667 4.62682 8.79358 4.99992 8.33334 4.99992Z" fill="currentColor"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M13.75 9.99992C11.6024 9.99992 10 11.5653 10 13.3333V18.3333C10 18.7935 9.62691 19.1666 9.16667 19.1666C8.70643 19.1666 8.33334 18.7935 8.33334 18.3333V13.3333C8.33334 10.4989 10.835 8.33325 13.75 8.33325C16.665 8.33325 19.1667 10.4989 19.1667 13.3333V14.9999C19.1667 15.4602 18.7936 15.8333 18.3333 15.8333C17.8731 15.8333 17.5 15.4602 17.5 14.9999V13.3333C17.5 11.5653 15.8976 9.99992 13.75 9.99992Z" fill="currentColor"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M13.75 12.4999C14.5169 12.4999 15 13.0477 15 13.5605V18.3333C15 18.7935 15.3731 19.1666 15.8333 19.1666C16.2936 19.1666 16.6667 18.7935 16.6667 18.3333V13.5605C16.6667 11.9813 15.2843 10.8333 13.75 10.8333C12.2157 10.8333 10.8333 11.9813 10.8333 13.5605V14.3181C10.8333 14.7783 11.2064 15.1514 11.6667 15.1514C12.1269 15.1514 12.5 14.7783 12.5 14.3181V13.5605C12.5 13.0477 12.9831 12.4999 13.75 12.4999Z" fill="currentColor"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M18.3333 16.6665C18.7936 16.6665 19.1667 17.0396 19.1667 17.4998L19.1667 18.3332C19.1667 18.7934 18.7936 19.1665 18.3333 19.1665C17.8731 19.1665 17.5 18.7934 17.5 18.3332L17.5 17.4998C17.5 17.0396 17.8731 16.6665 18.3333 16.6665Z" fill="currentColor"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M13.75 16.6665C14.2102 16.6665 14.5833 17.0396 14.5833 17.4998L14.5833 18.3332C14.5833 18.7934 14.2102 19.1665 13.75 19.1665C13.2898 19.1665 12.9167 18.7934 12.9167 18.3332L12.9167 17.4998C12.9167 17.0396 13.2898 16.6665 13.75 16.6665Z" fill="currentColor"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M11.6667 15.8333C12.1269 15.8333 12.5 16.2063 12.5 16.6666L12.5 18.3333C12.5 18.7935 12.1269 19.1666 11.6667 19.1666C11.2064 19.1666 10.8333 18.7935 10.8333 18.3333L10.8333 16.6666C10.8333 16.2063 11.2064 15.8333 11.6667 15.8333Z" fill="currentColor"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M13.75 13.3333C14.2102 13.3333 14.5833 13.7063 14.5833 14.1666V14.9999C14.5833 15.4602 14.2102 15.8333 13.75 15.8333C13.2898 15.8333 12.9167 15.4602 12.9167 14.9999V14.1666C12.9167 13.7063 13.2898 13.3333 13.75 13.3333Z" fill="currentColor"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_1158_5594">
|
||||
<rect width="20" height="20" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
After Width: | Height: | Size: 3.7 KiB |
14
packages/experience-legacy/src/assets/icons/info-icon.svg
Normal file
|
@ -0,0 +1,14 @@
|
|||
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M9.99984 1.66675C8.35166 1.66675 6.7405 2.15549 5.37009 3.07117C3.99968 3.98685 2.93158 5.28834 2.30084 6.81105C1.67011 8.33377 1.50509 10.0093 1.82663 11.6258C2.14817 13.2423 2.94185 14.7272 4.10728 15.8926C5.27272 17.0581 6.75758 17.8517 8.37409 18.1733C9.9906 18.4948 11.6662 18.3298 13.1889 17.6991C14.7116 17.0683 16.0131 16.0002 16.9288 14.6298C17.8444 13.2594 18.3332 11.6483 18.3332 10.0001C18.3332 8.90573 18.1176 7.8221 17.6988 6.81105C17.28 5.80001 16.6662 4.88135 15.8924 4.10752C15.1186 3.3337 14.1999 2.71987 13.1889 2.30109C12.1778 1.8823 11.0942 1.66675 9.99984 1.66675Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
<path
|
||||
d="M9.41081 9.41066C9.56709 9.25438 9.77906 9.16658 10.0001 9.16658C10.2211 9.16658 10.433 9.25438 10.5893 9.41066C10.7456 9.56694 10.8334 9.7789 10.8334 9.99991V13.3332C10.8334 13.5543 10.7456 13.7662 10.5893 13.9225C10.433 14.0788 10.2211 14.1666 10.0001 14.1666C9.77906 14.1666 9.56709 14.0788 9.41081 13.9225C9.25453 13.7662 9.16674 13.5543 9.16674 13.3332V9.99991C9.16674 9.7789 9.25453 9.56694 9.41081 9.41066Z"
|
||||
fill="white"
|
||||
/>
|
||||
<path
|
||||
d="M9.6834 5.89991C9.88629 5.81657 10.1139 5.81657 10.3167 5.89991C10.419 5.93958 10.5125 5.99905 10.5917 6.07491C10.744 6.23461 10.8303 6.44594 10.8334 6.66658C10.8327 6.80307 10.7985 6.9373 10.7338 7.05747C10.6691 7.17765 10.5759 7.28009 10.4623 7.3558C10.3488 7.43151 10.2183 7.47817 10.0825 7.49167C9.94671 7.50518 9.80965 7.48511 9.6834 7.43325C9.58242 7.39105 9.4894 7.33186 9.4084 7.25825C9.33117 7.18038 9.27006 7.08803 9.22859 6.9865C9.18712 6.88497 9.1661 6.77625 9.16674 6.66658C9.16392 6.55727 9.18675 6.44881 9.2334 6.34991C9.2756 6.24893 9.33479 6.15591 9.4084 6.07491C9.48766 5.99905 9.58111 5.93958 9.6834 5.89991Z"
|
||||
fill="white"
|
||||
/>
|
||||
</svg>
|
After Width: | Height: | Size: 1.8 KiB |
15
packages/experience-legacy/src/assets/icons/loading-icon.svg
Normal file
|
@ -0,0 +1,15 @@
|
|||
<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect opacity="0.48" x="15" width="2" height="8" rx="1" fill="currentColor"/>
|
||||
<rect opacity="0.96" x="15" y="24" width="2" height="8" rx="1" fill="currentColor"/>
|
||||
<rect opacity="0.72" y="17" width="2" height="8" rx="1" transform="rotate(-90 0 17)" fill="currentColor"/>
|
||||
<rect opacity="0.24" x="24" y="17" width="2" height="8" rx="1" transform="rotate(-90 24 17)" fill="currentColor"/>
|
||||
<rect opacity="0.32" x="29.3564" y="7.13403" width="2" height="8" rx="1" transform="rotate(60 29.3564 7.13403)" fill="currentColor"/>
|
||||
<rect opacity="0.8" x="8.57227" y="19.134" width="2" height="8" rx="1" transform="rotate(60 8.57227 19.134)" fill="currentColor"/>
|
||||
<rect opacity="0.64" x="1.64355" y="8.86597" width="2" height="8" rx="1" transform="rotate(-60 1.64355 8.86597)" fill="currentColor"/>
|
||||
<rect opacity="0.16" x="22.4277" y="20.866" width="2" height="8" rx="1" transform="rotate(-60 22.4277 20.866)" fill="currentColor"/>
|
||||
<rect opacity="0.4" x="23.1338" y="1.64355" width="2" height="8" rx="1" transform="rotate(30 23.1338 1.64355)" fill="currentColor"/>
|
||||
<rect opacity="0.88" x="11.1338" y="22.4282" width="2" height="8" rx="1" transform="rotate(30 11.1338 22.4282)" fill="currentColor"/>
|
||||
<rect opacity="0.56" x="7.13379" y="2.64355" width="2" height="8" rx="1" transform="rotate(-30 7.13379 2.64355)" fill="currentColor"/>
|
||||
<rect opacity="0.08" x="19.1338" y="23.4282" width="2" height="8" rx="1" transform="rotate(-30 19.1338 23.4282)" fill="currentColor"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
|
@ -0,0 +1,3 @@
|
|||
<svg width="21" height="20" viewBox="0 0 21 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M11.8357 16.8714C11.941 17.4135 11.5865 17.9451 11.0355 17.9821C9.9048 18.0579 8.7669 17.8929 7.69834 17.4934C6.31639 16.9767 5.10425 16.0879 4.19591 14.9253C3.28758 13.7627 2.71844 12.3715 2.55143 10.9056C2.38441 9.43973 2.62602 7.9562 3.24954 6.61905C3.87306 5.28191 4.85421 4.14323 6.0845 3.32891C7.3148 2.5146 8.74632 2.05636 10.2208 2.00487C11.6953 1.95338 13.1553 2.31064 14.4394 3.03715C15.4323 3.59891 16.2901 4.36452 16.9588 5.27942C17.2847 5.72531 17.1054 6.33858 16.6223 6.60633C16.1393 6.87408 15.5366 6.69278 15.1924 6.26086C14.7154 5.66218 14.1262 5.15785 13.4545 4.77787C12.4915 4.23298 11.3965 3.96504 10.2906 4.00366C9.18474 4.04227 8.1111 4.38595 7.18838 4.99669C6.26565 5.60742 5.52979 6.46143 5.06215 7.46429C4.59451 8.46715 4.41331 9.5798 4.53857 10.6792C4.66383 11.7786 5.09069 12.822 5.77194 13.694C6.45319 14.5659 7.3623 15.2325 8.39876 15.62C9.12154 15.8903 9.88663 16.0175 10.6519 15.9981C11.204 15.9841 11.7303 16.3293 11.8357 16.8714Z" fill="currentColor"/>
|
||||
</svg>
|
After Width: | Height: | Size: 1.1 KiB |
4
packages/experience-legacy/src/assets/icons/lock.svg
Normal file
|
@ -0,0 +1,4 @@
|
|||
<svg width="21" height="20" viewBox="0 0 21 20"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M10.5007 10.8332C10.2469 10.8302 9.99841 10.905 9.78852 11.0476C9.57863 11.1901 9.41744 11.3936 9.32666 11.6305C9.23588 11.8674 9.21987 12.1265 9.28077 12.3728C9.34168 12.6191 9.47658 12.8408 9.66732 13.0082V14.1665C9.66732 14.3875 9.75512 14.5995 9.9114 14.7558C10.0677 14.912 10.2796 14.9998 10.5007 14.9998C10.7217 14.9998 10.9336 14.912 11.0899 14.7558C11.2462 14.5995 11.334 14.3875 11.334 14.1665V13.0082C11.5247 12.8408 11.6596 12.6191 11.7205 12.3728C11.7814 12.1265 11.7654 11.8674 11.6746 11.6305C11.5839 11.3936 11.4227 11.1901 11.2128 11.0476C11.0029 10.905 10.7544 10.8302 10.5007 10.8332ZM14.6673 7.49984V5.83317C14.6673 4.7281 14.2283 3.66829 13.4469 2.88689C12.6655 2.10549 11.6057 1.6665 10.5007 1.6665C9.39558 1.6665 8.33577 2.10549 7.55437 2.88689C6.77297 3.66829 6.33398 4.7281 6.33398 5.83317V7.49984C5.67094 7.49984 5.03506 7.76323 4.56622 8.23207C4.09738 8.70091 3.83398 9.3368 3.83398 9.99984V15.8332C3.83398 16.4962 4.09738 17.1321 4.56622 17.6009C5.03506 18.0698 5.67094 18.3332 6.33398 18.3332H14.6673C15.3304 18.3332 15.9662 18.0698 16.4351 17.6009C16.9039 17.1321 17.1673 16.4962 17.1673 15.8332V9.99984C17.1673 9.3368 16.9039 8.70091 16.4351 8.23207C15.9662 7.76323 15.3304 7.49984 14.6673 7.49984ZM8.00065 5.83317C8.00065 5.17013 8.26404 4.53424 8.73288 4.0654C9.20172 3.59656 9.83761 3.33317 10.5007 3.33317C11.1637 3.33317 11.7996 3.59656 12.2684 4.0654C12.7373 4.53424 13.0007 5.17013 13.0007 5.83317V7.49984H8.00065V5.83317ZM15.5007 15.8332C15.5007 16.0542 15.4129 16.2661 15.2566 16.4224C15.1003 16.5787 14.8883 16.6665 14.6673 16.6665H6.33398C6.11297 16.6665 5.90101 16.5787 5.74473 16.4224C5.58845 16.2661 5.50065 16.0542 5.50065 15.8332V9.99984C5.50065 9.77882 5.58845 9.56686 5.74473 9.41058C5.90101 9.2543 6.11297 9.1665 6.33398 9.1665H14.6673C14.8883 9.1665 15.1003 9.2543 15.2566 9.41058C15.4129 9.56686 15.5007 9.77882 15.5007 9.99984V15.8332Z" fill="white" fill-opacity="0.7"/>
|
||||
</svg>
|
After Width: | Height: | Size: 2 KiB |
|
@ -0,0 +1,22 @@
|
|||
<svg width="52" height="18" viewBox="0 0 52 18" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_1251_17490)">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M1 4.5299C1 4.15639 1 3.96963 1.06856 3.81931C1.12899 3.68684 1.22616 3.57457 1.34851 3.49586C1.48735 3.40655 1.67193 3.38004 2.0411 3.32702L7.3061 2.57085C7.784 2.50221 8.02295 2.46789 8.20864 2.54035C8.37165 2.60396 8.50768 2.72206 8.59369 2.87463C8.69167 3.04844 8.69167 3.2902 8.69167 3.77374V14.2263C8.69167 14.7098 8.69167 14.9516 8.59369 15.1254C8.50768 15.2779 8.37165 15.396 8.20864 15.4596C8.02296 15.5321 7.784 15.4978 7.30611 15.4291H7.3061L2.0411 14.673L2.04108 14.673L2.04106 14.673C1.67192 14.62 1.48734 14.5934 1.34851 14.5041C1.22616 14.4254 1.12899 14.3132 1.06856 14.1807C1 14.0304 1 13.8436 1 13.4701V4.5299ZM6.30838 8.07075C6.30838 7.959 6.30838 7.90312 6.32939 7.85895C6.3479 7.82005 6.37758 7.78756 6.41464 7.76561C6.45672 7.74068 6.51237 7.73562 6.62366 7.7255L7.12199 7.6802H7.122C7.25312 7.66828 7.31868 7.66232 7.3693 7.68419C7.41378 7.7034 7.45053 7.73696 7.47369 7.77951C7.50005 7.82795 7.50005 7.89378 7.50005 8.02544V9.97456C7.50005 10.1062 7.50005 10.1721 7.47369 10.2205C7.45053 10.263 7.41378 10.2966 7.3693 10.3158C7.31868 10.3377 7.25312 10.3317 7.12199 10.3198L6.62366 10.2745C6.51237 10.2644 6.45672 10.2593 6.41464 10.2344C6.37758 10.2124 6.3479 10.1799 6.32939 10.141C6.30838 10.0969 6.30838 10.041 6.30838 9.92925V8.07075ZM10.1866 3.58339H9.44997V14.4167H10.1866C10.6113 14.4167 10.8237 14.4167 10.9859 14.3341C11.1286 14.2614 11.2446 14.1454 11.3173 14.0027C11.4 13.8405 11.4 13.6281 11.4 13.2034V4.79673C11.4 4.37202 11.4 4.15967 11.3173 3.99745C11.2446 3.85476 11.1286 3.73875 10.9859 3.66605C10.8237 3.58339 10.6113 3.58339 10.1866 3.58339Z" fill="#928F9A"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M1 4.5299C1 4.15639 1 3.96963 1.06856 3.81931C1.12899 3.68684 1.22616 3.57457 1.34851 3.49586C1.48735 3.40655 1.67193 3.38004 2.0411 3.32702L7.3061 2.57085C7.784 2.50221 8.02295 2.46789 8.20864 2.54035C8.37165 2.60396 8.50768 2.72206 8.59369 2.87463C8.69167 3.04844 8.69167 3.2902 8.69167 3.77374V14.2263C8.69167 14.7098 8.69167 14.9516 8.59369 15.1254C8.50768 15.2779 8.37165 15.396 8.20864 15.4596C8.02296 15.5321 7.784 15.4978 7.30611 15.4291H7.3061L2.0411 14.673L2.04108 14.673L2.04106 14.673C1.67192 14.62 1.48734 14.5934 1.34851 14.5041C1.22616 14.4254 1.12899 14.3132 1.06856 14.1807C1 14.0304 1 13.8436 1 13.4701V4.5299ZM6.30838 8.07075C6.30838 7.959 6.30838 7.90312 6.32939 7.85895C6.3479 7.82005 6.37758 7.78756 6.41464 7.76561C6.45672 7.74068 6.51237 7.73562 6.62366 7.7255L7.12199 7.6802H7.122C7.25312 7.66828 7.31868 7.66232 7.3693 7.68419C7.41378 7.7034 7.45053 7.73696 7.47369 7.77951C7.50005 7.82795 7.50005 7.89378 7.50005 8.02544V9.97456C7.50005 10.1062 7.50005 10.1721 7.47369 10.2205C7.45053 10.263 7.41378 10.2966 7.3693 10.3158C7.31868 10.3377 7.25312 10.3317 7.12199 10.3198L6.62366 10.2745C6.51237 10.2644 6.45672 10.2593 6.41464 10.2344C6.37758 10.2124 6.3479 10.1799 6.32939 10.141C6.30838 10.0969 6.30838 10.041 6.30838 9.92925V8.07075ZM10.1866 3.58339H9.44997V14.4167H10.1866C10.6113 14.4167 10.8237 14.4167 10.9859 14.3341C11.1286 14.2614 11.2446 14.1454 11.3173 14.0027C11.4 13.8405 11.4 13.6281 11.4 13.2034V4.79673C11.4 4.37202 11.4 4.15967 11.3173 3.99745C11.2446 3.85476 11.1286 3.73875 10.9859 3.66605C10.8237 3.58339 10.6113 3.58339 10.1866 3.58339Z" fill="url(#paint0_linear_1251_17490)"/>
|
||||
</g>
|
||||
<path d="M25.3042 13.8727C24.5566 13.8727 23.9109 13.7173 23.3672 13.4066C22.8234 13.0959 22.4059 12.6638 22.1146 12.1104C21.8233 11.5472 21.6777 10.8967 21.6777 10.1588C21.6777 9.4014 21.8282 8.746 22.1292 8.19255C22.4302 7.6391 22.8526 7.20702 23.3963 6.89632C23.9497 6.58561 24.5954 6.43025 25.3334 6.43025C26.081 6.43025 26.7218 6.58561 27.2559 6.89632C27.7996 7.20702 28.222 7.6391 28.523 8.19255C28.824 8.746 28.9745 9.39655 28.9745 10.1442C28.9745 10.8821 28.8191 11.5327 28.5084 12.0958C28.2074 12.659 27.7851 13.0959 27.2413 13.4066C26.6976 13.7076 26.0519 13.863 25.3042 13.8727ZM25.3188 12.4599C25.7266 12.4599 26.0762 12.358 26.3674 12.1541C26.6587 11.9502 26.8821 11.6735 27.0374 11.3239C27.2025 10.9744 27.285 10.5811 27.285 10.1442C27.285 9.69755 27.2073 9.29945 27.052 8.9499C26.8966 8.60036 26.6733 8.32849 26.382 8.13429C26.0907 7.93039 25.7412 7.82844 25.3334 7.82844C24.945 7.82844 24.6003 7.93039 24.2993 8.13429C23.9983 8.3382 23.7653 8.61492 23.6002 8.96447C23.4448 9.31402 23.3623 9.70726 23.3526 10.1442C23.3526 10.5908 23.4303 10.9889 23.5856 11.3385C23.741 11.688 23.9692 11.9647 24.2702 12.1686C24.5712 12.3628 24.9207 12.4599 25.3188 12.4599Z" fill="#F7F8F8"/>
|
||||
<path d="M36.4994 6.69557C36.4994 6.65361 36.4654 6.61959 36.4234 6.61959H34.9296C34.8876 6.61959 34.8536 6.65361 34.8536 6.69557V14.1494C34.8536 14.6446 34.6691 14.9522 34.3002 15.224C33.9409 15.4959 33.5368 15.5848 32.964 15.5945C32.5659 15.5848 32.1924 15.5493 31.8622 15.4425C31.5526 15.3514 31.2137 15.2176 30.8604 15.0411C30.8219 15.0219 30.775 15.0379 30.7567 15.0768L30.2198 16.2213C30.2042 16.2544 30.2144 16.2939 30.2446 16.3144C30.4084 16.4259 30.6 16.5256 30.8193 16.6133C31.062 16.7104 31.3096 16.7881 31.5621 16.8463C31.8242 16.9143 32.0951 16.971 32.3281 17.0001C32.5708 17.0292 32.8 17.0332 32.9457 17.0332C33.6836 17.0332 34.3147 16.9167 34.8391 16.6836C35.3731 16.4506 35.7809 16.1205 36.0625 15.6932C36.3538 15.266 36.4994 14.7563 36.4994 14.164V6.69557ZM35.3104 11.5198C35.2881 11.4671 35.2178 11.4569 35.1803 11.5C34.8943 11.8287 34.6043 12.0616 34.3293 12.2123C34.038 12.3774 33.703 12.4599 33.3244 12.4599C32.936 12.4599 32.5961 12.3628 32.3049 12.1686C32.0233 11.9647 31.8097 11.688 31.664 11.3385C31.5184 10.9889 31.4455 10.586 31.4455 10.1296C31.4455 9.69269 31.5184 9.30431 31.664 8.96447C31.8097 8.61492 32.0233 8.3382 32.3049 8.13429C32.5961 7.93039 32.9408 7.82844 33.3389 7.82844C33.7079 7.82844 33.9992 7.90612 34.3002 8.06147C34.5812 8.20197 34.8803 8.52282 35.1376 8.85792C35.1735 8.90461 35.2468 8.89592 35.2698 8.84172L35.6831 7.86653C35.6932 7.84278 35.6906 7.81558 35.6759 7.79442C35.1544 7.04603 34.2722 6.43025 33.2679 6.43025C32.5397 6.43025 31.965 6.58561 31.431 6.89632C30.897 7.20702 30.4843 7.6391 30.193 8.19255C29.9114 8.746 29.7706 9.39169 29.7706 10.1296C29.7706 10.887 29.9114 11.5472 30.193 12.1104C30.4746 12.6638 30.8775 13.0959 31.4019 13.4066C31.9359 13.7173 32.567 13.8727 33.2952 13.8727C33.5671 13.8727 33.8487 13.8193 34.14 13.7125C34.441 13.6154 34.7323 13.4697 35.0138 13.2755C35.2832 13.0898 35.5215 12.8684 35.7287 12.6115C35.7461 12.59 35.75 12.5606 35.7392 12.5352L35.3104 11.5198Z" fill="#F7F8F8"/>
|
||||
<path d="M41.9863 6.75383C41.9863 6.71187 41.9523 6.67785 41.9104 6.67785H40.2855C40.2435 6.67785 40.2095 6.64383 40.2095 6.60187V4.61531C40.2095 4.57334 40.1755 4.53933 40.1335 4.53933H38.6542C38.6123 4.53933 38.5783 4.57334 38.5783 4.61531V6.60187C38.5783 6.64383 38.5442 6.67785 38.5023 6.67785H37.5127C37.4704 6.67785 37.4363 6.71236 37.4367 6.75463L37.4497 7.98629C37.4501 8.02794 37.484 8.06147 37.5257 8.06147H38.5023C38.5442 8.06147 38.5783 8.09549 38.5783 8.13745V11.5715C38.5783 12.0861 38.6802 12.5231 38.8841 12.8823C39.0977 13.2319 39.389 13.4989 39.758 13.6834C40.1269 13.8678 40.5736 13.9601 41.0979 13.9601C41.2436 13.9601 41.3989 13.9407 41.564 13.9018C41.7387 13.863 41.9076 13.8221 42.0532 13.7638C42.1833 13.7151 42.4366 13.588 42.5658 13.5131C42.6001 13.4932 42.6108 13.4498 42.5914 13.4151L41.9903 12.3556C41.9714 12.3219 41.9304 12.3079 41.8944 12.3216C41.7972 12.3587 41.6968 12.3892 41.5931 12.4131C41.4669 12.4422 41.3407 12.4568 41.2144 12.4568C40.8746 12.4568 40.6221 12.4211 40.4571 12.1978C40.292 11.9647 40.2095 11.6686 40.2095 11.3093V8.13745C40.2095 8.09549 40.2435 8.06147 40.2855 8.06147H41.9104C41.9523 8.06147 41.9863 8.02745 41.9863 7.98549V6.75383Z" fill="#F7F8F8"/>
|
||||
<path d="M46.4061 13.8727C45.6584 13.8727 45.0128 13.7173 44.469 13.4066C43.9253 13.0959 43.5078 12.6638 43.2165 12.1104C42.9252 11.5472 42.7795 10.8967 42.7795 10.1588C42.7795 9.4014 42.93 8.746 43.231 8.19255C43.532 7.6391 43.9544 7.20702 44.4981 6.89632C45.0516 6.58561 45.6973 6.43025 46.4352 6.43025C47.1829 6.43025 47.8237 6.58561 48.3577 6.89632C48.9015 7.20702 49.3238 7.6391 49.6248 8.19255C49.9258 8.746 50.0763 9.39655 50.0763 10.1442C50.0763 10.8821 49.921 11.5327 49.6103 12.0958C49.3093 12.659 48.8869 13.0959 48.3432 13.4066C47.7994 13.7076 47.1537 13.863 46.4061 13.8727ZM46.4207 12.4599C46.8285 12.4599 47.178 12.358 47.4693 12.1541C47.7606 11.9502 47.9839 11.6735 48.1393 11.3239C48.3043 10.9744 48.3869 10.5811 48.3869 10.1442C48.3869 9.69755 48.3092 9.29945 48.1538 8.9499C47.9985 8.60036 47.7751 8.32849 47.4839 8.13429C47.1926 7.93039 46.843 7.82844 46.4352 7.82844C46.0468 7.82844 45.7021 7.93039 45.4011 8.13429C45.1001 8.3382 44.8671 8.61492 44.702 8.96447C44.5467 9.31402 44.4642 9.70726 44.4544 10.1442C44.4544 10.5908 44.5321 10.9889 44.6875 11.3385C44.8428 11.688 45.071 11.9647 45.372 12.1686C45.673 12.3628 46.0226 12.4599 46.4207 12.4599Z" fill="#F7F8F8"/>
|
||||
<path d="M21.0534 12.4017C21.0534 12.3597 21.0194 12.3257 20.9774 12.3257H17.0671C17.0252 12.3257 16.9912 12.2917 16.9912 12.2497V4.2354C16.9912 4.19344 16.9571 4.15942 16.9152 4.15942H15.4505C15.4085 4.15942 15.3745 4.19344 15.3745 4.2354V13.7967C15.3745 13.8387 15.4085 13.8727 15.4505 13.8727H20.9774C21.0194 13.8727 21.0534 13.8387 21.0534 13.7967V12.4017Z" fill="#F7F8F8"/>
|
||||
<defs>
|
||||
<linearGradient id="paint0_linear_1251_17490" x1="-2.21904" y1="11.4904" x2="10.7367" y2="6.40599" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#4B2EFB"/>
|
||||
<stop offset="1" stop-color="#E65FFC"/>
|
||||
</linearGradient>
|
||||
<clipPath id="clip0_1251_17490">
|
||||
<rect width="10.4" height="13" fill="white" transform="translate(1 2.5)"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
||||
|
After Width: | Height: | Size: 9.5 KiB |
|
@ -0,0 +1,21 @@
|
|||
<svg width="52" height="18" viewBox="0 0 52 18" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_1251_17291)">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M1 4.5299C1 4.15639 1 3.96963 1.06856 3.81931C1.12899 3.68684 1.22616 3.57457 1.34851 3.49586C1.48735 3.40655 1.67193 3.38004 2.0411 3.32702L7.3061 2.57085C7.784 2.50221 8.02295 2.46789 8.20864 2.54035C8.37165 2.60396 8.50768 2.72206 8.59369 2.87463C8.69167 3.04844 8.69167 3.2902 8.69167 3.77374V14.2263C8.69167 14.7098 8.69167 14.9516 8.59369 15.1254C8.50768 15.2779 8.37165 15.396 8.20864 15.4596C8.02296 15.5321 7.784 15.4978 7.30611 15.4291H7.3061L2.0411 14.673L2.04108 14.673L2.04106 14.673C1.67192 14.62 1.48734 14.5934 1.34851 14.5041C1.22616 14.4254 1.12899 14.3132 1.06856 14.1807C1 14.0304 1 13.8436 1 13.4701V4.5299ZM6.30838 8.07075C6.30838 7.959 6.30838 7.90312 6.32939 7.85895C6.3479 7.82005 6.37758 7.78756 6.41464 7.76561C6.45672 7.74068 6.51237 7.73562 6.62366 7.7255L7.12199 7.6802H7.122C7.25312 7.66828 7.31868 7.66232 7.3693 7.68419C7.41378 7.7034 7.45053 7.73696 7.47369 7.77951C7.50005 7.82795 7.50005 7.89378 7.50005 8.02544V9.97456C7.50005 10.1062 7.50005 10.1721 7.47369 10.2205C7.45053 10.263 7.41378 10.2966 7.3693 10.3158C7.31868 10.3377 7.25312 10.3317 7.12199 10.3198L6.62366 10.2745C6.51237 10.2644 6.45672 10.2593 6.41464 10.2344C6.37758 10.2124 6.3479 10.1799 6.32939 10.141C6.30838 10.0969 6.30838 10.041 6.30838 9.92925V8.07075ZM10.1866 3.58339H9.44997V14.4167H10.1866C10.6113 14.4167 10.8237 14.4167 10.9859 14.3341C11.1286 14.2614 11.2446 14.1454 11.3173 14.0027C11.4 13.8405 11.4 13.6281 11.4 13.2034V4.79673C11.4 4.37202 11.4 4.15967 11.3173 3.99745C11.2446 3.85476 11.1286 3.73875 10.9859 3.66605C10.8237 3.58339 10.6113 3.58339 10.1866 3.58339Z" fill="#928F9A"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M1 4.5299C1 4.15639 1 3.96963 1.06856 3.81931C1.12899 3.68684 1.22616 3.57457 1.34851 3.49586C1.48735 3.40655 1.67193 3.38004 2.0411 3.32702L7.3061 2.57085C7.784 2.50221 8.02295 2.46789 8.20864 2.54035C8.37165 2.60396 8.50768 2.72206 8.59369 2.87463C8.69167 3.04844 8.69167 3.2902 8.69167 3.77374V14.2263C8.69167 14.7098 8.69167 14.9516 8.59369 15.1254C8.50768 15.2779 8.37165 15.396 8.20864 15.4596C8.02296 15.5321 7.784 15.4978 7.30611 15.4291H7.3061L2.0411 14.673L2.04108 14.673L2.04106 14.673C1.67192 14.62 1.48734 14.5934 1.34851 14.5041C1.22616 14.4254 1.12899 14.3132 1.06856 14.1807C1 14.0304 1 13.8436 1 13.4701V4.5299ZM6.30838 8.07075C6.30838 7.959 6.30838 7.90312 6.32939 7.85895C6.3479 7.82005 6.37758 7.78756 6.41464 7.76561C6.45672 7.74068 6.51237 7.73562 6.62366 7.7255L7.12199 7.6802H7.122C7.25312 7.66828 7.31868 7.66232 7.3693 7.68419C7.41378 7.7034 7.45053 7.73696 7.47369 7.77951C7.50005 7.82795 7.50005 7.89378 7.50005 8.02544V9.97456C7.50005 10.1062 7.50005 10.1721 7.47369 10.2205C7.45053 10.263 7.41378 10.2966 7.3693 10.3158C7.31868 10.3377 7.25312 10.3317 7.12199 10.3198L6.62366 10.2745C6.51237 10.2644 6.45672 10.2593 6.41464 10.2344C6.37758 10.2124 6.3479 10.1799 6.32939 10.141C6.30838 10.0969 6.30838 10.041 6.30838 9.92925V8.07075ZM10.1866 3.58339H9.44997V14.4167H10.1866C10.6113 14.4167 10.8237 14.4167 10.9859 14.3341C11.1286 14.2614 11.2446 14.1454 11.3173 14.0027C11.4 13.8405 11.4 13.6281 11.4 13.2034V4.79673C11.4 4.37202 11.4 4.15967 11.3173 3.99745C11.2446 3.85476 11.1286 3.73875 10.9859 3.66605C10.8237 3.58339 10.6113 3.58339 10.1866 3.58339Z" fill="url(#paint0_linear_1251_17291)"/>
|
||||
</g>
|
||||
<path d="M25.3042 13.8727C24.5566 13.8727 23.9109 13.7173 23.3672 13.4066C22.8234 13.0959 22.4059 12.6638 22.1146 12.1104C21.8233 11.5472 21.6777 10.8967 21.6777 10.1588C21.6777 9.4014 21.8282 8.746 22.1292 8.19255C22.4302 7.6391 22.8526 7.20702 23.3963 6.89632C23.9497 6.58561 24.5954 6.43025 25.3334 6.43025C26.081 6.43025 26.7218 6.58561 27.2559 6.89632C27.7996 7.20702 28.222 7.6391 28.523 8.19255C28.824 8.746 28.9745 9.39655 28.9745 10.1442C28.9745 10.8821 28.8191 11.5327 28.5084 12.0958C28.2074 12.659 27.7851 13.0959 27.2413 13.4066C26.6976 13.7076 26.0519 13.863 25.3042 13.8727ZM25.3188 12.4599C25.7266 12.4599 26.0762 12.358 26.3674 12.1541C26.6587 11.9502 26.8821 11.6735 27.0374 11.3239C27.2025 10.9744 27.285 10.5811 27.285 10.1442C27.285 9.69755 27.2073 9.29945 27.052 8.9499C26.8966 8.60036 26.6733 8.32849 26.382 8.13429C26.0907 7.93039 25.7412 7.82844 25.3334 7.82844C24.945 7.82844 24.6003 7.93039 24.2993 8.13429C23.9983 8.3382 23.7653 8.61492 23.6002 8.96447C23.4448 9.31402 23.3623 9.70726 23.3526 10.1442C23.3526 10.5908 23.4303 10.9889 23.5856 11.3385C23.741 11.688 23.9692 11.9647 24.2702 12.1686C24.5712 12.3628 24.9207 12.4599 25.3188 12.4599Z" fill="#191C1D"/>
|
||||
<path d="M36.4994 6.69557C36.4994 6.65361 36.4654 6.61959 36.4234 6.61959H34.9296C34.8876 6.61959 34.8536 6.65361 34.8536 6.69557V14.1494C34.8536 14.6446 34.6691 14.9522 34.3002 15.224C33.9409 15.4959 33.5368 15.5848 32.964 15.5945C32.5659 15.5848 32.1924 15.5493 31.8622 15.4425C31.5526 15.3514 31.2137 15.2176 30.8604 15.0411C30.8219 15.0219 30.775 15.0379 30.7567 15.0768L30.2198 16.2213C30.2042 16.2544 30.2144 16.2939 30.2446 16.3144C30.4084 16.4259 30.6 16.5256 30.8193 16.6133C31.062 16.7104 31.3096 16.7881 31.5621 16.8463C31.8242 16.9143 32.0951 16.971 32.3281 17.0001C32.5708 17.0292 32.8 17.0332 32.9457 17.0332C33.6836 17.0332 34.3147 16.9167 34.8391 16.6836C35.3731 16.4506 35.7809 16.1205 36.0625 15.6932C36.3538 15.266 36.4994 14.7563 36.4994 14.164V6.69557ZM35.3104 11.5198C35.2881 11.4671 35.2178 11.4569 35.1803 11.5C34.8943 11.8287 34.6043 12.0616 34.3293 12.2123C34.038 12.3774 33.703 12.4599 33.3244 12.4599C32.936 12.4599 32.5961 12.3628 32.3049 12.1686C32.0233 11.9647 31.8097 11.688 31.664 11.3385C31.5184 10.9889 31.4455 10.586 31.4455 10.1296C31.4455 9.69269 31.5184 9.30431 31.664 8.96447C31.8097 8.61492 32.0233 8.3382 32.3049 8.13429C32.5961 7.93039 32.9408 7.82844 33.3389 7.82844C33.7079 7.82844 33.9992 7.90612 34.3002 8.06147C34.5812 8.20197 34.8803 8.52282 35.1376 8.85792C35.1735 8.90461 35.2468 8.89592 35.2698 8.84172L35.6831 7.86653C35.6932 7.84278 35.6906 7.81558 35.6759 7.79442C35.1544 7.04603 34.2722 6.43025 33.2679 6.43025C32.5397 6.43025 31.965 6.58561 31.431 6.89632C30.897 7.20702 30.4843 7.6391 30.193 8.19255C29.9114 8.746 29.7706 9.39169 29.7706 10.1296C29.7706 10.887 29.9114 11.5472 30.193 12.1104C30.4746 12.6638 30.8775 13.0959 31.4019 13.4066C31.9359 13.7173 32.567 13.8727 33.2952 13.8727C33.5671 13.8727 33.8487 13.8193 34.14 13.7125C34.441 13.6154 34.7323 13.4697 35.0138 13.2755C35.2832 13.0898 35.5215 12.8684 35.7287 12.6115C35.7461 12.59 35.75 12.5606 35.7392 12.5352L35.3104 11.5198Z" fill="#191C1D"/>
|
||||
<path d="M41.9863 6.75383C41.9863 6.71187 41.9523 6.67785 41.9104 6.67785H40.2855C40.2435 6.67785 40.2095 6.64383 40.2095 6.60187V4.61531C40.2095 4.57334 40.1755 4.53933 40.1335 4.53933H38.6542C38.6123 4.53933 38.5783 4.57334 38.5783 4.61531V6.60187C38.5783 6.64383 38.5442 6.67785 38.5023 6.67785H37.5127C37.4704 6.67785 37.4363 6.71236 37.4367 6.75463L37.4497 7.98629C37.4501 8.02794 37.484 8.06147 37.5257 8.06147H38.5023C38.5442 8.06147 38.5783 8.09549 38.5783 8.13745V11.5715C38.5783 12.0861 38.6802 12.5231 38.8841 12.8823C39.0977 13.2319 39.389 13.4989 39.758 13.6834C40.1269 13.8678 40.5736 13.9601 41.0979 13.9601C41.2436 13.9601 41.3989 13.9407 41.564 13.9018C41.7387 13.863 41.9076 13.8221 42.0533 13.7638C42.1833 13.7151 42.4366 13.588 42.5658 13.5131C42.6001 13.4932 42.6108 13.4498 42.5914 13.4151L41.9903 12.3556C41.9714 12.3219 41.9304 12.3079 41.8944 12.3216C41.7972 12.3587 41.6968 12.3892 41.5931 12.4131C41.4669 12.4422 41.3407 12.4568 41.2144 12.4568C40.8746 12.4568 40.6221 12.4211 40.4571 12.1978C40.292 11.9647 40.2095 11.6686 40.2095 11.3093V8.13745C40.2095 8.09549 40.2435 8.06147 40.2855 8.06147H41.9104C41.9523 8.06147 41.9863 8.02745 41.9863 7.98549V6.75383Z" fill="#191C1D"/>
|
||||
<path d="M46.4061 13.8727C45.6584 13.8727 45.0128 13.7173 44.469 13.4066C43.9253 13.0959 43.5078 12.6638 43.2165 12.1104C42.9252 11.5472 42.7795 10.8967 42.7795 10.1588C42.7795 9.4014 42.93 8.746 43.231 8.19255C43.532 7.6391 43.9544 7.20702 44.4981 6.89632C45.0516 6.58561 45.6973 6.43025 46.4352 6.43025C47.1829 6.43025 47.8237 6.58561 48.3577 6.89632C48.9015 7.20702 49.3238 7.6391 49.6248 8.19255C49.9258 8.746 50.0763 9.39655 50.0763 10.1442C50.0763 10.8821 49.921 11.5327 49.6103 12.0958C49.3093 12.659 48.8869 13.0959 48.3432 13.4066C47.7994 13.7076 47.1537 13.863 46.4061 13.8727ZM46.4206 12.4599C46.8285 12.4599 47.178 12.358 47.4693 12.1541C47.7606 11.9502 47.9839 11.6735 48.1393 11.3239C48.3043 10.9744 48.3869 10.5811 48.3869 10.1442C48.3869 9.69755 48.3092 9.29945 48.1538 8.9499C47.9985 8.60036 47.7751 8.32849 47.4839 8.13429C47.1926 7.93039 46.843 7.82844 46.4352 7.82844C46.0468 7.82844 45.7021 7.93039 45.4011 8.13429C45.1001 8.3382 44.8671 8.61492 44.702 8.96447C44.5467 9.31402 44.4642 9.70726 44.4544 10.1442C44.4544 10.5908 44.5321 10.9889 44.6875 11.3385C44.8428 11.688 45.071 11.9647 45.372 12.1686C45.673 12.3628 46.0226 12.4599 46.4206 12.4599Z" fill="#191C1D"/>
|
||||
<path d="M21.0534 12.4017C21.0534 12.3597 21.0194 12.3257 20.9774 12.3257H17.0671C17.0252 12.3257 16.9912 12.2917 16.9912 12.2497V4.2354C16.9912 4.19344 16.9571 4.15942 16.9152 4.15942H15.4505C15.4085 4.15942 15.3745 4.19344 15.3745 4.2354V13.7967C15.3745 13.8387 15.4085 13.8727 15.4505 13.8727H20.9774C21.0194 13.8727 21.0534 13.8387 21.0534 13.7967V12.4017Z" fill="#191C1D"/>
|
||||
<defs>
|
||||
<linearGradient id="paint0_linear_1251_17291" x1="-2.21904" y1="11.4904" x2="10.7367" y2="6.40599" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#4B2EFB"/>
|
||||
<stop offset="1" stop-color="#E65FFC"/>
|
||||
</linearGradient>
|
||||
<clipPath id="clip0_1251_17291">
|
||||
<rect width="10.4" height="13" fill="white" transform="translate(1 2.5)"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 9.5 KiB |
|
@ -0,0 +1,15 @@
|
|||
<svg width="52" height="18" viewBox="0 0 52 18" fill="currentcolor" xmlns="http://www.w3.org/2000/svg">
|
||||
<g opacity="0.8" clip-path="url(#clip0_1251_17267)">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M1 4.5299C1 4.15639 1 3.96963 1.06856 3.81931C1.12899 3.68684 1.22616 3.57457 1.34851 3.49586C1.48735 3.40655 1.67193 3.38004 2.0411 3.32702L7.3061 2.57085C7.784 2.50221 8.02295 2.46789 8.20864 2.54035C8.37165 2.60396 8.50768 2.72206 8.59369 2.87463C8.69167 3.04844 8.69167 3.2902 8.69167 3.77374V14.2263C8.69167 14.7098 8.69167 14.9516 8.59369 15.1254C8.50768 15.2779 8.37165 15.396 8.20864 15.4596C8.02296 15.5321 7.784 15.4978 7.30611 15.4291H7.3061L2.0411 14.673L2.04108 14.673L2.04106 14.673C1.67192 14.62 1.48734 14.5934 1.34851 14.5041C1.22616 14.4254 1.12899 14.3132 1.06856 14.1807C1 14.0304 1 13.8436 1 13.4701V4.5299ZM6.30838 8.07075C6.30838 7.959 6.30838 7.90312 6.32939 7.85895C6.3479 7.82005 6.37758 7.78756 6.41464 7.76561C6.45672 7.74068 6.51237 7.73562 6.62366 7.7255L7.12199 7.6802H7.122C7.25312 7.66828 7.31868 7.66232 7.3693 7.68419C7.41378 7.7034 7.45053 7.73696 7.47369 7.77951C7.50005 7.82795 7.50005 7.89378 7.50005 8.02544V9.97456C7.50005 10.1062 7.50005 10.1721 7.47369 10.2205C7.45053 10.263 7.41378 10.2966 7.3693 10.3158C7.31868 10.3377 7.25312 10.3317 7.12199 10.3198L6.62366 10.2745C6.51237 10.2644 6.45672 10.2593 6.41464 10.2344C6.37758 10.2124 6.3479 10.1799 6.32939 10.141C6.30838 10.0969 6.30838 10.041 6.30838 9.92925V8.07075ZM10.1866 3.58339H9.44997V14.4167H10.1866C10.6113 14.4167 10.8237 14.4167 10.9859 14.3341C11.1286 14.2614 11.2446 14.1454 11.3173 14.0027C11.4 13.8405 11.4 13.6281 11.4 13.2034V4.79673C11.4 4.37202 11.4 4.15967 11.3173 3.99745C11.2446 3.85476 11.1286 3.73875 10.9859 3.66605C10.8237 3.58339 10.6113 3.58339 10.1866 3.58339Z" fill="currentcolor"/>
|
||||
</g>
|
||||
<path d="M25.3042 13.8727C24.5566 13.8727 23.9109 13.7173 23.3672 13.4066C22.8234 13.0959 22.4059 12.6638 22.1146 12.1104C21.8233 11.5472 21.6777 10.8967 21.6777 10.1588C21.6777 9.4014 21.8282 8.746 22.1292 8.19255C22.4302 7.6391 22.8526 7.20702 23.3963 6.89632C23.9497 6.58561 24.5954 6.43025 25.3334 6.43025C26.081 6.43025 26.7218 6.58561 27.2559 6.89632C27.7996 7.20702 28.222 7.6391 28.523 8.19255C28.824 8.746 28.9745 9.39655 28.9745 10.1442C28.9745 10.8821 28.8191 11.5327 28.5084 12.0958C28.2074 12.659 27.7851 13.0959 27.2413 13.4066C26.6976 13.7076 26.0519 13.863 25.3042 13.8727ZM25.3188 12.4599C25.7266 12.4599 26.0762 12.358 26.3674 12.1541C26.6587 11.9502 26.8821 11.6735 27.0374 11.3239C27.2025 10.9744 27.285 10.5811 27.285 10.1442C27.285 9.69755 27.2073 9.29945 27.052 8.9499C26.8966 8.60036 26.6733 8.32849 26.382 8.13429C26.0907 7.93039 25.7412 7.82844 25.3334 7.82844C24.945 7.82844 24.6003 7.93039 24.2993 8.13429C23.9983 8.3382 23.7653 8.61492 23.6002 8.96447C23.4448 9.31402 23.3623 9.70726 23.3526 10.1442C23.3526 10.5908 23.4303 10.9889 23.5856 11.3385C23.741 11.688 23.9692 11.9647 24.2702 12.1686C24.5712 12.3628 24.9207 12.4599 25.3188 12.4599Z" fill="currentcolor"/>
|
||||
<path d="M36.4994 6.69557C36.4994 6.65361 36.4654 6.61959 36.4234 6.61959H34.9296C34.8876 6.61959 34.8536 6.65361 34.8536 6.69557V14.1494C34.8536 14.6446 34.6691 14.9522 34.3002 15.224C33.9409 15.4959 33.5368 15.5848 32.964 15.5945C32.5659 15.5848 32.1924 15.5493 31.8622 15.4425C31.5526 15.3514 31.2137 15.2176 30.8604 15.0411C30.8219 15.0219 30.775 15.0379 30.7567 15.0768L30.2198 16.2213C30.2042 16.2544 30.2144 16.2939 30.2446 16.3144C30.4084 16.4259 30.6 16.5256 30.8193 16.6133C31.062 16.7104 31.3096 16.7881 31.5621 16.8463C31.8242 16.9143 32.0951 16.971 32.3281 17.0001C32.5708 17.0292 32.8 17.0332 32.9457 17.0332C33.6836 17.0332 34.3147 16.9167 34.8391 16.6836C35.3731 16.4506 35.7809 16.1205 36.0625 15.6932C36.3538 15.266 36.4994 14.7563 36.4994 14.164V6.69557ZM35.3104 11.5198C35.2881 11.4671 35.2178 11.4569 35.1803 11.5C34.8943 11.8287 34.6043 12.0616 34.3293 12.2123C34.038 12.3774 33.703 12.4599 33.3244 12.4599C32.936 12.4599 32.5961 12.3628 32.3049 12.1686C32.0233 11.9647 31.8097 11.688 31.664 11.3385C31.5184 10.9889 31.4455 10.586 31.4455 10.1296C31.4455 9.69269 31.5184 9.30431 31.664 8.96447C31.8097 8.61492 32.0233 8.3382 32.3049 8.13429C32.5961 7.93039 32.9408 7.82844 33.3389 7.82844C33.7079 7.82844 33.9992 7.90612 34.3002 8.06147C34.5812 8.20197 34.8803 8.52282 35.1376 8.85792C35.1735 8.90461 35.2468 8.89592 35.2698 8.84172L35.6831 7.86653C35.6932 7.84278 35.6906 7.81558 35.6759 7.79442C35.1544 7.04603 34.2722 6.43025 33.2679 6.43025C32.5397 6.43025 31.965 6.58561 31.431 6.89632C30.897 7.20702 30.4843 7.6391 30.193 8.19255C29.9114 8.746 29.7706 9.39169 29.7706 10.1296C29.7706 10.887 29.9114 11.5472 30.193 12.1104C30.4746 12.6638 30.8775 13.0959 31.4019 13.4066C31.9359 13.7173 32.567 13.8727 33.2952 13.8727C33.5671 13.8727 33.8487 13.8193 34.14 13.7125C34.441 13.6154 34.7323 13.4697 35.0138 13.2755C35.2832 13.0898 35.5215 12.8684 35.7287 12.6115C35.7461 12.59 35.75 12.5606 35.7392 12.5352L35.3104 11.5198Z" fill="currentcolor"/>
|
||||
<path d="M41.9863 6.75383C41.9863 6.71187 41.9523 6.67785 41.9104 6.67785H40.2855C40.2435 6.67785 40.2095 6.64383 40.2095 6.60187V4.61531C40.2095 4.57334 40.1755 4.53933 40.1335 4.53933H38.6542C38.6123 4.53933 38.5783 4.57334 38.5783 4.61531V6.60187C38.5783 6.64383 38.5442 6.67785 38.5023 6.67785H37.5127C37.4704 6.67785 37.4363 6.71236 37.4367 6.75463L37.4497 7.98629C37.4501 8.02794 37.484 8.06147 37.5257 8.06147H38.5023C38.5442 8.06147 38.5783 8.09549 38.5783 8.13745V11.5715C38.5783 12.0861 38.6802 12.5231 38.8841 12.8823C39.0977 13.2319 39.389 13.4989 39.758 13.6834C40.1269 13.8678 40.5736 13.9601 41.0979 13.9601C41.2436 13.9601 41.3989 13.9407 41.564 13.9018C41.7387 13.863 41.9076 13.8221 42.0532 13.7638C42.1833 13.7151 42.4366 13.588 42.5658 13.5131C42.6001 13.4932 42.6108 13.4498 42.5914 13.4151L41.9903 12.3556C41.9714 12.3219 41.9304 12.3079 41.8944 12.3216C41.7972 12.3587 41.6968 12.3892 41.5931 12.4131C41.4669 12.4422 41.3407 12.4568 41.2144 12.4568C40.8746 12.4568 40.6221 12.4211 40.4571 12.1978C40.292 11.9647 40.2095 11.6686 40.2095 11.3093V8.13745C40.2095 8.09549 40.2435 8.06147 40.2855 8.06147H41.9104C41.9523 8.06147 41.9863 8.02745 41.9863 7.98549V6.75383Z" fill="currentcolor"/>
|
||||
<path d="M46.4061 13.8727C45.6584 13.8727 45.0128 13.7173 44.469 13.4066C43.9253 13.0959 43.5078 12.6638 43.2165 12.1104C42.9252 11.5472 42.7795 10.8967 42.7795 10.1588C42.7795 9.4014 42.93 8.746 43.231 8.19255C43.532 7.6391 43.9544 7.20702 44.4981 6.89632C45.0516 6.58561 45.6973 6.43025 46.4352 6.43025C47.1829 6.43025 47.8237 6.58561 48.3577 6.89632C48.9015 7.20702 49.3238 7.6391 49.6248 8.19255C49.9258 8.746 50.0763 9.39655 50.0763 10.1442C50.0763 10.8821 49.921 11.5327 49.6103 12.0958C49.3093 12.659 48.8869 13.0959 48.3432 13.4066C47.7994 13.7076 47.1537 13.863 46.4061 13.8727ZM46.4207 12.4599C46.8285 12.4599 47.178 12.358 47.4693 12.1541C47.7606 11.9502 47.9839 11.6735 48.1393 11.3239C48.3043 10.9744 48.3869 10.5811 48.3869 10.1442C48.3869 9.69755 48.3092 9.29945 48.1538 8.9499C47.9985 8.60036 47.7751 8.32849 47.4839 8.13429C47.1926 7.93039 46.843 7.82844 46.4352 7.82844C46.0468 7.82844 45.7021 7.93039 45.4011 8.13429C45.1001 8.3382 44.8671 8.61492 44.702 8.96447C44.5467 9.31402 44.4642 9.70726 44.4544 10.1442C44.4544 10.5908 44.5321 10.9889 44.6875 11.3385C44.8428 11.688 45.071 11.9647 45.372 12.1686C45.673 12.3628 46.0226 12.4599 46.4207 12.4599Z" fill="currentcolor"/>
|
||||
<path d="M21.0534 12.4017C21.0534 12.3597 21.0194 12.3257 20.9774 12.3257H17.0671C17.0252 12.3257 16.9912 12.2917 16.9912 12.2497V4.2354C16.9912 4.19344 16.9571 4.15942 16.9152 4.15942H15.4505C15.4085 4.15942 15.3745 4.19344 15.3745 4.2354V13.7967C15.3745 13.8387 15.4085 13.8727 15.4505 13.8727H20.9774C21.0194 13.8727 21.0534 13.8387 21.0534 13.7967V12.4017Z" fill="currentcolor"/>
|
||||
<defs>
|
||||
<clipPath id="clip0_1251_17267">
|
||||
<rect width="10.4" height="13" fill="white" transform="translate(1 2.5)"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
After Width: | Height: | Size: 7.7 KiB |
|
@ -0,0 +1,3 @@
|
|||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M12 10C11.6044 10 11.2178 10.1173 10.8889 10.3371C10.56 10.5568 10.3036 10.8692 10.1522 11.2346C10.0009 11.6001 9.96126 12.0022 10.0384 12.3902C10.1156 12.7781 10.3061 13.1345 10.5858 13.4142C10.8655 13.6939 11.2219 13.8844 11.6098 13.9616C11.9978 14.0387 12.3999 13.9991 12.7654 13.8478C13.1308 13.6964 13.4432 13.44 13.6629 13.1111C13.8827 12.7822 14 12.3956 14 12C14 11.4696 13.7893 10.9609 13.4142 10.5858C13.0391 10.2107 12.5304 10 12 10ZM5 10C4.60444 10 4.21776 10.1173 3.88886 10.3371C3.55996 10.5568 3.30362 10.8692 3.15224 11.2346C3.00087 11.6001 2.96126 12.0022 3.03843 12.3902C3.1156 12.7781 3.30608 13.1345 3.58579 13.4142C3.86549 13.6939 4.22186 13.8844 4.60982 13.9616C4.99778 14.0387 5.39992 13.9991 5.76537 13.8478C6.13082 13.6964 6.44318 13.44 6.66294 13.1111C6.8827 12.7822 7 12.3956 7 12C7 11.4696 6.78929 10.9609 6.41421 10.5858C6.03914 10.2107 5.53043 10 5 10ZM19 10C18.6044 10 18.2178 10.1173 17.8889 10.3371C17.56 10.5568 17.3036 10.8692 17.1522 11.2346C17.0009 11.6001 16.9613 12.0022 17.0384 12.3902C17.1156 12.7781 17.3061 13.1345 17.5858 13.4142C17.8655 13.6939 18.2219 13.8844 18.6098 13.9616C18.9978 14.0387 19.3999 13.9991 19.7654 13.8478C20.1308 13.6964 20.4432 13.44 20.6629 13.1111C20.8827 12.7822 21 12.3956 21 12C21 11.4696 20.7893 10.9609 20.4142 10.5858C20.0391 10.2107 19.5304 10 19 10Z" fill="currentcolor"/>
|
||||
</svg>
|
After Width: | Height: | Size: 1.4 KiB |
|
@ -0,0 +1,3 @@
|
|||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M13.4099 12.0002L17.7099 7.71019C17.8982 7.52188 18.004 7.26649 18.004 7.00019C18.004 6.73388 17.8982 6.47849 17.7099 6.29019C17.5216 6.10188 17.2662 5.99609 16.9999 5.99609C16.7336 5.99609 16.4782 6.10188 16.2899 6.29019L11.9999 10.5902L7.70994 6.29019C7.52164 6.10188 7.26624 5.99609 6.99994 5.99609C6.73364 5.99609 6.47824 6.10188 6.28994 6.29019C6.10164 6.47849 5.99585 6.73388 5.99585 7.00019C5.99585 7.26649 6.10164 7.52188 6.28994 7.71019L10.5899 12.0002L6.28994 16.2902C6.19621 16.3831 6.12182 16.4937 6.07105 16.6156C6.02028 16.7375 5.99414 16.8682 5.99414 17.0002C5.99414 17.1322 6.02028 17.2629 6.07105 17.3848C6.12182 17.5066 6.19621 17.6172 6.28994 17.7102C6.3829 17.8039 6.4935 17.8783 6.61536 17.9291C6.73722 17.9798 6.86793 18.006 6.99994 18.006C7.13195 18.006 7.26266 17.9798 7.38452 17.9291C7.50638 17.8783 7.61698 17.8039 7.70994 17.7102L11.9999 13.4102L16.2899 17.7102C16.3829 17.8039 16.4935 17.8783 16.6154 17.9291C16.7372 17.9798 16.8679 18.006 16.9999 18.006C17.132 18.006 17.2627 17.9798 17.3845 17.9291C17.5064 17.8783 17.617 17.8039 17.7099 17.7102C17.8037 17.6172 17.8781 17.5066 17.9288 17.3848C17.9796 17.2629 18.0057 17.1322 18.0057 17.0002C18.0057 16.8682 17.9796 16.7375 17.9288 16.6156C17.8781 16.4937 17.8037 16.3831 17.7099 16.2902L13.4099 12.0002Z" fill="currentcolor"/>
|
||||
</svg>
|
After Width: | Height: | Size: 1.4 KiB |
|
@ -0,0 +1,4 @@
|
|||
<svg width="20" height="20" viewBox="0 0 20 20" fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M11.6665 6.66699H12.4998C12.7209 6.66699 12.9328 6.5792 13.0891 6.42291C13.2454 6.26663 13.3332 6.05467 13.3332 5.83366C13.3332 5.61265 13.2454 5.40068 13.0891 5.2444C12.9328 5.08812 12.7209 5.00033 12.4998 5.00033H11.6665C11.4455 5.00033 11.2335 5.08812 11.0772 5.2444C10.921 5.40068 10.8332 5.61265 10.8332 5.83366C10.8332 6.05467 10.921 6.26663 11.0772 6.42291C11.2335 6.5792 11.4455 6.66699 11.6665 6.66699ZM11.6665 10.0003H12.4998C12.7209 10.0003 12.9328 9.91253 13.0891 9.75625C13.2454 9.59997 13.3332 9.38801 13.3332 9.16699C13.3332 8.94598 13.2454 8.73402 13.0891 8.57774C12.9328 8.42146 12.7209 8.33366 12.4998 8.33366H11.6665C11.4455 8.33366 11.2335 8.42146 11.0772 8.57774C10.921 8.73402 10.8332 8.94598 10.8332 9.16699C10.8332 9.38801 10.921 9.59997 11.0772 9.75625C11.2335 9.91253 11.4455 10.0003 11.6665 10.0003ZM7.49984 6.66699H8.33317C8.55418 6.66699 8.76615 6.5792 8.92243 6.42291C9.07871 6.26663 9.1665 6.05467 9.1665 5.83366C9.1665 5.61265 9.07871 5.40068 8.92243 5.2444C8.76615 5.08812 8.55418 5.00033 8.33317 5.00033H7.49984C7.27882 5.00033 7.06686 5.08812 6.91058 5.2444C6.7543 5.40068 6.6665 5.61265 6.6665 5.83366C6.6665 6.05467 6.7543 6.26663 6.91058 6.42291C7.06686 6.5792 7.27882 6.66699 7.49984 6.66699ZM7.49984 10.0003H8.33317C8.55418 10.0003 8.76615 9.91253 8.92243 9.75625C9.07871 9.59997 9.1665 9.38801 9.1665 9.16699C9.1665 8.94598 9.07871 8.73402 8.92243 8.57774C8.76615 8.42146 8.55418 8.33366 8.33317 8.33366H7.49984C7.27882 8.33366 7.06686 8.42146 6.91058 8.57774C6.7543 8.73402 6.6665 8.94598 6.6665 9.16699C6.6665 9.38801 6.7543 9.59997 6.91058 9.75625C7.06686 9.91253 7.27882 10.0003 7.49984 10.0003ZM17.4998 16.667H16.6665V2.50033C16.6665 2.27931 16.5787 2.06735 16.4224 1.91107C16.2661 1.75479 16.0542 1.66699 15.8332 1.66699H4.1665C3.94549 1.66699 3.73353 1.75479 3.57725 1.91107C3.42097 2.06735 3.33317 2.27931 3.33317 2.50033V16.667H2.49984C2.27882 16.667 2.06686 16.7548 1.91058 16.9111C1.7543 17.0674 1.6665 17.2793 1.6665 17.5003C1.6665 17.7213 1.7543 17.9333 1.91058 18.0896C2.06686 18.2459 2.27882 18.3337 2.49984 18.3337H17.4998C17.7209 18.3337 17.9328 18.2459 18.0891 18.0896C18.2454 17.9333 18.3332 17.7213 18.3332 17.5003C18.3332 17.2793 18.2454 17.0674 18.0891 16.9111C17.9328 16.7548 17.7209 16.667 17.4998 16.667ZM10.8332 16.667H9.1665V13.3337H10.8332V16.667ZM14.9998 16.667H12.4998V12.5003C12.4998 12.2793 12.412 12.0674 12.2558 11.9111C12.0995 11.7548 11.8875 11.667 11.6665 11.667H8.33317C8.11216 11.667 7.9002 11.7548 7.74392 11.9111C7.58764 12.0674 7.49984 12.2793 7.49984 12.5003V16.667H4.99984V3.33366H14.9998V16.667Z" fill="currentcolor"/>
|
||||
</svg>
|
After Width: | Height: | Size: 2.7 KiB |
|
@ -0,0 +1,3 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M4.92879 3.92888C4.53826 4.3194 4.53826 4.95257 4.92879 5.34309L6.50507 6.91938C3.79112 8.79701 2 11.4523 2 12C2 12.866 6.47715 19 12 19C13.8197 19 15.5259 18.3341 16.9958 17.4101L17.6567 18.071C18.0472 18.4615 18.6804 18.4615 19.0709 18.071C19.4614 17.6805 19.4614 17.0473 19.0709 16.6568L6.343 3.92888C5.95248 3.53836 5.31931 3.53836 4.92879 3.92888ZM14.6137 15.028L8.97197 9.38628C8.36632 10.0873 8 11.0009 8 12C8 14.2091 9.79086 16 12 16C12.9991 16 13.9127 15.6337 14.6137 15.028ZM13.5568 8.31427C14.5141 8.7191 15.2809 9.48594 15.6857 10.4432L20.0754 14.8329C21.2856 13.5325 22 12.3459 22 12C22 11.134 17.5228 5 12 5C11.4584 5 10.9269 5.05898 10.4087 5.16619L13.5568 8.31427Z" fill="currentcolor"/>
|
||||
</svg>
|
After Width: | Height: | Size: 823 B |
|
@ -0,0 +1,3 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M22 12C22 12.866 17.5228 19 12 19C6.47715 19 2 12.866 2 12C2 11.134 6.47715 5 12 5C17.5228 5 22 11.134 22 12ZM16 12C16 14.2091 14.2091 16 12 16C9.79086 16 8 14.2091 8 12C8 9.79086 9.79086 8 12 8C14.2091 8 16 9.79086 16 12ZM11 14C12.1046 14 13 13.1046 13 12C13 10.8954 12.1046 10 11 10C9.89543 10 9 10.8954 9 12C9 13.1046 9.89543 14 11 14Z" fill="currentcolor"/>
|
||||
</svg>
|
After Width: | Height: | Size: 481 B |
|
@ -0,0 +1,3 @@
|
|||
<svg width="16" height="17" viewBox="0 0 16 17" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M6 10.5C3.791 10.5 2 8.709 2 6.5C2 4.291 3.791 2.5 6 2.5C8.209 2.5 10 4.291 10 6.5C10 8.709 8.209 10.5 6 10.5ZM15.707 14.793L10.887 9.973C11.585 8.992 12 7.796 12 6.5C12 3.187 9.313 0.5 6 0.5C2.687 0.5 0 3.187 0 6.5C0 9.813 2.687 12.5 6 12.5C7.296 12.5 8.492 12.085 9.473 11.387L14.293 16.207C14.488 16.402 14.744 16.5 15 16.5C15.256 16.5 15.512 16.402 15.707 16.207C16.098 15.816 16.098 15.184 15.707 14.793Z" fill="currentcolor"/>
|
||||
</svg>
|
After Width: | Height: | Size: 587 B |
|
@ -0,0 +1,3 @@
|
|||
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M16.2825 6.71315L13.2825 3.71315C13.2126 3.64322 13.1295 3.58775 13.0382 3.54991C12.9468 3.51206 12.8489 3.49258 12.75 3.49258C12.5503 3.49258 12.3587 3.57192 12.2175 3.71315C12.0763 3.85438 11.9969 4.04592 11.9969 4.24565C11.9969 4.44538 12.0763 4.63692 12.2175 4.77815L13.9425 6.49565H5.24998C5.05107 6.49565 4.86031 6.57467 4.71965 6.71532C4.579 6.85597 4.49998 7.04674 4.49998 7.24565C4.49998 7.44456 4.579 7.63533 4.71965 7.77598C4.86031 7.91663 5.05107 7.99565 5.24998 7.99565H15.75C15.8981 7.99491 16.0426 7.95036 16.1654 7.86761C16.2882 7.78486 16.3837 7.66762 16.44 7.53065C16.4974 7.39407 16.5131 7.24353 16.4851 7.09804C16.457 6.95255 16.3866 6.81862 16.2825 6.71315ZM12.75 10.4957H2.24998C2.10191 10.4964 1.95738 10.5409 1.83459 10.6237C1.7118 10.7064 1.61625 10.8237 1.55998 10.9607C1.50255 11.0972 1.48686 11.2478 1.51489 11.3933C1.54292 11.5388 1.61341 11.6727 1.71748 11.7782L4.71748 14.7782C4.78721 14.8484 4.87016 14.9042 4.96155 14.9423C5.05294 14.9804 5.15097 15 5.24998 15C5.34899 15 5.44702 14.9804 5.53842 14.9423C5.62981 14.9042 5.71276 14.8484 5.78248 14.7782C5.85278 14.7084 5.90858 14.6255 5.94665 14.5341C5.98473 14.4427 6.00433 14.3447 6.00433 14.2457C6.00433 14.1466 5.98473 14.0486 5.94665 13.9572C5.90858 13.8658 5.85278 13.7829 5.78248 13.7132L4.05748 11.9957H12.75C12.9489 11.9957 13.1397 11.9166 13.2803 11.776C13.421 11.6353 13.5 11.4446 13.5 11.2457C13.5 11.0467 13.421 10.856 13.2803 10.7153C13.1397 10.5747 12.9489 10.4957 12.75 10.4957Z" fill="currentcolor"/>
|
||||
</svg>
|
After Width: | Height: | Size: 1.6 KiB |
6
packages/experience-legacy/src/assets/index.d.ts
vendored
Normal file
|
@ -0,0 +1,6 @@
|
|||
interface SvgComponent extends React.FunctionComponent<React.SVGAttributes<SVGElement>> {}
|
||||
|
||||
declare module '@/assets/icons/*.svg' {
|
||||
const value: SvgComponent;
|
||||
export default value;
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
@use '@/scss/underscore' as _;
|
||||
|
||||
$logo-height: 40px;
|
||||
|
||||
.container {
|
||||
width: 100%;
|
||||
@include _.flex-column;
|
||||
}
|
||||
|
||||
.logoWrapper {
|
||||
@include _.flex-row;
|
||||
}
|
||||
|
||||
.connectIcon {
|
||||
color: var(--color-neutral-variant-80);
|
||||
margin: 0 _.unit(3);
|
||||
}
|
||||
|
||||
.logo {
|
||||
height: $logo-height;
|
||||
width: auto;
|
||||
@include _.image-align-center;
|
||||
}
|
||||
|
||||
.headline {
|
||||
flex-shrink: 0;
|
||||
text-align: center;
|
||||
color: var(--color-type-primary);
|
||||
@include _.multi-line-ellipsis(2);
|
||||
}
|
||||
|
||||
:global(body.mobile) {
|
||||
.container {
|
||||
height: 15vh;
|
||||
min-height: 92px;
|
||||
max-height: 148px;
|
||||
}
|
||||
|
||||
.logoWrapper:not(:last-child) {
|
||||
margin-bottom: _.unit(2);
|
||||
}
|
||||
|
||||
.headline {
|
||||
font: var(--font-title-1);
|
||||
}
|
||||
}
|
||||
|
||||
:global(body.desktop) {
|
||||
.logoWrapper:not(:last-child) {
|
||||
margin-bottom: _.unit(3);
|
||||
}
|
||||
|
||||
.headline {
|
||||
font: var(--font-title-2);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
import { render } from '@testing-library/react';
|
||||
|
||||
import { appLogo } from '@/__mocks__/logto';
|
||||
|
||||
import BrandingHeader from '.';
|
||||
|
||||
describe('BrandingHeader UI Component', () => {
|
||||
const appHeadline = 'description.sign_in_to_your_account';
|
||||
|
||||
test('render logo with context', () => {
|
||||
const { queryByText, container } = render(
|
||||
<BrandingHeader logo={appLogo} headline={appHeadline} />
|
||||
);
|
||||
expect(queryByText(appHeadline)).not.toBeNull();
|
||||
expect(container.querySelector('img')).not.toBeNull();
|
||||
});
|
||||
});
|
|
@ -0,0 +1,57 @@
|
|||
import type { Nullable } from '@silverhand/essentials';
|
||||
import classNames from 'classnames';
|
||||
import type { TFuncKey } from 'i18next';
|
||||
|
||||
import ConnectIcon from '@/assets/icons/connect-icon.svg?react';
|
||||
|
||||
import DynamicT from '../DynamicT';
|
||||
|
||||
import styles from './index.module.scss';
|
||||
|
||||
export type Props = {
|
||||
readonly className?: string;
|
||||
readonly logo?: Nullable<string>;
|
||||
readonly thirdPartyLogo?: Nullable<string>;
|
||||
readonly headline?: TFuncKey;
|
||||
readonly headlineInterpolation?: Record<string, unknown>;
|
||||
};
|
||||
|
||||
const BrandingHeader = ({
|
||||
logo,
|
||||
thirdPartyLogo,
|
||||
headline,
|
||||
headlineInterpolation,
|
||||
className,
|
||||
}: Props) => {
|
||||
const shouldShowLogo = Boolean(thirdPartyLogo ?? logo);
|
||||
const shouldConnectSvg = Boolean(thirdPartyLogo && logo);
|
||||
|
||||
return (
|
||||
<div className={classNames(styles.container, className)}>
|
||||
{shouldShowLogo && (
|
||||
<div className={styles.logoWrapper}>
|
||||
{thirdPartyLogo && (
|
||||
<img
|
||||
className={styles.logo}
|
||||
alt="third party logo"
|
||||
src={thirdPartyLogo}
|
||||
crossOrigin="anonymous"
|
||||
/>
|
||||
)}
|
||||
{shouldConnectSvg && <ConnectIcon className={styles.connectIcon} />}
|
||||
{logo && (
|
||||
<img className={styles.logo} alt="app logo" src={logo} crossOrigin="anonymous" />
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{headline && (
|
||||
<div className={styles.headline}>
|
||||
<DynamicT forKey={headline} interpolation={headlineInterpolation} />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default BrandingHeader;
|
|
@ -0,0 +1,29 @@
|
|||
@use '@/scss/underscore' as _;
|
||||
|
||||
.iconButton {
|
||||
border: none;
|
||||
outline: none;
|
||||
background: none;
|
||||
border-color: none;
|
||||
border-radius: 6px;
|
||||
padding: _.unit(1);
|
||||
@include _.flex-column;
|
||||
cursor: pointer;
|
||||
|
||||
> svg {
|
||||
color: var(--color-type-secondary);
|
||||
}
|
||||
|
||||
&:active {
|
||||
background: var(--color-overlay-neutral-pressed);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
:global(body.desktop) {
|
||||
.iconButton {
|
||||
&:hover:not(:active) {
|
||||
background: var(--color-overlay-neutral-hover);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
import classNames from 'classnames';
|
||||
import type { HTMLProps, Ref } from 'react';
|
||||
import { forwardRef } from 'react';
|
||||
|
||||
import styles from './IconButton.module.scss';
|
||||
|
||||
export type Props = Omit<HTMLProps<HTMLButtonElement>, 'type'>;
|
||||
|
||||
const IconButton = ({ children, className, ...rest }: Props, ref: Ref<HTMLButtonElement>) => {
|
||||
return (
|
||||
<button ref={ref} type="button" className={classNames(styles.iconButton, className)} {...rest}>
|
||||
{children}
|
||||
</button>
|
||||
);
|
||||
};
|
||||
|
||||
export default forwardRef<HTMLButtonElement, Props>(IconButton);
|
|
@ -0,0 +1,39 @@
|
|||
@use '@/scss/underscore' as _;
|
||||
|
||||
.mfaFactorButton {
|
||||
padding: _.unit(3) _.unit(4) _.unit(3) _.unit(3);
|
||||
height: unset;
|
||||
gap: _.unit(4);
|
||||
border-radius: 12px;
|
||||
border-color: var(--color-line-divider);
|
||||
}
|
||||
|
||||
.icon {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
color: var(--color-type-secondary);
|
||||
}
|
||||
|
||||
.title {
|
||||
flex: 1;
|
||||
@include _.flex-column;
|
||||
align-items: flex-start;
|
||||
text-align: left;
|
||||
|
||||
.name {
|
||||
font: var(--font-label-1);
|
||||
}
|
||||
|
||||
.description {
|
||||
font: var(--font-body-2);
|
||||
color: var(--color-type-secondary);
|
||||
}
|
||||
}
|
||||
|
||||
:global(body.desktop) {
|
||||
.title {
|
||||
.name {
|
||||
font: var(--font-label-2);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
import { MfaFactor } from '@logto/schemas';
|
||||
import classNames from 'classnames';
|
||||
import { type TFuncKey } from 'i18next';
|
||||
|
||||
import ArrowNext from '@/assets/icons/arrow-next.svg?react';
|
||||
import FactorBackupCode from '@/assets/icons/factor-backup-code.svg?react';
|
||||
import FactorTotp from '@/assets/icons/factor-totp.svg?react';
|
||||
import FactorWebAuthn from '@/assets/icons/factor-webauthn.svg?react';
|
||||
|
||||
import DynamicT from '../DynamicT';
|
||||
|
||||
import mfaFactorButtonStyles from './MfaFactorButton.module.scss';
|
||||
import styles from './index.module.scss';
|
||||
|
||||
export type Props = {
|
||||
readonly factor: MfaFactor;
|
||||
readonly isBinding: boolean;
|
||||
readonly onClick?: () => void;
|
||||
};
|
||||
|
||||
const factorIcon: Record<MfaFactor, SvgComponent> = {
|
||||
[MfaFactor.TOTP]: FactorTotp,
|
||||
[MfaFactor.WebAuthn]: FactorWebAuthn,
|
||||
[MfaFactor.BackupCode]: FactorBackupCode,
|
||||
};
|
||||
|
||||
const factorName: Record<MfaFactor, TFuncKey> = {
|
||||
[MfaFactor.TOTP]: 'mfa.totp',
|
||||
[MfaFactor.WebAuthn]: 'mfa.webauthn',
|
||||
[MfaFactor.BackupCode]: 'mfa.backup_code',
|
||||
};
|
||||
|
||||
const factorDescription: Record<MfaFactor, TFuncKey> = {
|
||||
[MfaFactor.TOTP]: 'mfa.verify_totp_description',
|
||||
[MfaFactor.WebAuthn]: 'mfa.verify_webauthn_description',
|
||||
[MfaFactor.BackupCode]: 'mfa.verify_backup_code_description',
|
||||
};
|
||||
|
||||
const linkFactorDescription: Record<MfaFactor, TFuncKey> = {
|
||||
[MfaFactor.TOTP]: 'mfa.link_totp_description',
|
||||
[MfaFactor.WebAuthn]: 'mfa.link_webauthn_description',
|
||||
[MfaFactor.BackupCode]: 'mfa.link_backup_code_description',
|
||||
};
|
||||
|
||||
const MfaFactorButton = ({ factor, isBinding, onClick }: Props) => {
|
||||
const Icon = factorIcon[factor];
|
||||
|
||||
return (
|
||||
<button
|
||||
className={classNames(
|
||||
styles.button,
|
||||
styles.secondary,
|
||||
styles.large,
|
||||
mfaFactorButtonStyles.mfaFactorButton
|
||||
)}
|
||||
type="button"
|
||||
onClick={onClick}
|
||||
>
|
||||
<Icon className={mfaFactorButtonStyles.icon} />
|
||||
<div className={mfaFactorButtonStyles.title}>
|
||||
<div className={mfaFactorButtonStyles.name}>
|
||||
<DynamicT forKey={factorName[factor]} />
|
||||
</div>
|
||||
<div className={mfaFactorButtonStyles.description}>
|
||||
<DynamicT forKey={(isBinding ? linkFactorDescription : factorDescription)[factor]} />
|
||||
</div>
|
||||
</div>
|
||||
<ArrowNext className={mfaFactorButtonStyles.icon} />
|
||||
</button>
|
||||
);
|
||||
};
|
||||
|
||||
export default MfaFactorButton;
|
|
@ -0,0 +1,14 @@
|
|||
.icon {
|
||||
animation: rotating 1s linear infinite;
|
||||
}
|
||||
|
||||
|
||||
@keyframes rotating {
|
||||
from {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
import Ring from '@/assets/icons/loading-ring.svg?react';
|
||||
|
||||
import RotatingRingIconStyles from './RotatingRingIcon.module.scss';
|
||||
|
||||
const RotatingRingIcon = () => <Ring className={RotatingRingIconStyles.icon} />;
|
||||
|
||||
export default RotatingRingIcon;
|