@oanda/labs-order-book-widget 1.0.71 → 1.0.72
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +276 -0
- package/dist/main/OrderBookWidget/ChartWithData.js +62 -0
- package/dist/main/OrderBookWidget/ChartWithData.js.map +1 -0
- package/dist/main/OrderBookWidget/Main.js +46 -0
- package/dist/main/OrderBookWidget/Main.js.map +1 -0
- package/dist/main/OrderBookWidget/OrderBookWidget.js +2 -2
- package/dist/main/OrderBookWidget/OrderBookWidget.js.map +1 -1
- package/dist/main/OrderBookWidget/components/Chart/Chart.js +16 -7
- package/dist/main/OrderBookWidget/components/Chart/Chart.js.map +1 -1
- package/dist/main/OrderBookWidget/components/Chart/constants.js +5 -3
- package/dist/main/OrderBookWidget/components/Chart/constants.js.map +1 -1
- package/dist/main/OrderBookWidget/components/Chart/formatters.js +10 -4
- package/dist/main/OrderBookWidget/components/Chart/formatters.js.map +1 -1
- package/dist/main/OrderBookWidget/components/Chart/getOption.js +81 -36
- package/dist/main/OrderBookWidget/components/Chart/getOption.js.map +1 -1
- package/dist/main/OrderBookWidget/components/Chart/types.js.map +1 -1
- package/dist/main/OrderBookWidget/config.js +69 -1
- package/dist/main/OrderBookWidget/config.js.map +1 -1
- package/dist/main/OrderBookWidget/types.js +20 -0
- package/dist/main/OrderBookWidget/types.js.map +1 -1
- package/dist/main/translations/sources/en.json +3 -0
- package/dist/main/translations/sources/zh_TW.json +3 -0
- package/dist/module/OrderBookWidget/ChartWithData.js +55 -0
- package/dist/module/OrderBookWidget/ChartWithData.js.map +1 -0
- package/dist/module/OrderBookWidget/Main.js +38 -0
- package/dist/module/OrderBookWidget/Main.js.map +1 -0
- package/dist/module/OrderBookWidget/OrderBookWidget.js +2 -2
- package/dist/module/OrderBookWidget/OrderBookWidget.js.map +1 -1
- package/dist/module/OrderBookWidget/components/Chart/Chart.js +17 -8
- package/dist/module/OrderBookWidget/components/Chart/Chart.js.map +1 -1
- package/dist/module/OrderBookWidget/components/Chart/constants.js +4 -2
- package/dist/module/OrderBookWidget/components/Chart/constants.js.map +1 -1
- package/dist/module/OrderBookWidget/components/Chart/formatters.js +10 -4
- package/dist/module/OrderBookWidget/components/Chart/formatters.js.map +1 -1
- package/dist/module/OrderBookWidget/components/Chart/getOption.js +80 -35
- package/dist/module/OrderBookWidget/components/Chart/getOption.js.map +1 -1
- package/dist/module/OrderBookWidget/components/Chart/types.js.map +1 -1
- package/dist/module/OrderBookWidget/config.js +69 -1
- package/dist/module/OrderBookWidget/config.js.map +1 -1
- package/dist/module/OrderBookWidget/types.js +19 -1
- package/dist/module/OrderBookWidget/types.js.map +1 -1
- package/dist/module/translations/sources/en.json +3 -0
- package/dist/module/translations/sources/zh_TW.json +3 -0
- package/dist/types/OrderBookWidget/ChartWithData.d.ts +4 -0
- package/dist/types/OrderBookWidget/Main.d.ts +4 -0
- package/dist/types/OrderBookWidget/components/Chart/Chart.d.ts +1 -1
- package/dist/types/OrderBookWidget/components/Chart/constants.d.ts +4 -2
- package/dist/types/OrderBookWidget/components/Chart/getOption.d.ts +16 -1
- package/dist/types/OrderBookWidget/components/Chart/types.d.ts +11 -1
- package/dist/types/OrderBookWidget/config.d.ts +7 -1
- package/dist/types/OrderBookWidget/types.d.ts +26 -3
- package/package.json +3 -3
- package/src/OrderBookWidget/ChartWithData.tsx +78 -0
- package/src/OrderBookWidget/Main.tsx +40 -0
- package/src/OrderBookWidget/OrderBookWidget.tsx +2 -2
- package/src/OrderBookWidget/components/Chart/Chart.tsx +12 -6
- package/src/OrderBookWidget/components/Chart/constants.ts +4 -2
- package/src/OrderBookWidget/components/Chart/formatters.ts +6 -4
- package/src/OrderBookWidget/components/Chart/getOption.ts +93 -39
- package/src/OrderBookWidget/components/Chart/types.ts +11 -3
- package/src/OrderBookWidget/config.ts +70 -1
- package/src/OrderBookWidget/types.ts +28 -3
- package/src/translations/sources/en.json +3 -0
- package/src/translations/sources/zh_TW.json +3 -0
- package/test/Main.test.tsx +129 -0
- package/test/chartOptions.test.ts +20 -0
- package/dist/main/OrderBookWidget/Widget.js +0 -61
- package/dist/main/OrderBookWidget/Widget.js.map +0 -1
- package/dist/module/OrderBookWidget/Widget.js +0 -53
- package/dist/module/OrderBookWidget/Widget.js.map +0 -1
- package/dist/types/OrderBookWidget/Widget.d.ts +0 -4
- package/src/OrderBookWidget/Widget.tsx +0 -62
- package/test/Widget.test.tsx +0 -71
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
export declare const INITIAL_BARS = 80;
|
|
2
2
|
export declare const X_LABEL_SIZE = 40;
|
|
3
|
-
export declare const Y_LABEL_SIZE_MOBILE =
|
|
3
|
+
export declare const Y_LABEL_SIZE_MOBILE = 50;
|
|
4
4
|
export declare const Y_LABEL_SIZE_DESKTOP = 120;
|
|
5
5
|
export declare const CHART_WIDTH = 9999;
|
|
6
|
-
export declare const
|
|
6
|
+
export declare const CHART_HEIGHT_DESKTOP = 450;
|
|
7
|
+
export declare const CHART_HEIGHT_MOBILE = 390;
|
|
8
|
+
export declare const ZOOM_CONTROL_HEIGHT = 40;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { GetOptionType, GetResponsiveOptionsProps } from './types';
|
|
2
|
-
export declare const
|
|
2
|
+
export declare const getResponsiveOption: ({ isDark, isOrderBook, isDesktop, lang, }: GetResponsiveOptionsProps) => {
|
|
3
3
|
grid: {
|
|
4
4
|
name: string;
|
|
5
5
|
top: string;
|
|
@@ -7,6 +7,21 @@ export declare const getDesktopOption: ({ isDark, isOrderBook }: GetResponsiveOp
|
|
|
7
7
|
right: string;
|
|
8
8
|
bottom: string;
|
|
9
9
|
}[];
|
|
10
|
+
yAxis: {
|
|
11
|
+
axisLabel: {
|
|
12
|
+
margin: number;
|
|
13
|
+
};
|
|
14
|
+
};
|
|
15
|
+
series: {
|
|
16
|
+
type: string;
|
|
17
|
+
name: string;
|
|
18
|
+
id: string;
|
|
19
|
+
markLine: {
|
|
20
|
+
label: {
|
|
21
|
+
padding: number[];
|
|
22
|
+
};
|
|
23
|
+
};
|
|
24
|
+
}[];
|
|
10
25
|
graphic: ({
|
|
11
26
|
top: number | undefined;
|
|
12
27
|
bottom: number | undefined;
|
|
@@ -3,16 +3,26 @@ import { GetOrderPositionBooksQuery } from '../../../gql/types/graphql';
|
|
|
3
3
|
export interface ChartProps {
|
|
4
4
|
data: GetOrderPositionBooksQuery;
|
|
5
5
|
isOrderBook: boolean;
|
|
6
|
+
precision: number;
|
|
6
7
|
}
|
|
7
8
|
export interface GetResponsiveOptionsProps {
|
|
9
|
+
isDesktop: boolean;
|
|
8
10
|
isDark: boolean;
|
|
9
11
|
isOrderBook: boolean;
|
|
12
|
+
lang: (label: string) => string;
|
|
10
13
|
}
|
|
11
14
|
export interface GetOptionProps {
|
|
12
15
|
data: GetOrderPositionBooksQuery;
|
|
13
16
|
precision: number;
|
|
14
17
|
isDark: boolean;
|
|
15
18
|
isOrderBook: boolean;
|
|
19
|
+
isDesktop: boolean;
|
|
20
|
+
lang: (label: string) => string;
|
|
16
21
|
}
|
|
17
22
|
export type GetOptionType = (props: GetOptionProps) => EChartsOption;
|
|
18
|
-
export type TooltipFormatterType = (
|
|
23
|
+
export type TooltipFormatterType = (props: {
|
|
24
|
+
data: number[];
|
|
25
|
+
precision: number;
|
|
26
|
+
isOrderBook: boolean;
|
|
27
|
+
lang: (label: string) => string;
|
|
28
|
+
}) => string;
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import { BookType } from '../gql/types/graphql';
|
|
2
|
+
import { InstrumentId } from './types';
|
|
2
3
|
declare const navigationConfig: {
|
|
3
4
|
id: BookType;
|
|
4
5
|
label: string;
|
|
5
6
|
}[];
|
|
6
|
-
|
|
7
|
+
declare const instrumentSelectConfig: {
|
|
8
|
+
id: InstrumentId;
|
|
9
|
+
label: string;
|
|
10
|
+
}[];
|
|
11
|
+
declare const instrumentPrecisionConfig: Record<InstrumentId, number>;
|
|
12
|
+
export { navigationConfig, instrumentSelectConfig, instrumentPrecisionConfig };
|
|
@@ -1,14 +1,37 @@
|
|
|
1
1
|
import { Theme } from '@oanda/labs-widget-common';
|
|
2
2
|
import { Locale } from '@oanda/mono-i18n';
|
|
3
|
+
import { BookType } from '../gql/types/graphql';
|
|
3
4
|
export interface OrderBookWidgetConfig {
|
|
4
5
|
graphqlUrl: string;
|
|
5
|
-
instrument:
|
|
6
|
+
instrument: InstrumentId;
|
|
6
7
|
locale: Locale;
|
|
7
8
|
theme?: Theme;
|
|
8
9
|
}
|
|
9
10
|
export interface OrderBookWrapperConfig extends OrderBookWidgetConfig {
|
|
10
11
|
renderElementId: string;
|
|
11
12
|
}
|
|
12
|
-
export interface
|
|
13
|
-
instrument
|
|
13
|
+
export interface MainProps {
|
|
14
|
+
instrument?: InstrumentId;
|
|
15
|
+
}
|
|
16
|
+
export interface ChartWithDataProps {
|
|
17
|
+
instrument: InstrumentId;
|
|
18
|
+
bookType: BookType;
|
|
19
|
+
}
|
|
20
|
+
export declare enum InstrumentId {
|
|
21
|
+
EUR_AUD = "EUR_AUD",
|
|
22
|
+
EUR_GBP = "EUR_GBP",
|
|
23
|
+
EUR_JPY = "EUR_JPY",
|
|
24
|
+
EUR_USD = "EUR_USD",
|
|
25
|
+
EUR_CHF = "EUR_CHF",
|
|
26
|
+
USD_CHF = "USD_CHF",
|
|
27
|
+
USD_JPY = "USD_JPY",
|
|
28
|
+
USD_CAD = "USD_CAD",
|
|
29
|
+
GBP_USD = "GBP_USD",
|
|
30
|
+
GBP_JPY = "GBP_JPY",
|
|
31
|
+
GBP_CHF = "GBP_CHF",
|
|
32
|
+
AUD_JPY = "AUD_JPY",
|
|
33
|
+
AUD_USD = "AUD_USD",
|
|
34
|
+
NZD_USD = "NZD_USD",
|
|
35
|
+
XAU_USD = "XAU_USD",
|
|
36
|
+
XAG_USD = "XAG_USD"
|
|
14
37
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oanda/labs-order-book-widget",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.72",
|
|
4
4
|
"description": "Labs Order Book Widget",
|
|
5
5
|
"main": "dist/main/index.js",
|
|
6
6
|
"module": "dist/module/index.js",
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"license": "UNLICENSED",
|
|
14
14
|
"dependencies": {
|
|
15
15
|
"@apollo/client": "3.7.17",
|
|
16
|
-
"@oanda/labs-widget-common": "^1.0.
|
|
16
|
+
"@oanda/labs-widget-common": "^1.0.72",
|
|
17
17
|
"@oanda/mono-i18n": "9.0.0",
|
|
18
18
|
"classnames": "2.3.2",
|
|
19
19
|
"echarts": "5.4.3",
|
|
@@ -25,5 +25,5 @@
|
|
|
25
25
|
"@graphql-codegen/client-preset": "4.1.0",
|
|
26
26
|
"@graphql-codegen/typescript": "4.0.1"
|
|
27
27
|
},
|
|
28
|
-
"gitHead": "
|
|
28
|
+
"gitHead": "4a224fac68b6b607825b7ac6802ea0b5c499996e"
|
|
29
29
|
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { useQuery } from '@apollo/client';
|
|
3
|
+
import { useMediaQuery } from 'usehooks-ts';
|
|
4
|
+
import classnames from 'classnames';
|
|
5
|
+
import { ChartError, Spinner, SpinnerSize } from '@oanda/labs-widget-common';
|
|
6
|
+
import { ChartWithDataProps } from './types';
|
|
7
|
+
import { getOrderPositionBooks } from '../gql/getOrderPositionBooks';
|
|
8
|
+
import { GetOrderPositionBooksQuery, GetOrderPositionBooksQueryVariables, BookType } from '../gql/types/graphql';
|
|
9
|
+
import { Chart } from './components/Chart/Chart';
|
|
10
|
+
import { instrumentPrecisionConfig } from './config';
|
|
11
|
+
|
|
12
|
+
const ChartWithData = ({
|
|
13
|
+
instrument,
|
|
14
|
+
bookType,
|
|
15
|
+
}: ChartWithDataProps) => {
|
|
16
|
+
const isDesktop = useMediaQuery('(min-width: 768px)');
|
|
17
|
+
|
|
18
|
+
const { loading, data, error } = useQuery<
|
|
19
|
+
GetOrderPositionBooksQuery,
|
|
20
|
+
GetOrderPositionBooksQueryVariables
|
|
21
|
+
>(getOrderPositionBooks, {
|
|
22
|
+
variables: {
|
|
23
|
+
instrument,
|
|
24
|
+
bookType,
|
|
25
|
+
recentHours: 1,
|
|
26
|
+
},
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
const isError = (!loading && !data?.orderPositionBooks[0]?.price) || !!error;
|
|
30
|
+
|
|
31
|
+
return (
|
|
32
|
+
<div className={classnames('lw-relative lw-w-full', {
|
|
33
|
+
'lw-h-[450px]': isDesktop,
|
|
34
|
+
'lw-h-[390px]': !isDesktop,
|
|
35
|
+
})}
|
|
36
|
+
>
|
|
37
|
+
{isError && (
|
|
38
|
+
<div className={
|
|
39
|
+
classnames(
|
|
40
|
+
'lw-absolute lw-left-0 lw-top-0 lw-flex lw-w-full lw-items-center lw-justify-center lw-border lw-border-solid lw-border-border-primary',
|
|
41
|
+
{
|
|
42
|
+
'lw-h-full': isDesktop,
|
|
43
|
+
'lw-h-[calc(100%-40px)]': !isDesktop,
|
|
44
|
+
},
|
|
45
|
+
)
|
|
46
|
+
}
|
|
47
|
+
>
|
|
48
|
+
<ChartError />
|
|
49
|
+
</div>
|
|
50
|
+
)}
|
|
51
|
+
{loading && (
|
|
52
|
+
<div className={
|
|
53
|
+
classnames(
|
|
54
|
+
'lw-absolute lw-left-0 lw-top-0 lw-flex lw-w-full lw-items-center lw-justify-center lw-border lw-border-solid lw-border-border-primary',
|
|
55
|
+
{
|
|
56
|
+
'lw-h-full': isDesktop,
|
|
57
|
+
'lw-h-[calc(100%-40px)]': !isDesktop,
|
|
58
|
+
},
|
|
59
|
+
)
|
|
60
|
+
}
|
|
61
|
+
>
|
|
62
|
+
<Spinner size={SpinnerSize.lg} />
|
|
63
|
+
</div>
|
|
64
|
+
)}
|
|
65
|
+
{data && (
|
|
66
|
+
<div className="lw-absolute lw-left-0 lw-top-0 lw-flex lw-h-full lw-w-full">
|
|
67
|
+
<Chart
|
|
68
|
+
data={data}
|
|
69
|
+
isOrderBook={bookType === BookType.Order}
|
|
70
|
+
precision={instrumentPrecisionConfig[instrument]}
|
|
71
|
+
/>
|
|
72
|
+
</div>
|
|
73
|
+
)}
|
|
74
|
+
</div>
|
|
75
|
+
);
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
export { ChartWithData };
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import React, { useState } from 'react';
|
|
2
|
+
import { Select, Tabs } from '@oanda/labs-widget-common';
|
|
3
|
+
import { useLocale } from '@oanda/mono-i18n';
|
|
4
|
+
import { InstrumentId, MainProps } from './types';
|
|
5
|
+
import { BookType } from '../gql/types/graphql';
|
|
6
|
+
import { instrumentSelectConfig, navigationConfig } from './config';
|
|
7
|
+
import { ChartWithData } from './ChartWithData';
|
|
8
|
+
|
|
9
|
+
const Main = ({ instrument }: MainProps) => {
|
|
10
|
+
const [bookType, setBookType] = useState(BookType.Order);
|
|
11
|
+
const [toolInstrument, setToolInstrument] = useState(instrumentSelectConfig[0]);
|
|
12
|
+
const { lang } = useLocale();
|
|
13
|
+
|
|
14
|
+
return (
|
|
15
|
+
<div data-testid="order-book-widget" className="lw-p-4 lw-pt-0 lw-text-sm lw-tracking-normal lw-text-black">
|
|
16
|
+
<Tabs
|
|
17
|
+
activeTab={bookType}
|
|
18
|
+
handleClick={(e) => setBookType(e.currentTarget.value as BookType)}
|
|
19
|
+
labelCallback={lang}
|
|
20
|
+
items={navigationConfig}
|
|
21
|
+
mobileFullWidth
|
|
22
|
+
/>
|
|
23
|
+
{!instrument && (
|
|
24
|
+
<div className="lw-mb-6 lw-mt-12">
|
|
25
|
+
<Select
|
|
26
|
+
selectLabel={lang('select_instrument')}
|
|
27
|
+
options={instrumentSelectConfig}
|
|
28
|
+
selectedOption={toolInstrument}
|
|
29
|
+
setSelectedOption={
|
|
30
|
+
(val) => setToolInstrument(val as { id: InstrumentId; label: string })
|
|
31
|
+
}
|
|
32
|
+
/>
|
|
33
|
+
</div>
|
|
34
|
+
)}
|
|
35
|
+
<ChartWithData instrument={instrument || toolInstrument.id} bookType={bookType} />
|
|
36
|
+
</div>
|
|
37
|
+
);
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export { Main };
|
|
@@ -2,7 +2,7 @@ import React from 'react';
|
|
|
2
2
|
import { ApolloClient, InMemoryCache, ApolloProvider } from '@apollo/client';
|
|
3
3
|
import { LocaleProvider } from '@oanda/mono-i18n';
|
|
4
4
|
import { ThemeProvider, getLocale } from '@oanda/labs-widget-common';
|
|
5
|
-
import {
|
|
5
|
+
import { Main } from './Main';
|
|
6
6
|
import { OrderBookWidgetConfig } from './types';
|
|
7
7
|
import { translations } from '../translations';
|
|
8
8
|
|
|
@@ -21,7 +21,7 @@ const OrderBookWidget = ({
|
|
|
21
21
|
<ThemeProvider theme={theme}>
|
|
22
22
|
<LocaleProvider locale={getLocale(locale)} translations={translations}>
|
|
23
23
|
<ApolloProvider client={client}>
|
|
24
|
-
<
|
|
24
|
+
<Main instrument={instrument} />
|
|
25
25
|
</ApolloProvider>
|
|
26
26
|
</LocaleProvider>
|
|
27
27
|
</ThemeProvider>
|
|
@@ -5,13 +5,15 @@ import {
|
|
|
5
5
|
Theme, ThemeContext, colorPalette, getChartTheme,
|
|
6
6
|
} from '@oanda/labs-widget-common';
|
|
7
7
|
import { useMediaQuery } from 'usehooks-ts';
|
|
8
|
-
import {
|
|
8
|
+
import { useLocale } from '@oanda/mono-i18n';
|
|
9
|
+
import { getResponsiveOption, getOption } from './getOption';
|
|
9
10
|
import { ChartProps } from './types';
|
|
10
11
|
|
|
11
12
|
registerTheme('dark_theme', getChartTheme(Theme.Dark));
|
|
12
13
|
registerTheme('light_theme', getChartTheme(Theme.Light));
|
|
13
14
|
|
|
14
|
-
export const Chart = ({ data, isOrderBook }: ChartProps) => {
|
|
15
|
+
export const Chart = ({ data, isOrderBook, precision }: ChartProps) => {
|
|
16
|
+
const { lang } = useLocale();
|
|
15
17
|
const isDark = useContext(ThemeContext) === Theme.Dark;
|
|
16
18
|
const echartRef = useRef(null);
|
|
17
19
|
const isDesktop = useMediaQuery('(min-width: 768px)');
|
|
@@ -48,9 +50,13 @@ export const Chart = ({ data, isOrderBook }: ChartProps) => {
|
|
|
48
50
|
// @ts-ignore
|
|
49
51
|
const echartInstance = echartRef.current.getEchartsInstance() as EChartsType;
|
|
50
52
|
|
|
51
|
-
echartInstance.setOption(
|
|
53
|
+
echartInstance.setOption(
|
|
54
|
+
getResponsiveOption({
|
|
55
|
+
isDark, isOrderBook, isDesktop, lang,
|
|
56
|
+
}),
|
|
57
|
+
);
|
|
52
58
|
}
|
|
53
|
-
}, [echartRef, isDesktop, isDark, isOrderBook]);
|
|
59
|
+
}, [echartRef, isDesktop, isDark, isOrderBook, lang]);
|
|
54
60
|
|
|
55
61
|
return (
|
|
56
62
|
<div className="lw-relative lw-w-full">
|
|
@@ -60,11 +66,11 @@ export const Chart = ({ data, isOrderBook }: ChartProps) => {
|
|
|
60
66
|
ref={echartRef}
|
|
61
67
|
theme={isDark ? 'dark_theme' : 'light_theme'}
|
|
62
68
|
style={{
|
|
63
|
-
height: '450px',
|
|
69
|
+
height: isDesktop ? '450px' : '390px',
|
|
64
70
|
width: '100%',
|
|
65
71
|
}}
|
|
66
72
|
option={getOption({
|
|
67
|
-
data, precision
|
|
73
|
+
data, precision, isDark, isOrderBook, isDesktop, lang,
|
|
68
74
|
})}
|
|
69
75
|
/>
|
|
70
76
|
)}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
export const INITIAL_BARS = 80;
|
|
2
2
|
|
|
3
3
|
export const X_LABEL_SIZE = 40;
|
|
4
|
-
export const Y_LABEL_SIZE_MOBILE =
|
|
4
|
+
export const Y_LABEL_SIZE_MOBILE = 50;
|
|
5
5
|
export const Y_LABEL_SIZE_DESKTOP = 120;
|
|
6
6
|
export const CHART_WIDTH = 9999;
|
|
7
|
-
export const
|
|
7
|
+
export const CHART_HEIGHT_DESKTOP = 450;
|
|
8
|
+
export const CHART_HEIGHT_MOBILE = 390;
|
|
9
|
+
export const ZOOM_CONTROL_HEIGHT = 40;
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { TooltipFormatterType } from './types';
|
|
2
2
|
|
|
3
|
-
const tooltipFormatter: TooltipFormatterType = (
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
const
|
|
3
|
+
const tooltipFormatter: TooltipFormatterType = ({
|
|
4
|
+
data, precision, isOrderBook, lang,
|
|
5
|
+
}) => {
|
|
6
|
+
const priceText = `${lang('price')}: ${data[0].toFixed(precision)}`;
|
|
7
|
+
const buyText = data[1] ? `<br />${lang(isOrderBook ? 'buy' : 'long_positions')}: ${data[1]}%` : '';
|
|
8
|
+
const sellText = data[2] ? `<br />${lang(isOrderBook ? 'sell' : 'short_positions')}: ${data[2] * -1}%` : '';
|
|
7
9
|
|
|
8
10
|
return priceText + buyText + sellText;
|
|
9
11
|
};
|
|
@@ -1,17 +1,31 @@
|
|
|
1
1
|
import { colorPalette, getGridLines, getZoomControls } from '@oanda/labs-widget-common';
|
|
2
2
|
import {
|
|
3
|
-
INITIAL_BARS,
|
|
3
|
+
INITIAL_BARS,
|
|
4
|
+
CHART_WIDTH,
|
|
5
|
+
CHART_HEIGHT_DESKTOP,
|
|
6
|
+
CHART_HEIGHT_MOBILE,
|
|
7
|
+
X_LABEL_SIZE,
|
|
8
|
+
Y_LABEL_SIZE_DESKTOP,
|
|
9
|
+
Y_LABEL_SIZE_MOBILE,
|
|
10
|
+
ZOOM_CONTROL_HEIGHT,
|
|
4
11
|
} from './constants';
|
|
5
12
|
import { GetOptionType, GetResponsiveOptionsProps } from './types';
|
|
6
13
|
import { tooltipFormatter } from './formatters';
|
|
7
14
|
|
|
8
|
-
export const
|
|
15
|
+
export const getResponsiveOption = (
|
|
16
|
+
{
|
|
17
|
+
isDark, isOrderBook, isDesktop, lang,
|
|
18
|
+
}
|
|
19
|
+
: GetResponsiveOptionsProps,
|
|
20
|
+
) => {
|
|
9
21
|
const desktopGridLines = getGridLines({
|
|
10
22
|
isDark,
|
|
11
23
|
chartWidth: CHART_WIDTH,
|
|
12
|
-
chartHeight:
|
|
13
|
-
xLabelsSize: X_LABEL_SIZE,
|
|
14
|
-
yLabelSize: Y_LABEL_SIZE_DESKTOP,
|
|
24
|
+
chartHeight: isDesktop ? CHART_HEIGHT_DESKTOP : CHART_HEIGHT_MOBILE,
|
|
25
|
+
xLabelsSize: isDesktop ? X_LABEL_SIZE : X_LABEL_SIZE + ZOOM_CONTROL_HEIGHT,
|
|
26
|
+
yLabelSize: isDesktop ? Y_LABEL_SIZE_DESKTOP : Y_LABEL_SIZE_MOBILE,
|
|
27
|
+
bottomLeftBox: isDesktop,
|
|
28
|
+
marginBottom: isDesktop ? 0 : ZOOM_CONTROL_HEIGHT,
|
|
15
29
|
});
|
|
16
30
|
|
|
17
31
|
return {
|
|
@@ -20,8 +34,25 @@ export const getDesktopOption = ({ isDark, isOrderBook }: GetResponsiveOptionsPr
|
|
|
20
34
|
name: 'main-grid',
|
|
21
35
|
top: '48px',
|
|
22
36
|
left: '0px',
|
|
23
|
-
right: `${Y_LABEL_SIZE_DESKTOP}px`,
|
|
24
|
-
bottom: `${X_LABEL_SIZE}px`,
|
|
37
|
+
right: `${isDesktop ? Y_LABEL_SIZE_DESKTOP : Y_LABEL_SIZE_MOBILE}px`,
|
|
38
|
+
bottom: `${isDesktop ? X_LABEL_SIZE : X_LABEL_SIZE + ZOOM_CONTROL_HEIGHT}px`,
|
|
39
|
+
},
|
|
40
|
+
],
|
|
41
|
+
yAxis: {
|
|
42
|
+
axisLabel: {
|
|
43
|
+
margin: isDesktop ? 10 : 0,
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
series: [
|
|
47
|
+
{
|
|
48
|
+
type: 'custom',
|
|
49
|
+
name: 'current-price',
|
|
50
|
+
id: 'current-price',
|
|
51
|
+
markLine: {
|
|
52
|
+
label: {
|
|
53
|
+
padding: isDesktop ? [5, 15, 5, 15] : [5, 12, 5, 5],
|
|
54
|
+
},
|
|
55
|
+
},
|
|
25
56
|
},
|
|
26
57
|
],
|
|
27
58
|
graphic: [
|
|
@@ -58,14 +89,14 @@ export const getDesktopOption = ({ isDark, isOrderBook }: GetResponsiveOptionsPr
|
|
|
58
89
|
fill: isDark ? colorPalette.white : colorPalette.black,
|
|
59
90
|
width: 70,
|
|
60
91
|
height: 30,
|
|
61
|
-
text: isOrderBook ? '
|
|
92
|
+
text: lang(isOrderBook ? 'sell' : 'short'),
|
|
62
93
|
},
|
|
63
94
|
},
|
|
64
95
|
],
|
|
65
96
|
},
|
|
66
97
|
{
|
|
67
98
|
type: 'group',
|
|
68
|
-
right: '
|
|
99
|
+
right: `${(isDesktop ? Y_LABEL_SIZE_DESKTOP : Y_LABEL_SIZE_MOBILE) + 8}px'`,
|
|
69
100
|
top: '56px',
|
|
70
101
|
silent: true,
|
|
71
102
|
children: [
|
|
@@ -95,7 +126,7 @@ export const getDesktopOption = ({ isDark, isOrderBook }: GetResponsiveOptionsPr
|
|
|
95
126
|
fill: isDark ? colorPalette.white : colorPalette.black,
|
|
96
127
|
width: 70,
|
|
97
128
|
height: 30,
|
|
98
|
-
text: isOrderBook ? '
|
|
129
|
+
text: lang(isOrderBook ? 'buy' : 'long'),
|
|
99
130
|
},
|
|
100
131
|
},
|
|
101
132
|
],
|
|
@@ -105,11 +136,12 @@ export const getDesktopOption = ({ isDark, isOrderBook }: GetResponsiveOptionsPr
|
|
|
105
136
|
};
|
|
106
137
|
|
|
107
138
|
export const getOption: GetOptionType = ({
|
|
108
|
-
data, precision, isDark, isOrderBook,
|
|
139
|
+
data, precision, isDark, isOrderBook, isDesktop, lang,
|
|
109
140
|
}) => {
|
|
110
141
|
const buckets = data.orderPositionBooks[0]?.buckets || [];
|
|
111
142
|
const bucketWidth = data.orderPositionBooks[0]?.bucketWidth!;
|
|
112
143
|
const price = data.orderPositionBooks[0]?.price!;
|
|
144
|
+
const bucketPrecision = bucketWidth.toString().split('.')[1].length || 0;
|
|
113
145
|
|
|
114
146
|
const dataset = buckets.map((item) => ([
|
|
115
147
|
item!.price,
|
|
@@ -133,7 +165,7 @@ export const getOption: GetOptionType = ({
|
|
|
133
165
|
isDark ? colorPalette.orange : colorPalette.raspberryDark,
|
|
134
166
|
],
|
|
135
167
|
title: {
|
|
136
|
-
text: isOrderBook ? '
|
|
168
|
+
text: lang(isOrderBook ? 'open_orders' : 'open_positions').toUpperCase(),
|
|
137
169
|
padding: 20,
|
|
138
170
|
textStyle: {
|
|
139
171
|
fontSize: 14,
|
|
@@ -161,12 +193,23 @@ export const getOption: GetOptionType = ({
|
|
|
161
193
|
axisPointer: {
|
|
162
194
|
axis: 'y',
|
|
163
195
|
},
|
|
164
|
-
formatter: (val) => tooltipFormatter(
|
|
165
|
-
(val as { data: number[] }[])[0].data,
|
|
166
|
-
precision,
|
|
196
|
+
formatter: (val) => tooltipFormatter({
|
|
197
|
+
data: (val as { data: number[] }[])[0].data,
|
|
198
|
+
precision: bucketPrecision,
|
|
167
199
|
isOrderBook,
|
|
168
|
-
|
|
200
|
+
lang,
|
|
201
|
+
}),
|
|
202
|
+
extraCssText: 'z-index: 1',
|
|
169
203
|
},
|
|
204
|
+
grid: [
|
|
205
|
+
{
|
|
206
|
+
name: 'main-grid',
|
|
207
|
+
top: '48px',
|
|
208
|
+
left: '0px',
|
|
209
|
+
right: `${isDesktop ? Y_LABEL_SIZE_DESKTOP : Y_LABEL_SIZE_MOBILE}px`,
|
|
210
|
+
bottom: `${isDesktop ? X_LABEL_SIZE : X_LABEL_SIZE + ZOOM_CONTROL_HEIGHT}px`,
|
|
211
|
+
},
|
|
212
|
+
],
|
|
170
213
|
xAxis: {
|
|
171
214
|
type: 'value',
|
|
172
215
|
min: range * -1.05,
|
|
@@ -186,10 +229,11 @@ export const getOption: GetOptionType = ({
|
|
|
186
229
|
axisLine: { show: false },
|
|
187
230
|
axisTick: { show: false },
|
|
188
231
|
axisLabel: {
|
|
232
|
+
margin: isDesktop ? 10 : 0,
|
|
189
233
|
showMaxLabel: false,
|
|
190
234
|
showMinLabel: false,
|
|
191
235
|
padding: [0, 0, 0, 10],
|
|
192
|
-
formatter: (value) => value.toFixed(
|
|
236
|
+
formatter: (value) => value.toFixed(bucketPrecision),
|
|
193
237
|
},
|
|
194
238
|
},
|
|
195
239
|
dataset: {
|
|
@@ -198,6 +242,8 @@ export const getOption: GetOptionType = ({
|
|
|
198
242
|
series: [
|
|
199
243
|
{
|
|
200
244
|
type: 'custom',
|
|
245
|
+
name: 'sell-short',
|
|
246
|
+
id: 'sell-short',
|
|
201
247
|
clip: true,
|
|
202
248
|
encode: {
|
|
203
249
|
x: 1,
|
|
@@ -234,34 +280,14 @@ export const getOption: GetOptionType = ({
|
|
|
234
280
|
},
|
|
235
281
|
{
|
|
236
282
|
type: 'custom',
|
|
283
|
+
name: 'buy-long',
|
|
284
|
+
id: 'buy-long',
|
|
237
285
|
clip: true,
|
|
238
286
|
encode: {
|
|
239
287
|
x: 1,
|
|
240
288
|
y: 0,
|
|
241
289
|
tooltip: 2,
|
|
242
290
|
},
|
|
243
|
-
markLine: {
|
|
244
|
-
animation: false,
|
|
245
|
-
silent: true,
|
|
246
|
-
precision: 4,
|
|
247
|
-
symbol: ['none', 'triangle'],
|
|
248
|
-
symbolRotate: 90,
|
|
249
|
-
symbolSize: [20, 10],
|
|
250
|
-
lineStyle: {
|
|
251
|
-
color: isDark ? colorPalette.orange : colorPalette.bottleGreenDark,
|
|
252
|
-
width: 1,
|
|
253
|
-
},
|
|
254
|
-
label: {
|
|
255
|
-
padding: [5, 15, 5, 15],
|
|
256
|
-
color: isDark ? colorPalette.black : colorPalette.white,
|
|
257
|
-
backgroundColor: isDark ? colorPalette.orange : colorPalette.bottleGreenDark,
|
|
258
|
-
},
|
|
259
|
-
data: [
|
|
260
|
-
{
|
|
261
|
-
yAxis: price,
|
|
262
|
-
},
|
|
263
|
-
],
|
|
264
|
-
},
|
|
265
291
|
renderItem: (params, api) => {
|
|
266
292
|
const yValue = api.value(0);
|
|
267
293
|
const xStart = api.coord([api.value(2), yValue]);
|
|
@@ -290,6 +316,34 @@ export const getOption: GetOptionType = ({
|
|
|
290
316
|
};
|
|
291
317
|
},
|
|
292
318
|
},
|
|
319
|
+
{
|
|
320
|
+
type: 'custom',
|
|
321
|
+
name: 'current-price',
|
|
322
|
+
id: 'current-price',
|
|
323
|
+
markLine: {
|
|
324
|
+
animation: false,
|
|
325
|
+
silent: true,
|
|
326
|
+
precision,
|
|
327
|
+
symbol: ['none', 'triangle'],
|
|
328
|
+
symbolRotate: 90,
|
|
329
|
+
symbolSize: [20, 10],
|
|
330
|
+
lineStyle: {
|
|
331
|
+
color: isDark ? colorPalette.orange : colorPalette.bottleGreenDark,
|
|
332
|
+
width: 1,
|
|
333
|
+
},
|
|
334
|
+
label: {
|
|
335
|
+
padding: isDesktop ? [5, 15, 5, 15] : [5, 12, 5, 5],
|
|
336
|
+
color: isDark ? colorPalette.black : colorPalette.white,
|
|
337
|
+
backgroundColor: isDark ? colorPalette.orange : colorPalette.bottleGreenDark,
|
|
338
|
+
},
|
|
339
|
+
data: [
|
|
340
|
+
{
|
|
341
|
+
yAxis: price,
|
|
342
|
+
},
|
|
343
|
+
],
|
|
344
|
+
},
|
|
345
|
+
renderItem: () => null,
|
|
346
|
+
},
|
|
293
347
|
],
|
|
294
348
|
}
|
|
295
349
|
);
|
|
@@ -4,11 +4,14 @@ import { GetOrderPositionBooksQuery } from '../../../gql/types/graphql';
|
|
|
4
4
|
export interface ChartProps {
|
|
5
5
|
data: GetOrderPositionBooksQuery;
|
|
6
6
|
isOrderBook: boolean;
|
|
7
|
+
precision: number;
|
|
7
8
|
}
|
|
8
9
|
|
|
9
10
|
export interface GetResponsiveOptionsProps {
|
|
11
|
+
isDesktop: boolean;
|
|
10
12
|
isDark: boolean;
|
|
11
13
|
isOrderBook: boolean;
|
|
14
|
+
lang: (label: string) => string;
|
|
12
15
|
}
|
|
13
16
|
|
|
14
17
|
export interface GetOptionProps {
|
|
@@ -16,6 +19,8 @@ export interface GetOptionProps {
|
|
|
16
19
|
precision: number;
|
|
17
20
|
isDark: boolean;
|
|
18
21
|
isOrderBook: boolean;
|
|
22
|
+
isDesktop: boolean;
|
|
23
|
+
lang: (label: string) => string;
|
|
19
24
|
}
|
|
20
25
|
|
|
21
26
|
export type GetOptionType = (
|
|
@@ -23,7 +28,10 @@ export type GetOptionType = (
|
|
|
23
28
|
) => EChartsOption;
|
|
24
29
|
|
|
25
30
|
export type TooltipFormatterType = (
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
31
|
+
props : {
|
|
32
|
+
data: number[],
|
|
33
|
+
precision: number,
|
|
34
|
+
isOrderBook: boolean,
|
|
35
|
+
lang: (label: string) => string;
|
|
36
|
+
}
|
|
29
37
|
) => string;
|