+ {amount_of_steps.map((st, index) => {
+ const active = step === index + 1;
+
+ return (
+
setStep(index + 1)}
+ className={active ? 'progress-bar-rectangle' : 'progress-bar-circle'}
+ />
+ );
+ })}
+
+ );
+};
+
+export default ProgressBarOnboarding;
diff --git a/packages/components/src/components/timeline/timeline.jsx b/packages/components/src/components/timeline/timeline.jsx
new file mode 100644
index 000000000000..b43858e6802c
--- /dev/null
+++ b/packages/components/src/components/timeline/timeline.jsx
@@ -0,0 +1,43 @@
+import React from 'react';
+import classNames from 'classnames';
+import Text from '../text';
+
+const Oval = ({ children }) => {
+ return (
+
+
+ {children}
+
+
+ );
+};
+
+const Timeline = ({ children, disabled_items, ...props }) => {
+ return (
+
+ {children.map((child, idx) => (
+
+
{idx + 1}
+
+
+ {child.props.item_title}
+
+
{child}
+
+
+ ))}
+
+ );
+};
+
+const Item = ({ children, ...props }) =>
{children}
;
+
+Timeline.Item = Item;
+
+export default Timeline;
diff --git a/packages/components/src/index.js b/packages/components/src/index.js
index 27052523d165..2cf5b4d571d6 100644
--- a/packages/components/src/index.js
+++ b/packages/components/src/index.js
@@ -80,6 +80,7 @@ export { default as PopoverMobile } from './components/popover-mobile';
export { default as Popup } from './components/popup';
export { default as PopoverMessageCheckbox } from './components/popover-message-checkbox';
export { default as ProgressBar } from './components/progress-bar';
+export { default as ProgressBarOnboarding } from './components/progress-bar-onboarding';
export { default as ProgressIndicator } from './components/progress-indicator';
export { default as ProgressSlider } from './components/progress-slider';
export { default as ProgressSliderMobile } from './components/progress-slider-mobile';
diff --git a/packages/components/stories/icon/README.md b/packages/components/stories/icon/README.md
index 35366aaa7cd3..eca70000bd98 100644
--- a/packages/components/stories/icon/README.md
+++ b/packages/components/stories/icon/README.md
@@ -1,12 +1,11 @@
## **Usage**
+
1. Using icons within the Components package
```jsx
import Icon from '../icon'; // please import the relative path in Components
- const App = () => (
-
- );
+ const App = () =>
;
```
2. Using icons as a UI component library (in Trader or Bot)
@@ -14,25 +13,21 @@
```jsx
import { Icon } from '@deriv/components';
- const App = () => (
-
- );
+ const App = () =>
;
```
-
## **Props**
-|Name | Type | Default | Description
-|--|---|--|--|
-| size | `number | string` | `16` | Sets the width and height of the icon
-| height | `number | string` | `16` | Sets the height of the icon
-| width | `number | string` | `16` | Sets the width of the icon
-| color | `'active' |` `'disabled' |` `'secondary' |` `'red' |` `'green' |` `'brand' `| primary fill color: ```var(--text-general)```
secondary fill color: ```var(--text-less-prominent)```
tertiary fill color: ```var(--general-section-1)```| Sets the icon color with our current theme colors palette
-| custom_color | `string (hex color or CSS variable)` | - | Sets the icon custom color (on the primary fill color only)
-| onClick | `function` | - | Adds onClick event handler
-| onMouseEnter | `function` | - | Adds onMouseEnter event handler
-| onMouseLeave | `function` | - | Adds onMouseLeave event handler
-
+| Name | Type | Default | Description |
+| ------------ | ------------------------------------ | ------------- | ----------------------------------------------------------- | ------------------------------------- | ---------- | ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------- |
+| size | `number | string` | `16` | Sets the width and height of the icon |
+| height | `number | string` | `16` | Sets the height of the icon |
+| width | `number | string` | `16` | Sets the width of the icon |
+| color | `'active' | ` `'disabled' | ` `'secondary' | ` `'red' | ` `'green' | ` `'brand' ` | primary fill color: `var(--text-general)`
secondary fill color: `var(--text-less-prominent)`
tertiary fill color: `var(--general-section-1)` | Sets the icon color with our current theme colors palette |
+| custom_color | `string (hex color or CSS variable)` | - | Sets the icon custom color (on the primary fill color only) |
+| onClick | `function` | - | Adds onClick event handler |
+| onMouseEnter | `function` | - | Adds onMouseEnter event handler |
+| onMouseLeave | `function` | - | Adds onMouseLeave event handler |
#### Example:
@@ -42,7 +37,7 @@ import { Icon } from '@deriv/components';
const App = () => (
<>
// icon with different width and height
-
// icon with the same width and height
+
// icon with the same width and height
>
@@ -50,8 +45,9 @@ const App = () => (
```
## **Adding new icon**
+
1. Add an `.svg` icon file under one of the svg folders (or add a new folder) in `components/icon` folder.
-2. Make sure the icon file name is in `kebab-case` and is prefix with `ic-`. The icon file name will be converted to a `PascalCase` as the icon name.
+2. Make sure the icon file name is in `kebab-case` and is prefix with `ic-`. The icon file name will be converted to a `PascalCase` as the icon name.
- Example:
@@ -68,9 +64,11 @@ const App = () => (
3. Run `svgo` with the `--enable=sortAttrs` flag to clean and sort the icon attributes (for readibility).
```sh
- svgo src/components/icon/**/**.svg --enable=sortAttrs
+ npx svgo src/components/icon/**/**.svg --enable=sortAttrs
```
+ Note: If there are multiple svg files you are adding in the component, please make sure that the id's are not duplicated due to minification.
+
4. Run `npm run build` to rebuild the Icon component.
- Note: Running `npm run build` command will run the `npm run build:icons`. This command will then rewrite `icons.js` file and `stories/icon/icons.js` files with the newly added icon imports.
@@ -83,8 +81,10 @@ const App = () => (
```
## **Theming icon**
+
1. Theming has to be done manually for now. You need add CSS variables to each path that needs to be themed.
2. Rules:
+
- replace primary `
` fill or stroke color with `var(--fill-color1)`
- replace secondary `
` fill or stroke color with `var(--fill-color2)`
- replace background `
` or `
` fill color with `var(--fill-color3)`
@@ -102,6 +102,7 @@ const App = () => (
```
## **Adding new SVG sprite**
+
1. Configure webpack to create new SVG sprite:
```js
diff --git a/packages/components/stories/icon/icons.js b/packages/components/stories/icon/icons.js
index 59c0923563e1..78d460ba1866 100644
--- a/packages/components/stories/icon/icons.js
+++ b/packages/components/stories/icon/icons.js
@@ -2,11 +2,64 @@
export const icons =
{
+ 'appstore': [
+ 'IcAppstoreAddRounded',
+ 'IcAppstoreAddSquare',
+ 'IcAppstoreAdd',
+ 'IcAppstoreAppCardDefaultBackgroundSmall',
+ 'IcAppstoreAppCardDefaultBackground',
+ 'IcAppstoreCfdsTradeType',
+ 'IcAppstoreCheck',
+ 'IcAppstoreCheckedRedBg',
+ 'IcAppstoreCheckedTransparent',
+ 'IcAppstoreChecked',
+ 'IcAppstoreCircle',
+ 'IcAppstoreCloseDark',
+ 'IcAppstoreCloseLight',
+ 'IcAppstoreDerivLogo',
+ 'IcAppstoreEllipse',
+ 'IcAppstoreError',
+ 'IcAppstoreHomeDark',
+ 'IcAppstoreHome',
+ 'IcAppstoreInformation',
+ 'IcAppstoreLinkWallet',
+ 'IcAppstoreLinkedWallets',
+ 'IcAppstoreMenuHomepage',
+ 'IcAppstoreMultipliersTradeType',
+ 'IcAppstoreOptionTradeType',
+ 'IcAppstoreSkeletonCardBorder',
+ 'IcAppstoreSuccess',
+ 'IcAppstoreTradingHubBeta',
+ 'IcAppstoreTradingHubOnboardingDark',
+ 'IcAppstoreTradingHubOnboarding',
+ 'IcAppstoreWalletAudLight',
+ 'IcAppstoreWalletBitcoinLight',
+ 'IcAppstoreWalletCardPlaceholderDarkRedLine',
+ 'IcAppstoreWalletCardPlaceholderDark',
+ 'IcAppstoreWalletCardPlaceholderLightRedLine',
+ 'IcAppstoreWalletCardPlaceholderLight',
+ 'IcAppstoreWalletCardXsBackground',
+ 'IcAppstoreWalletDefault',
+ 'IcAppstoreWalletDemo',
+ 'IcAppstoreWalletEthereumLight',
+ 'IcAppstoreWalletEurLight',
+ 'IcAppstoreWalletEusdtLight',
+ 'IcAppstoreWalletGbpLight',
+ 'IcAppstoreWalletLitecoinLight',
+ 'IcAppstoreWalletP2pLight',
+ 'IcAppstoreWalletPaLight',
+ 'IcAppstoreWalletSmall',
+ 'IcAppstoreWalletUsdLight',
+ 'IcAppstoreWalletUsdcLight',
+ 'IcAppstoreWalletUsdtLight',
+ 'IcAppstoreWarning',
+ ],
'brand': [
'IcBrandBinarybot',
'IcBrandDbot',
'IcBrandDerivApps',
'IcBrandDeriv',
+ 'IcBrandDerivgo',
'IcBrandDmt5FinancialStp',
'IcBrandDmt5Financial',
'IcBrandDmt5Synthetics',
@@ -885,4 +938,4 @@ export const icons =
'IcWalletZingpayDark',
'IcWalletZingpayLight',
],
-};
+}
diff --git a/packages/core/build/loaders-config.js b/packages/core/build/loaders-config.js
index 79da6ad5b24b..ccc4762464cc 100644
--- a/packages/core/build/loaders-config.js
+++ b/packages/core/build/loaders-config.js
@@ -5,6 +5,7 @@ const js_loaders = [
'@deriv/shared/src/loaders/react-import-loader.js',
'@deriv/shared/src/loaders/deriv-account-loader.js',
'@deriv/shared/src/loaders/deriv-cashier-loader.js',
+ '@deriv/shared/src/loaders/deriv-cfd-loader.js',
{
loader: 'babel-loader',
options: {
diff --git a/packages/core/globals.d.ts b/packages/core/globals.d.ts
new file mode 100644
index 000000000000..5a3a696213f0
--- /dev/null
+++ b/packages/core/globals.d.ts
@@ -0,0 +1,11 @@
+declare module '@deriv/account';
+declare module '@deriv/bot-skeleton';
+declare module '@deriv/bot-web-ui';
+declare module '@deriv/cashier';
+declare module '@deriv/cfd';
+declare module '@deriv/components';
+declare module '@deriv/appstore';
+declare module '@deriv/p2p';
+declare module '@deriv/translations';
+declare module '@deriv/shared';
+declare module '@deriv/trader';
diff --git a/packages/core/src/App/Components/Elements/LiveChat/use-livechat.ts b/packages/core/src/App/Components/Elements/LiveChat/use-livechat.ts
index 9c3d85cb4672..33b56e0b4e48 100644
--- a/packages/core/src/App/Components/Elements/LiveChat/use-livechat.ts
+++ b/packages/core/src/App/Components/Elements/LiveChat/use-livechat.ts
@@ -15,8 +15,8 @@ const useLiveChat = (has_cookie_account = false) => {
if (window.LiveChatWidget) {
window.LiveChatWidget.on('ready', () => {
try {
- if (window.LiveChatWidget.get('customer_data').status !== 'chatting') {
- window.LiveChatWidget.call('destroy');
+ if (window.LiveChatWidget?.get('customer_data').status !== 'chatting') {
+ window.LiveChatWidget?.call('destroy');
resolve();
}
} catch (e) {
@@ -70,29 +70,33 @@ const useLiveChat = (has_cookie_account = false) => {
utm_medium: utm_medium ?? ' ',
utm_campaign: utm_campaign ?? ' ',
};
- window.LiveChatWidget.call('set_session_variables', session_variables);
+ window.LiveChatWidget?.call('set_session_variables', session_variables);
if (is_logged_in) {
// client logged in
// prepfill name and email
- window.LiveChatWidget.call('set_customer_email', session_variables.email);
- window.LiveChatWidget.call('set_customer_name', `${client_first_name} ${client_last_name}`);
+ window.LiveChatWidget?.call('set_customer_email', session_variables.email);
+ window.LiveChatWidget?.call('set_customer_name', `${client_first_name} ${client_last_name}`);
// prefill name and email fields after chat has ended
- window.LC_API.on_chat_ended = () => {
- window.LiveChatWidget.call('set_customer_email', session_variables.email);
- window.LiveChatWidget.call('set_customer_name', `${client_first_name} ${client_last_name}`);
- };
+ if (window.LC_API?.on_chat_ended) {
+ window.LC_API.on_chat_ended = () => {
+ window.LiveChatWidget?.call('set_customer_email', session_variables.email);
+ window.LiveChatWidget?.call('set_customer_name', `${client_first_name} ${client_last_name}`);
+ };
+ }
} else {
// client not logged in
// clear name and email fields
- window.LiveChatWidget.call('set_customer_email', ' ');
- window.LiveChatWidget.call('set_customer_name', ' ');
+ window.LiveChatWidget?.call('set_customer_email', ' ');
+ window.LiveChatWidget?.call('set_customer_name', ' ');
// clear name and email fields after chat has ended
- window.LC_API.on_chat_ended = () => {
- window.LiveChatWidget.call('set_customer_email', ' ');
- window.LiveChatWidget.call('set_customer_name', ' ');
- };
+ if (window.LC_API?.on_chat_ended) {
+ window.LC_API.on_chat_ended = () => {
+ window.LiveChatWidget?.call('set_customer_email', ' ');
+ window.LiveChatWidget?.call('set_customer_name', ' ');
+ };
+ }
}
});
};
diff --git a/packages/core/src/App/Components/Layout/Footer/toggle-settings.jsx b/packages/core/src/App/Components/Layout/Footer/toggle-settings.jsx
index 13ff1b0ef20d..18eb27f0cbea 100644
--- a/packages/core/src/App/Components/Layout/Footer/toggle-settings.jsx
+++ b/packages/core/src/App/Components/Layout/Footer/toggle-settings.jsx
@@ -5,6 +5,7 @@ import Loadable from 'react-loadable';
import { Icon, Modal, Popover, VerticalTab, UILoader } from '@deriv/components';
import { localize } from '@deriv/translations';
import 'Sass/app/modules/settings.scss';
+import { PlatformContext } from '@deriv/shared';
const ThemeSetting = Loadable({
loader: () =>
@@ -23,20 +24,25 @@ const LanguageSettingContainer = Loadable({
});
const ModalContent = ({ settings_extension }) => {
- const content = [
- {
- icon: 'IcTheme',
- label: localize('Themes'),
- // eslint-disable-next-line react/display-name
- value: ThemeSetting,
- },
- {
- icon: 'IcLanguage',
- label: localize('Language'),
- value: LanguageSettingContainer,
- },
- ...(settings_extension || []),
- ];
+ const { is_pre_appstore } = React.useContext(PlatformContext);
+ const content = [];
+ if (is_pre_appstore) {
+ content.push(...(settings_extension || []));
+ } else {
+ content.push(
+ {
+ icon: 'IcTheme',
+ label: localize('Themes'),
+ value: ThemeSetting,
+ },
+ {
+ icon: 'IcLanguage',
+ label: localize('Language'),
+ value: LanguageSettingContainer,
+ },
+ ...(settings_extension || [])
+ );
+ }
return
;
};
diff --git a/packages/core/src/App/Components/Layout/Header/__tests__/platform-dropdown.spec.js b/packages/core/src/App/Components/Layout/Header/__tests__/platform-dropdown.spec.js
index 2f393b7baf95..9d9b02a1f559 100644
--- a/packages/core/src/App/Components/Layout/Header/__tests__/platform-dropdown.spec.js
+++ b/packages/core/src/App/Components/Layout/Header/__tests__/platform-dropdown.spec.js
@@ -29,8 +29,8 @@ describe('PlatformDropdown', () => {
expect(wrapper.find('.platform-dropdown__list-platform').exists()).to.be.false;
});
- it('should contain
if platform_config is not an empty array', () => {
- const wrapper = shallow(
);
- expect(wrapper.find('.platform-dropdown__list-platform').children().type()).to.equal(PlatformBox);
+ it('should not contain
if platform_config is an empty array', () => {
+ const wrapper = shallow(
);
+ expect(wrapper.find(PlatformBox)).to.have.length(0);
});
});
diff --git a/packages/core/src/App/Components/Layout/Header/menu-links.jsx b/packages/core/src/App/Components/Layout/Header/menu-links.jsx
index f7f8072c3c9b..22e1afe3c3bd 100644
--- a/packages/core/src/App/Components/Layout/Header/menu-links.jsx
+++ b/packages/core/src/App/Components/Layout/Header/menu-links.jsx
@@ -3,44 +3,43 @@ import React from 'react';
import { Text } from '@deriv/components';
import { BinaryLink } from '../../Routes';
-const MenuLinks = ({ is_logged_in, items }) => (
+const MenuItems = ({ item, hide_menu_item }) => {
+ const { id, link_to, href, text, image, logo, icon } = item;
+ return hide_menu_item ? null : (
+
+
+ {icon}
+ {text()}
+ {logo}
+
+
+ {image}
+ {logo}
+
+
+ );
+};
+
+const MenuLinks = ({ is_logged_in, items, is_pre_appstore }) => (
{!!items.length && (
- {items.map((item, idx) => {
- const item_text = item.text();
-
- return item.login_only && item.login_only !== is_logged_in ? null : (
-
-
- {item_text && (
-
- {item.icon}
- {item_text}
- {item.logo}
-
- )}
- {item.image && (
-
- {item.image}
- {item.logo}
-
- )}
-
-
+ {items.map(item => {
+ return (
+ is_logged_in && (
+
+ )
);
})}
@@ -60,6 +59,7 @@ MenuLinks.propTypes = {
})
),
is_logged_in: PropTypes.bool,
+ is_pre_appstore: PropTypes.bool,
};
export { MenuLinks };
diff --git a/packages/core/src/App/Components/Layout/Header/platform-dropdown.jsx b/packages/core/src/App/Components/Layout/Header/platform-dropdown.jsx
index de8cd4d01cda..88f517794c13 100644
--- a/packages/core/src/App/Components/Layout/Header/platform-dropdown.jsx
+++ b/packages/core/src/App/Components/Layout/Header/platform-dropdown.jsx
@@ -2,7 +2,7 @@ import PropTypes from 'prop-types';
import React from 'react';
import ReactDOM from 'react-dom';
import { Div100vhContainer, Icon, useOnClickOutside } from '@deriv/components';
-import { routes, isDesktop, isMobile, getActivePlatform } from '@deriv/shared';
+import { routes, isDesktop, isMobile, getActivePlatform, PlatformContext, getPlatformSettings } from '@deriv/shared';
import { BinaryLink } from 'App/Components/Routes';
import 'Sass/app/_common/components/platform-dropdown.scss';
@@ -19,6 +19,26 @@ const PlatformBox = ({ platform: { icon, title, description } }) => (
>
);
+const PlatformDropdownContent = ({ platform, app_routing_history, hide_dropdown_items }) => {
+ return !hide_dropdown_items
+ ? (platform.link_to && (
+ getActivePlatform(app_routing_history) === platform.name}
+ >
+
+
+ )) || (
+
+
+
+ )
+ : null;
+};
+
const PlatformDropdown = ({ app_routing_history, closeDrawer, platform_config }) => {
React.useEffect(() => {
window.addEventListener('popstate', closeDrawer);
@@ -35,31 +55,28 @@ const PlatformDropdown = ({ app_routing_history, closeDrawer, platform_config })
closeDrawer();
}
};
+ const { is_pre_appstore } = React.useContext(PlatformContext);
useOnClickOutside(ref, handleClickOutside, () => isDesktop());
const platform_dropdown = (
- {platform_config.map((platform, idx) => (
-
- {platform.link_to ? (
-
getActivePlatform(app_routing_history) === platform.name}
- >
-
-
- ) : (
-
-
-
- )}
-
- ))}
+ {platform_config.map(platform => {
+ const should_hide_dropdown_item =
+ (platform.name === getPlatformSettings('mt5').name ||
+ platform.name === getPlatformSettings('dxtrade').name) &&
+ is_pre_appstore;
+ return (
+
+ );
+ })}
);
diff --git a/packages/core/src/App/Components/Layout/Header/toggle-menu-drawer.jsx b/packages/core/src/App/Components/Layout/Header/toggle-menu-drawer.jsx
index 7e10e7744e68..f43aef9db770 100644
--- a/packages/core/src/App/Components/Layout/Header/toggle-menu-drawer.jsx
+++ b/packages/core/src/App/Components/Layout/Header/toggle-menu-drawer.jsx
@@ -1,7 +1,7 @@
import classNames from 'classnames';
import React from 'react';
-import { Div100vhContainer, Icon, MobileDrawer, ToggleSwitch, Text } from '@deriv/components';
-import { routes, PlatformContext, whatsapp_url } from '@deriv/shared';
+import { Div100vhContainer, Icon, MobileDrawer, ToggleSwitch, Text, Button } from '@deriv/components';
+import { routes, PlatformContext, getStaticUrl, whatsapp_url } from '@deriv/shared';
import { localize, getAllowedLanguages, getLanguage } from '@deriv/translations';
import NetworkStatus from 'App/Components/Layout/Footer';
import ServerTime from 'App/Containers/server-time.jsx';
@@ -9,6 +9,7 @@ import { BinaryLink } from 'App/Components/Routes';
import getRoutesConfig from 'App/Constants/routes-config';
import { changeLanguage } from 'Utils/Language';
import LiveChat from 'App/Components/Elements/LiveChat';
+import { useLocation, useHistory } from 'react-router-dom';
import useLiveChat from 'App/Components/Elements/LiveChat/use-livechat.ts';
const MenuLink = ({
@@ -22,6 +23,8 @@ const MenuLink = ({
text,
onClickLink,
}) => {
+ const deriv_static_url = getStaticUrl(link_to);
+
if (is_language) {
return (
}
);
+ } else if (deriv_static_url) {
+ return (
+