@oanda/labs-widget-common 1.0.224 → 1.0.226

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.
Files changed (41) hide show
  1. package/CHANGELOG.md +1780 -0
  2. package/dist/main/components/TableWidget/ColumnRenderer.js +7 -1
  3. package/dist/main/components/TableWidget/ColumnRenderer.js.map +1 -1
  4. package/dist/main/hooks/useLiveRatesQuery.js.map +1 -1
  5. package/dist/main/hooks/useVisibleLiveDataRecord.js +2 -1
  6. package/dist/main/hooks/useVisibleLiveDataRecord.js.map +1 -1
  7. package/dist/main/providers/LiveRates/LiveRatesProvider.js +25 -2
  8. package/dist/main/providers/LiveRates/LiveRatesProvider.js.map +1 -1
  9. package/dist/main/providers/Widget/WidgetProvider.js +3 -1
  10. package/dist/main/providers/Widget/WidgetProvider.js.map +1 -1
  11. package/dist/main/types/dataTypes.js +1 -0
  12. package/dist/main/types/dataTypes.js.map +1 -1
  13. package/dist/main/types/liveRatesTypes.js.map +1 -1
  14. package/dist/main/utils/liveRates/buildUrl.js +1 -1
  15. package/dist/main/utils/liveRates/buildUrl.js.map +1 -1
  16. package/dist/module/components/TableWidget/ColumnRenderer.js +7 -1
  17. package/dist/module/components/TableWidget/ColumnRenderer.js.map +1 -1
  18. package/dist/module/hooks/useLiveRatesQuery.js.map +1 -1
  19. package/dist/module/hooks/useVisibleLiveDataRecord.js +2 -1
  20. package/dist/module/hooks/useVisibleLiveDataRecord.js.map +1 -1
  21. package/dist/module/providers/LiveRates/LiveRatesProvider.js +25 -2
  22. package/dist/module/providers/LiveRates/LiveRatesProvider.js.map +1 -1
  23. package/dist/module/providers/Widget/WidgetProvider.js +3 -1
  24. package/dist/module/providers/Widget/WidgetProvider.js.map +1 -1
  25. package/dist/module/types/dataTypes.js +1 -0
  26. package/dist/module/types/dataTypes.js.map +1 -1
  27. package/dist/module/types/liveRatesTypes.js.map +1 -1
  28. package/dist/module/utils/liveRates/buildUrl.js +1 -1
  29. package/dist/module/utils/liveRates/buildUrl.js.map +1 -1
  30. package/dist/types/types/dataTypes.d.ts +3 -1
  31. package/dist/types/types/liveRatesTypes.d.ts +2 -1
  32. package/package.json +2 -2
  33. package/src/components/TableWidget/ColumnRenderer.tsx +10 -0
  34. package/src/hooks/useLiveRatesQuery.ts +5 -1
  35. package/src/hooks/useVisibleLiveDataRecord.ts +1 -0
  36. package/src/providers/LiveRates/LiveRatesProvider.tsx +44 -3
  37. package/src/providers/Widget/WidgetProvider.tsx +8 -2
  38. package/src/types/dataTypes.ts +2 -0
  39. package/src/types/liveRatesTypes.ts +2 -1
  40. package/src/utils/liveRates/buildUrl.ts +1 -1
  41. package/test/components/TableWidget/Cards.test.tsx +0 -24
@@ -1 +1 @@
1
- {"version":3,"file":"WidgetProvider.js","names":["ApolloProvider","LocaleProvider","React","Suspense","Theme","getLocale","ConditionalProvider","LayoutProvider","LiveRatesProvider","defaultStyling","fitContent","removePadding","size","undefined","WidgetProvider","_ref","children","locale","translations","client","theme","Light","withSuspense","styling","liveRates","url","options","_objectSpread","createElement","Provider","render","shouldFitContent","shouldRemovePadding"],"sources":["../../../../src/providers/Widget/WidgetProvider.tsx"],"sourcesContent":["import type { ApolloClient, NormalizedCacheObject } from '@apollo/client';\nimport { ApolloProvider } from '@apollo/client';\nimport type { Locale, Translations } from '@oanda/mono-i18n';\nimport { LocaleProvider } from '@oanda/mono-i18n';\nimport type { PropsWithChildren } from 'react';\nimport React, { Suspense } from 'react';\n\nimport type { LiveRatesConfig, Size, WidgetStyling } from '../../types';\nimport { Theme } from '../../types';\nimport { getLocale } from '../../utils';\nimport { ConditionalProvider } from '../ConditionalProvider';\nimport { LayoutProvider } from '../Layout';\nimport { LiveRatesProvider } from '../LiveRates';\n\ninterface WidgetLayout {\n size?: Size;\n}\n\ntype WidgetProviderProps = PropsWithChildren & {\n locale: Locale;\n translations: Translations;\n client: ApolloClient<NormalizedCacheObject>;\n withSuspense?: boolean;\n theme?: Theme;\n styling?: Partial<WidgetStyling> & WidgetLayout;\n liveRates?: LiveRatesConfig;\n};\n\nconst defaultStyling: WidgetStyling & WidgetLayout = {\n fitContent: false,\n removePadding: false,\n size: undefined,\n};\n\nexport const WidgetProvider: React.FC<WidgetProviderProps> = ({\n children,\n locale,\n translations,\n client,\n theme = Theme.Light,\n withSuspense = false,\n styling,\n liveRates: { url, options } = { url: '' },\n}) => {\n const { fitContent, removePadding, size } = {\n ...defaultStyling,\n ...styling,\n };\n\n return (\n <LocaleProvider locale={getLocale(locale)} translations={translations}>\n <ConditionalProvider\n Provider={<LiveRatesProvider options={options} url={url} />}\n render={!!url}\n >\n <ApolloProvider client={client}>\n <ConditionalProvider Provider={<Suspense />} render={withSuspense}>\n <LayoutProvider\n shouldFitContent={fitContent}\n shouldRemovePadding={removePadding}\n size={size}\n theme={theme}\n >\n {children}\n </LayoutProvider>\n </ConditionalProvider>\n </ApolloProvider>\n </ConditionalProvider>\n </LocaleProvider>\n );\n};\n"],"mappings":";;;;;AACA,SAASA,cAAc,QAAQ,gBAAgB;AAE/C,SAASC,cAAc,QAAQ,kBAAkB;AAEjD,OAAOC,KAAK,IAAIC,QAAQ,QAAQ,OAAO;AAGvC,SAASC,KAAK,QAAQ,aAAa;AACnC,SAASC,SAAS,QAAQ,aAAa;AACvC,SAASC,mBAAmB,QAAQ,wBAAwB;AAC5D,SAASC,cAAc,QAAQ,WAAW;AAC1C,SAASC,iBAAiB,QAAQ,cAAc;AAgBhD,MAAMC,cAA4C,GAAG;EACnDC,UAAU,EAAE,KAAK;EACjBC,aAAa,EAAE,KAAK;EACpBC,IAAI,EAAEC;AACR,CAAC;AAED,OAAO,MAAMC,cAA6C,GAAGC,IAAA,IASvD;EAAA,IATwD;IAC5DC,QAAQ;IACRC,MAAM;IACNC,YAAY;IACZC,MAAM;IACNC,KAAK,GAAGhB,KAAK,CAACiB,KAAK;IACnBC,YAAY,GAAG,KAAK;IACpBC,OAAO;IACPC,SAAS,EAAE;MAAEC,GAAG;MAAEC;IAAQ,CAAC,GAAG;MAAED,GAAG,EAAE;IAAG;EAC1C,CAAC,GAAAV,IAAA;EACC,MAAM;IAAEL,UAAU;IAAEC,aAAa;IAAEC;EAAK,CAAC,GAAAe,aAAA,CAAAA,aAAA,KACpClB,cAAc,GACdc,OAAO,CACX;EAED,OACErB,KAAA,CAAA0B,aAAA,CAAC3B,cAAc;IAACgB,MAAM,EAAEZ,SAAS,CAACY,MAAM,CAAE;IAACC,YAAY,EAAEA;EAAa,GACpEhB,KAAA,CAAA0B,aAAA,CAACtB,mBAAmB;IAClBuB,QAAQ,EAAE3B,KAAA,CAAA0B,aAAA,CAACpB,iBAAiB;MAACkB,OAAO,EAAEA,OAAQ;MAACD,GAAG,EAAEA;IAAI,CAAE,CAAE;IAC5DK,MAAM,EAAE,CAAC,CAACL;EAAI,GAEdvB,KAAA,CAAA0B,aAAA,CAAC5B,cAAc;IAACmB,MAAM,EAAEA;EAAO,GAC7BjB,KAAA,CAAA0B,aAAA,CAACtB,mBAAmB;IAACuB,QAAQ,EAAE3B,KAAA,CAAA0B,aAAA,CAACzB,QAAQ,MAAE,CAAE;IAAC2B,MAAM,EAAER;EAAa,GAChEpB,KAAA,CAAA0B,aAAA,CAACrB,cAAc;IACbwB,gBAAgB,EAAErB,UAAW;IAC7BsB,mBAAmB,EAAErB,aAAc;IACnCC,IAAI,EAAEA,IAAK;IACXQ,KAAK,EAAEA;EAAM,GAEZJ,QACa,CACG,CACP,CACG,CACP,CAAC;AAErB,CAAC","ignoreList":[]}
1
+ {"version":3,"file":"WidgetProvider.js","names":["ApolloProvider","LocaleProvider","React","Suspense","Theme","getLocale","ConditionalProvider","LayoutProvider","LiveRatesProvider","defaultStyling","fitContent","removePadding","size","undefined","WidgetProvider","_ref","children","locale","translations","client","theme","Light","withSuspense","styling","liveRates","url","options","multipleDataSources","_objectSpread","createElement","Provider","render","shouldFitContent","shouldRemovePadding"],"sources":["../../../../src/providers/Widget/WidgetProvider.tsx"],"sourcesContent":["import type { ApolloClient, NormalizedCacheObject } from '@apollo/client';\nimport { ApolloProvider } from '@apollo/client';\nimport type { Locale, Translations } from '@oanda/mono-i18n';\nimport { LocaleProvider } from '@oanda/mono-i18n';\nimport type { PropsWithChildren } from 'react';\nimport React, { Suspense } from 'react';\n\nimport type { LiveRatesConfig, Size, WidgetStyling } from '../../types';\nimport { Theme } from '../../types';\nimport { getLocale } from '../../utils';\nimport { ConditionalProvider } from '../ConditionalProvider';\nimport { LayoutProvider } from '../Layout';\nimport { LiveRatesProvider } from '../LiveRates';\n\ninterface WidgetLayout {\n size?: Size;\n}\n\ntype WidgetProviderProps = PropsWithChildren & {\n locale: Locale;\n translations: Translations;\n client: ApolloClient<NormalizedCacheObject>;\n withSuspense?: boolean;\n theme?: Theme;\n styling?: Partial<WidgetStyling> & WidgetLayout;\n liveRates?: LiveRatesConfig;\n};\n\nconst defaultStyling: WidgetStyling & WidgetLayout = {\n fitContent: false,\n removePadding: false,\n size: undefined,\n};\n\nexport const WidgetProvider: React.FC<WidgetProviderProps> = ({\n children,\n locale,\n translations,\n client,\n theme = Theme.Light,\n withSuspense = false,\n styling,\n liveRates: { url, options, multipleDataSources } = { url: '' },\n}) => {\n const { fitContent, removePadding, size } = {\n ...defaultStyling,\n ...styling,\n };\n\n return (\n <LocaleProvider locale={getLocale(locale)} translations={translations}>\n <ConditionalProvider\n Provider={\n <LiveRatesProvider\n multipleDataSources={multipleDataSources}\n options={options}\n url={url}\n />\n }\n render={!!url}\n >\n <ApolloProvider client={client}>\n <ConditionalProvider Provider={<Suspense />} render={withSuspense}>\n <LayoutProvider\n shouldFitContent={fitContent}\n shouldRemovePadding={removePadding}\n size={size}\n theme={theme}\n >\n {children}\n </LayoutProvider>\n </ConditionalProvider>\n </ApolloProvider>\n </ConditionalProvider>\n </LocaleProvider>\n );\n};\n"],"mappings":";;;;;AACA,SAASA,cAAc,QAAQ,gBAAgB;AAE/C,SAASC,cAAc,QAAQ,kBAAkB;AAEjD,OAAOC,KAAK,IAAIC,QAAQ,QAAQ,OAAO;AAGvC,SAASC,KAAK,QAAQ,aAAa;AACnC,SAASC,SAAS,QAAQ,aAAa;AACvC,SAASC,mBAAmB,QAAQ,wBAAwB;AAC5D,SAASC,cAAc,QAAQ,WAAW;AAC1C,SAASC,iBAAiB,QAAQ,cAAc;AAgBhD,MAAMC,cAA4C,GAAG;EACnDC,UAAU,EAAE,KAAK;EACjBC,aAAa,EAAE,KAAK;EACpBC,IAAI,EAAEC;AACR,CAAC;AAED,OAAO,MAAMC,cAA6C,GAAGC,IAAA,IASvD;EAAA,IATwD;IAC5DC,QAAQ;IACRC,MAAM;IACNC,YAAY;IACZC,MAAM;IACNC,KAAK,GAAGhB,KAAK,CAACiB,KAAK;IACnBC,YAAY,GAAG,KAAK;IACpBC,OAAO;IACPC,SAAS,EAAE;MAAEC,GAAG;MAAEC,OAAO;MAAEC;IAAoB,CAAC,GAAG;MAAEF,GAAG,EAAE;IAAG;EAC/D,CAAC,GAAAV,IAAA;EACC,MAAM;IAAEL,UAAU;IAAEC,aAAa;IAAEC;EAAK,CAAC,GAAAgB,aAAA,CAAAA,aAAA,KACpCnB,cAAc,GACdc,OAAO,CACX;EAED,OACErB,KAAA,CAAA2B,aAAA,CAAC5B,cAAc;IAACgB,MAAM,EAAEZ,SAAS,CAACY,MAAM,CAAE;IAACC,YAAY,EAAEA;EAAa,GACpEhB,KAAA,CAAA2B,aAAA,CAACvB,mBAAmB;IAClBwB,QAAQ,EACN5B,KAAA,CAAA2B,aAAA,CAACrB,iBAAiB;MAChBmB,mBAAmB,EAAEA,mBAAoB;MACzCD,OAAO,EAAEA,OAAQ;MACjBD,GAAG,EAAEA;IAAI,CACV,CACF;IACDM,MAAM,EAAE,CAAC,CAACN;EAAI,GAEdvB,KAAA,CAAA2B,aAAA,CAAC7B,cAAc;IAACmB,MAAM,EAAEA;EAAO,GAC7BjB,KAAA,CAAA2B,aAAA,CAACvB,mBAAmB;IAACwB,QAAQ,EAAE5B,KAAA,CAAA2B,aAAA,CAAC1B,QAAQ,MAAE,CAAE;IAAC4B,MAAM,EAAET;EAAa,GAChEpB,KAAA,CAAA2B,aAAA,CAACtB,cAAc;IACbyB,gBAAgB,EAAEtB,UAAW;IAC7BuB,mBAAmB,EAAEtB,aAAc;IACnCC,IAAI,EAAEA,IAAK;IACXQ,KAAK,EAAEA;EAAM,GAEZJ,QACa,CACG,CACP,CACG,CACP,CAAC;AAErB,CAAC","ignoreList":[]}
@@ -10,6 +10,7 @@ export let DataRecordType = function (DataRecordType) {
10
10
  DataRecordType["HIGH"] = "high";
11
11
  DataRecordType["SYMBOL"] = "symbol";
12
12
  DataRecordType["TRADE_MODE"] = "tradeMode";
13
+ DataRecordType["DATA_SOURCE"] = "dataSource";
13
14
  return DataRecordType;
14
15
  }({});
15
16
  //# sourceMappingURL=dataTypes.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"dataTypes.js","names":["DataRecordType"],"sources":["../../../src/types/dataTypes.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any */\nexport interface DataRecord {\n [key: string]: string | number | SentimentValue | undefined | number[];\n instrument: string;\n displayName: string;\n buy?: number;\n sell?: number;\n spread?: number;\n sentiment?: SentimentValue;\n sellPriceMovement?: number;\n buyPriceMovement?: number;\n dailyPercentChange?: string;\n displayPrecision?: number;\n chart?: number[];\n high?: number;\n low?: number;\n tradeMode?: string;\n}\n\nexport interface SentimentValue {\n shortPercent: number;\n longPercent: number;\n}\n\nexport type EmptyRecord = Record<string, never>;\n\nexport interface QueryVariables {\n [key: string]: any;\n}\n\nexport enum DataRecordType {\n INSTRUMENT = 'instrument',\n SELL = 'sell',\n BUY = 'buy',\n DAILY_CHANGE = 'dailyChange',\n CHART = 'chart',\n SPREAD = 'spread',\n SENTIMENT = 'sentiment',\n LOW = 'low',\n HIGH = 'high',\n SYMBOL = 'symbol',\n TRADE_MODE = 'tradeMode',\n}\n"],"mappings":"AA8BA,WAAYA,cAAc,aAAdA,cAAc;EAAdA,cAAc;EAAdA,cAAc;EAAdA,cAAc;EAAdA,cAAc;EAAdA,cAAc;EAAdA,cAAc;EAAdA,cAAc;EAAdA,cAAc;EAAdA,cAAc;EAAdA,cAAc;EAAdA,cAAc;EAAA,OAAdA,cAAc;AAAA","ignoreList":[]}
1
+ {"version":3,"file":"dataTypes.js","names":["DataRecordType"],"sources":["../../../src/types/dataTypes.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any */\nexport interface DataRecord {\n [key: string]: string | number | SentimentValue | undefined | number[];\n instrument: string;\n displayName: string;\n buy?: number;\n sell?: number;\n spread?: number;\n sentiment?: SentimentValue;\n sellPriceMovement?: number;\n buyPriceMovement?: number;\n dailyPercentChange?: string;\n displayPrecision?: number;\n chart?: number[];\n high?: number;\n low?: number;\n tradeMode?: string;\n dataSource?: string;\n}\n\nexport interface SentimentValue {\n shortPercent: number;\n longPercent: number;\n}\n\nexport type EmptyRecord = Record<string, never>;\n\nexport interface QueryVariables {\n [key: string]: any;\n}\n\nexport enum DataRecordType {\n INSTRUMENT = 'instrument',\n SELL = 'sell',\n BUY = 'buy',\n DAILY_CHANGE = 'dailyChange',\n CHART = 'chart',\n SPREAD = 'spread',\n SENTIMENT = 'sentiment',\n LOW = 'low',\n HIGH = 'high',\n SYMBOL = 'symbol',\n TRADE_MODE = 'tradeMode',\n DATA_SOURCE = 'dataSource',\n}\n"],"mappings":"AA+BA,WAAYA,cAAc,aAAdA,cAAc;EAAdA,cAAc;EAAdA,cAAc;EAAdA,cAAc;EAAdA,cAAc;EAAdA,cAAc;EAAdA,cAAc;EAAdA,cAAc;EAAdA,cAAc;EAAdA,cAAc;EAAdA,cAAc;EAAdA,cAAc;EAAdA,cAAc;EAAA,OAAdA,cAAc;AAAA","ignoreList":[]}
@@ -1 +1 @@
1
- {"version":3,"file":"liveRatesTypes.js","names":[],"sources":["../../../src/types/liveRatesTypes.ts"],"sourcesContent":["export type LiveRatesDataSource = 'V20' | 'MT5';\n\nexport interface LiveRatesProviderQuery {\n instruments: string[];\n division?: string;\n dataSource?: LiveRatesDataSource;\n}\n\nexport interface LiveRatesProviderOptions {\n divisionCode?: string;\n dataSource?: LiveRatesDataSource;\n}\n\nexport interface LiveRatesConfig {\n url: string;\n query?: LiveRatesProviderQuery;\n options?: LiveRatesProviderOptions;\n eventSource?: EventSource;\n eventTarget?: EventTarget;\n eventName?: string;\n}\n\nexport interface LiveRatesHookMessage\n extends Omit<\n LiveRatesUpdateMessage,\n 'closingAsk' | 'closingBid' | 'openingAsk' | 'openingBid' | 'extraPrecision'\n > {\n spread: number;\n priceMovement: number;\n askPriceMovement: number;\n bidPriceMovement: number;\n dailyPriceMovement: number;\n dailyPipsChange: number;\n dailyPercentChange: number;\n dailyPercentChangeFromOpen: string;\n dailyPipsChangeFromOpen: number;\n displayPrecision: number;\n high: number;\n low: number;\n}\n\nexport interface LiveRatesHookReturnObject {\n update: LiveRatesHookMessage | null;\n error: LiveRatesErrorMessage | null;\n connectionError: boolean;\n setQuery: (query: LiveRatesProviderQuery) => void;\n}\n\nexport interface LiveRatesConnectionErrorMessage {\n messageType?: string;\n symbol: string;\n}\n\nexport interface LiveRatesTargetHookReturnObject {\n closeQuery: () => void;\n setQuery: (query: LiveRatesProviderQuery) => void;\n target: EventTarget | null;\n}\n\nexport interface LiveRatesMessageReturnObject {\n update: LiveRatesHookMessage | null;\n error: LiveRatesErrorMessage | null;\n connectionError: boolean;\n}\n\ninterface LiveRatesBaseMessage {\n messageType?: string;\n symbol: string;\n timestamp: string;\n}\nexport interface LiveRatesUpdateMessage extends LiveRatesBaseMessage {\n ask: number;\n bid: number;\n closingAsk: number;\n closingBid: number;\n openingAsk: number;\n openingBid: number;\n pipLocation: number;\n extraPrecision: number;\n low: number;\n high: number;\n}\n\nexport interface LiveRatesErrorMessage extends LiveRatesBaseMessage {\n error: string;\n}\n\nexport interface PriceChange {\n pipsChange: number;\n percentChange: number;\n priceMovement: number;\n askPriceMovement: number;\n bidPriceMovement: number;\n}\n\nexport interface PriceChangeFromOpen {\n percentChangeFromOpen: string;\n}\n\nexport interface PipsChangeFromOpen {\n pipsChangeFromOpen: number;\n}\n\nexport type Base64Decoder = (data: string) => string;\n\nexport type JsonParser = (data: string) => LiveRatesUpdateMessage;\n\nexport interface CalculatePriceChangeInput {\n pipLocation: number;\n extraPrecision: number;\n currentAsk: number;\n currentBid: number;\n prevAsk?: number;\n prevBid?: number;\n}\n"],"mappings":"","ignoreList":[]}
1
+ {"version":3,"file":"liveRatesTypes.js","names":[],"sources":["../../../src/types/liveRatesTypes.ts"],"sourcesContent":["export type LiveRatesDataSource = 'V20' | 'MT5' | 'All';\n\nexport interface LiveRatesProviderQuery {\n instruments: string[];\n division?: string;\n dataSource?: LiveRatesDataSource;\n}\n\nexport interface LiveRatesProviderOptions {\n divisionCode?: string;\n dataSource?: LiveRatesDataSource;\n}\n\nexport interface LiveRatesConfig {\n url: string;\n query?: LiveRatesProviderQuery;\n options?: LiveRatesProviderOptions;\n eventSource?: EventSource;\n eventTarget?: EventTarget;\n eventName?: string;\n multipleDataSources?: boolean;\n}\n\nexport interface LiveRatesHookMessage\n extends Omit<\n LiveRatesUpdateMessage,\n 'closingAsk' | 'closingBid' | 'openingAsk' | 'openingBid' | 'extraPrecision'\n > {\n spread: number;\n priceMovement: number;\n askPriceMovement: number;\n bidPriceMovement: number;\n dailyPriceMovement: number;\n dailyPipsChange: number;\n dailyPercentChange: number;\n dailyPercentChangeFromOpen: string;\n dailyPipsChangeFromOpen: number;\n displayPrecision: number;\n high: number;\n low: number;\n}\n\nexport interface LiveRatesHookReturnObject {\n update: LiveRatesHookMessage | null;\n error: LiveRatesErrorMessage | null;\n connectionError: boolean;\n setQuery: (query: LiveRatesProviderQuery) => void;\n}\n\nexport interface LiveRatesConnectionErrorMessage {\n messageType?: string;\n symbol: string;\n}\n\nexport interface LiveRatesTargetHookReturnObject {\n closeQuery: () => void;\n setQuery: (query: LiveRatesProviderQuery) => void;\n target: EventTarget | null;\n}\n\nexport interface LiveRatesMessageReturnObject {\n update: LiveRatesHookMessage | null;\n error: LiveRatesErrorMessage | null;\n connectionError: boolean;\n}\n\ninterface LiveRatesBaseMessage {\n messageType?: string;\n symbol: string;\n timestamp: string;\n}\nexport interface LiveRatesUpdateMessage extends LiveRatesBaseMessage {\n ask: number;\n bid: number;\n closingAsk: number;\n closingBid: number;\n openingAsk: number;\n openingBid: number;\n pipLocation: number;\n extraPrecision: number;\n low: number;\n high: number;\n}\n\nexport interface LiveRatesErrorMessage extends LiveRatesBaseMessage {\n error: string;\n}\n\nexport interface PriceChange {\n pipsChange: number;\n percentChange: number;\n priceMovement: number;\n askPriceMovement: number;\n bidPriceMovement: number;\n}\n\nexport interface PriceChangeFromOpen {\n percentChangeFromOpen: string;\n}\n\nexport interface PipsChangeFromOpen {\n pipsChangeFromOpen: number;\n}\n\nexport type Base64Decoder = (data: string) => string;\n\nexport type JsonParser = (data: string) => LiveRatesUpdateMessage;\n\nexport interface CalculatePriceChangeInput {\n pipLocation: number;\n extraPrecision: number;\n currentAsk: number;\n currentBid: number;\n prevAsk?: number;\n prevBid?: number;\n}\n"],"mappings":"","ignoreList":[]}
@@ -10,7 +10,7 @@ export const buildUrl = (url, query, options) => {
10
10
  }
11
11
  const queryParams = query && _objectSpread(_objectSpread({}, query), !query.division && options !== null && options !== void 0 && options.divisionCode ? {
12
12
  division: options.divisionCode,
13
- dataSource: options.dataSource
13
+ dataSource: options.dataSource || query.dataSource
14
14
  } : {});
15
15
  const queryString = queryParams ? Object.entries(queryParams).map(_ref => {
16
16
  let [key, value] = _ref;
@@ -1 +1 @@
1
- {"version":3,"file":"buildUrl.js","names":["buildUrl","url","query","options","baseUrl","baseQueryString","split","Error","queryParams","_objectSpread","division","divisionCode","dataSource","queryString","Object","entries","map","_ref","key","value","Array","isArray","concat","join","filter","Boolean"],"sources":["../../../../src/utils/liveRates/buildUrl.ts"],"sourcesContent":["import type {\n LiveRatesProviderOptions,\n LiveRatesProviderQuery,\n} from '../../types';\n\nexport const buildUrl = (\n url: string,\n query?: LiveRatesProviderQuery,\n options?: LiveRatesProviderOptions\n): string => {\n const [baseUrl, baseQueryString] = url.split('?');\n\n if (!query && !baseQueryString) {\n throw new Error('Instruments query is not provided!');\n }\n\n const queryParams = query && {\n ...query,\n ...(!query.division && options?.divisionCode\n ? {\n division: options.divisionCode,\n dataSource: options.dataSource,\n }\n : {}),\n };\n\n const queryString = queryParams\n ? Object.entries(queryParams)\n .map(([key, value]) =>\n Array.isArray(value)\n ? value && `${key}=${value.join(',')}`\n : value && `${key}=${value}`\n )\n .filter(Boolean)\n .join('&')\n : baseQueryString;\n\n return `${baseUrl}?${queryString}`;\n};\n"],"mappings":";;;;;AAKA,OAAO,MAAMA,QAAQ,GAAGA,CACtBC,GAAW,EACXC,KAA8B,EAC9BC,OAAkC,KACvB;EACX,MAAM,CAACC,OAAO,EAAEC,eAAe,CAAC,GAAGJ,GAAG,CAACK,KAAK,CAAC,GAAG,CAAC;EAEjD,IAAI,CAACJ,KAAK,IAAI,CAACG,eAAe,EAAE;IAC9B,MAAM,IAAIE,KAAK,CAAC,oCAAoC,CAAC;EACvD;EAEA,MAAMC,WAAW,GAAGN,KAAK,IAAAO,aAAA,CAAAA,aAAA,KACpBP,KAAK,GACJ,CAACA,KAAK,CAACQ,QAAQ,IAAIP,OAAO,aAAPA,OAAO,eAAPA,OAAO,CAAEQ,YAAY,GACxC;IACED,QAAQ,EAAEP,OAAO,CAACQ,YAAY;IAC9BC,UAAU,EAAET,OAAO,CAACS;EACtB,CAAC,GACD,CAAC,CAAC,CACP;EAED,MAAMC,WAAW,GAAGL,WAAW,GAC3BM,MAAM,CAACC,OAAO,CAACP,WAAW,CAAC,CACxBQ,GAAG,CAACC,IAAA;IAAA,IAAC,CAACC,GAAG,EAAEC,KAAK,CAAC,GAAAF,IAAA;IAAA,OAChBG,KAAK,CAACC,OAAO,CAACF,KAAK,CAAC,GAChBA,KAAK,OAAAG,MAAA,CAAOJ,GAAG,OAAAI,MAAA,CAAIH,KAAK,CAACI,IAAI,CAAC,GAAG,CAAC,CAAE,GACpCJ,KAAK,OAAAG,MAAA,CAAOJ,GAAG,OAAAI,MAAA,CAAIH,KAAK,CAAE;EAAA,CAChC,CAAC,CACAK,MAAM,CAACC,OAAO,CAAC,CACfF,IAAI,CAAC,GAAG,CAAC,GACZlB,eAAe;EAEnB,UAAAiB,MAAA,CAAUlB,OAAO,OAAAkB,MAAA,CAAIT,WAAW;AAClC,CAAC","ignoreList":[]}
1
+ {"version":3,"file":"buildUrl.js","names":["buildUrl","url","query","options","baseUrl","baseQueryString","split","Error","queryParams","_objectSpread","division","divisionCode","dataSource","queryString","Object","entries","map","_ref","key","value","Array","isArray","concat","join","filter","Boolean"],"sources":["../../../../src/utils/liveRates/buildUrl.ts"],"sourcesContent":["import type {\n LiveRatesProviderOptions,\n LiveRatesProviderQuery,\n} from '../../types';\n\nexport const buildUrl = (\n url: string,\n query?: LiveRatesProviderQuery,\n options?: LiveRatesProviderOptions\n): string => {\n const [baseUrl, baseQueryString] = url.split('?');\n\n if (!query && !baseQueryString) {\n throw new Error('Instruments query is not provided!');\n }\n\n const queryParams = query && {\n ...query,\n ...(!query.division && options?.divisionCode\n ? {\n division: options.divisionCode,\n dataSource: options.dataSource || query.dataSource,\n }\n : {}),\n };\n\n const queryString = queryParams\n ? Object.entries(queryParams)\n .map(([key, value]) =>\n Array.isArray(value)\n ? value && `${key}=${value.join(',')}`\n : value && `${key}=${value}`\n )\n .filter(Boolean)\n .join('&')\n : baseQueryString;\n\n return `${baseUrl}?${queryString}`;\n};\n"],"mappings":";;;;;AAKA,OAAO,MAAMA,QAAQ,GAAGA,CACtBC,GAAW,EACXC,KAA8B,EAC9BC,OAAkC,KACvB;EACX,MAAM,CAACC,OAAO,EAAEC,eAAe,CAAC,GAAGJ,GAAG,CAACK,KAAK,CAAC,GAAG,CAAC;EAEjD,IAAI,CAACJ,KAAK,IAAI,CAACG,eAAe,EAAE;IAC9B,MAAM,IAAIE,KAAK,CAAC,oCAAoC,CAAC;EACvD;EAEA,MAAMC,WAAW,GAAGN,KAAK,IAAAO,aAAA,CAAAA,aAAA,KACpBP,KAAK,GACJ,CAACA,KAAK,CAACQ,QAAQ,IAAIP,OAAO,aAAPA,OAAO,eAAPA,OAAO,CAAEQ,YAAY,GACxC;IACED,QAAQ,EAAEP,OAAO,CAACQ,YAAY;IAC9BC,UAAU,EAAET,OAAO,CAACS,UAAU,IAAIV,KAAK,CAACU;EAC1C,CAAC,GACD,CAAC,CAAC,CACP;EAED,MAAMC,WAAW,GAAGL,WAAW,GAC3BM,MAAM,CAACC,OAAO,CAACP,WAAW,CAAC,CACxBQ,GAAG,CAACC,IAAA;IAAA,IAAC,CAACC,GAAG,EAAEC,KAAK,CAAC,GAAAF,IAAA;IAAA,OAChBG,KAAK,CAACC,OAAO,CAACF,KAAK,CAAC,GAChBA,KAAK,OAAAG,MAAA,CAAOJ,GAAG,OAAAI,MAAA,CAAIH,KAAK,CAACI,IAAI,CAAC,GAAG,CAAC,CAAE,GACpCJ,KAAK,OAAAG,MAAA,CAAOJ,GAAG,OAAAI,MAAA,CAAIH,KAAK,CAAE;EAAA,CAChC,CAAC,CACAK,MAAM,CAACC,OAAO,CAAC,CACfF,IAAI,CAAC,GAAG,CAAC,GACZlB,eAAe;EAEnB,UAAAiB,MAAA,CAAUlB,OAAO,OAAAkB,MAAA,CAAIT,WAAW;AAClC,CAAC","ignoreList":[]}
@@ -14,6 +14,7 @@ export interface DataRecord {
14
14
  high?: number;
15
15
  low?: number;
16
16
  tradeMode?: string;
17
+ dataSource?: string;
17
18
  }
18
19
  export interface SentimentValue {
19
20
  shortPercent: number;
@@ -34,5 +35,6 @@ export declare enum DataRecordType {
34
35
  LOW = "low",
35
36
  HIGH = "high",
36
37
  SYMBOL = "symbol",
37
- TRADE_MODE = "tradeMode"
38
+ TRADE_MODE = "tradeMode",
39
+ DATA_SOURCE = "dataSource"
38
40
  }
@@ -1,4 +1,4 @@
1
- export type LiveRatesDataSource = 'V20' | 'MT5';
1
+ export type LiveRatesDataSource = 'V20' | 'MT5' | 'All';
2
2
  export interface LiveRatesProviderQuery {
3
3
  instruments: string[];
4
4
  division?: string;
@@ -15,6 +15,7 @@ export interface LiveRatesConfig {
15
15
  eventSource?: EventSource;
16
16
  eventTarget?: EventTarget;
17
17
  eventName?: string;
18
+ multipleDataSources?: boolean;
18
19
  }
19
20
  export interface LiveRatesHookMessage extends Omit<LiveRatesUpdateMessage, 'closingAsk' | 'closingBid' | 'openingAsk' | 'openingBid' | 'extraPrecision'> {
20
21
  spread: number;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oanda/labs-widget-common",
3
- "version": "1.0.224",
3
+ "version": "1.0.226",
4
4
  "description": "Labs Widget Common",
5
5
  "main": "dist/main/index.js",
6
6
  "module": "dist/module/index.js",
@@ -21,5 +21,5 @@
21
21
  "tailwind-merge": "2.2.2",
22
22
  "usehooks-ts": "3.0.2"
23
23
  },
24
- "gitHead": "b03e9304ac39928b92878bab83628b07214c3c6f"
24
+ "gitHead": "4709e181ae37de87e1c5d5569391c5f6cfeeca33"
25
25
  }
@@ -115,6 +115,16 @@ export const ColumnRenderer = ({
115
115
  <span>{record.tradeMode}</span>
116
116
  </TableCell>
117
117
  ),
118
+ [DataRecordType.DATA_SOURCE]: () => (
119
+ <TableCell
120
+ key={DataRecordType.TRADE_MODE}
121
+ isError={!record.dataSource}
122
+ isLoading={isLoading}
123
+ loaderSize={LoaderSize.sm}
124
+ >
125
+ <span>{record.dataSource}</span>
126
+ </TableCell>
127
+ ),
118
128
  };
119
129
 
120
130
  return activeColumns.map((item) => (
@@ -20,5 +20,9 @@ export const useLiveRatesQuery = (
20
20
  liveRates?.source?.close();
21
21
  };
22
22
 
23
- return { target: liveRates?.target || null, setQuery, closeQuery };
23
+ return {
24
+ target: liveRates?.target || null,
25
+ setQuery,
26
+ closeQuery,
27
+ };
24
28
  };
@@ -40,6 +40,7 @@ export const useVisibleLiveDataRecord = (
40
40
  displayPrecision: update?.displayPrecision,
41
41
  high: update?.high,
42
42
  low: update?.low,
43
+ dataSource: record.dataSource,
43
44
  });
44
45
  setError(liveRatesError);
45
46
  }
@@ -1,3 +1,4 @@
1
+ import { DataSource } from '@oanda/labs-instruments-table-widget/src/gql/types/graphql';
1
2
  import type { PropsWithChildren, ReactElement } from 'react';
2
3
  import React, { useEffect, useState } from 'react';
3
4
 
@@ -11,6 +12,7 @@ import type {
11
12
  LiveRatesConfig,
12
13
  LiveRatesConnectionErrorMessage,
13
14
  LiveRatesErrorMessage,
15
+ LiveRatesProviderQuery,
14
16
  LiveRatesUpdateMessage,
15
17
  } from '../../types';
16
18
  import { buildUrl, decodeLiveRateMessage } from '../../utils/liveRates';
@@ -26,15 +28,29 @@ export const LiveRatesProvider: React.FC<LiveRatesProviderProps> = ({
26
28
  eventSource,
27
29
  eventTarget,
28
30
  eventName = LIVE_RATES_EVENT_NAME,
31
+ multipleDataSources = false,
29
32
  }): ReactElement => {
30
33
  const [source, setSource] = useState(
31
34
  eventSource || (query && new EventSource(buildUrl(url, query, options)))
32
35
  );
36
+ const [secondSource, setSecondSource] = useState<EventSource | undefined>(
37
+ undefined
38
+ );
33
39
  const target = eventTarget || new EventTarget();
34
40
 
35
- const setQueryListener: EventListener = ({ detail }: CustomEventInit) => {
36
- // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
37
- setSource(new EventSource(buildUrl(url, detail, options)));
41
+ const setQueryListener: EventListener = ({
42
+ detail,
43
+ }: CustomEventInit<LiveRatesProviderQuery>) => {
44
+ if (multipleDataSources) {
45
+ if (detail?.dataSource === DataSource.Mt5) {
46
+ setSecondSource(new EventSource(buildUrl(url, detail, options)));
47
+ }
48
+ if (detail?.dataSource === DataSource.V20) {
49
+ setSource(new EventSource(buildUrl(url, detail, options)));
50
+ }
51
+ } else {
52
+ setSource(new EventSource(buildUrl(url, detail, options)));
53
+ }
38
54
  };
39
55
 
40
56
  target.addEventListener(SET_QUERY_EVENT_NAME, setQueryListener);
@@ -69,6 +85,18 @@ export const LiveRatesProvider: React.FC<LiveRatesProviderProps> = ({
69
85
  );
70
86
  source?.addEventListener('error', listener(LIVE_RATES_CONNECTION_ERROR));
71
87
 
88
+ if (multipleDataSources && secondSource) {
89
+ secondSource?.addEventListener(eventName, listener(eventName));
90
+ secondSource?.addEventListener(
91
+ LIVE_RATES_RATE_ERROR,
92
+ listener(LIVE_RATES_RATE_ERROR)
93
+ );
94
+ secondSource?.addEventListener(
95
+ 'error',
96
+ listener(LIVE_RATES_CONNECTION_ERROR)
97
+ );
98
+ }
99
+
72
100
  return () => {
73
101
  target.removeEventListener(SET_QUERY_EVENT_NAME, setQueryListener);
74
102
  source?.removeEventListener(eventName, listener(eventName));
@@ -81,6 +109,19 @@ export const LiveRatesProvider: React.FC<LiveRatesProviderProps> = ({
81
109
  listener(LIVE_RATES_CONNECTION_ERROR)
82
110
  );
83
111
  source?.close();
112
+
113
+ if (multipleDataSources && secondSource) {
114
+ secondSource?.removeEventListener(eventName, listener(eventName));
115
+ secondSource?.removeEventListener(
116
+ LIVE_RATES_RATE_ERROR,
117
+ listener(LIVE_RATES_RATE_ERROR)
118
+ );
119
+ secondSource?.removeEventListener(
120
+ 'error',
121
+ listener(LIVE_RATES_CONNECTION_ERROR)
122
+ );
123
+ secondSource?.close();
124
+ }
84
125
  };
85
126
  },
86
127
  // eslint-disable-next-line react-hooks/exhaustive-deps
@@ -40,7 +40,7 @@ export const WidgetProvider: React.FC<WidgetProviderProps> = ({
40
40
  theme = Theme.Light,
41
41
  withSuspense = false,
42
42
  styling,
43
- liveRates: { url, options } = { url: '' },
43
+ liveRates: { url, options, multipleDataSources } = { url: '' },
44
44
  }) => {
45
45
  const { fitContent, removePadding, size } = {
46
46
  ...defaultStyling,
@@ -50,7 +50,13 @@ export const WidgetProvider: React.FC<WidgetProviderProps> = ({
50
50
  return (
51
51
  <LocaleProvider locale={getLocale(locale)} translations={translations}>
52
52
  <ConditionalProvider
53
- Provider={<LiveRatesProvider options={options} url={url} />}
53
+ Provider={
54
+ <LiveRatesProvider
55
+ multipleDataSources={multipleDataSources}
56
+ options={options}
57
+ url={url}
58
+ />
59
+ }
54
60
  render={!!url}
55
61
  >
56
62
  <ApolloProvider client={client}>
@@ -15,6 +15,7 @@ export interface DataRecord {
15
15
  high?: number;
16
16
  low?: number;
17
17
  tradeMode?: string;
18
+ dataSource?: string;
18
19
  }
19
20
 
20
21
  export interface SentimentValue {
@@ -40,4 +41,5 @@ export enum DataRecordType {
40
41
  HIGH = 'high',
41
42
  SYMBOL = 'symbol',
42
43
  TRADE_MODE = 'tradeMode',
44
+ DATA_SOURCE = 'dataSource',
43
45
  }
@@ -1,4 +1,4 @@
1
- export type LiveRatesDataSource = 'V20' | 'MT5';
1
+ export type LiveRatesDataSource = 'V20' | 'MT5' | 'All';
2
2
 
3
3
  export interface LiveRatesProviderQuery {
4
4
  instruments: string[];
@@ -18,6 +18,7 @@ export interface LiveRatesConfig {
18
18
  eventSource?: EventSource;
19
19
  eventTarget?: EventTarget;
20
20
  eventName?: string;
21
+ multipleDataSources?: boolean;
21
22
  }
22
23
 
23
24
  export interface LiveRatesHookMessage
@@ -19,7 +19,7 @@ export const buildUrl = (
19
19
  ...(!query.division && options?.divisionCode
20
20
  ? {
21
21
  division: options.divisionCode,
22
- dataSource: options.dataSource,
22
+ dataSource: options.dataSource || query.dataSource,
23
23
  }
24
24
  : {}),
25
25
  };
@@ -71,29 +71,5 @@ describe('Table widget component', () => {
71
71
  expect(getAllByTestId('card-header').length).toEqual(2);
72
72
  expect(getAllByTestId('card-row').length).toEqual(10);
73
73
  });
74
-
75
- it('should render error', () => {
76
- const { getAllByTestId } = render(
77
- <MockLayoutProvider>
78
- <Cards
79
- isError
80
- records={records}
81
- renderCard={({ record, idx, isLast }) => (
82
- <CardRecordRow
83
- activeColumns={columns}
84
- index={idx}
85
- isLast={isLast}
86
- isLoading={false}
87
- record={record}
88
- target={null}
89
- tooltipId="toolTipId"
90
- />
91
- )}
92
- />
93
- </MockLayoutProvider>
94
- );
95
- expect(getAllByTestId('card').length).toEqual(1);
96
- expect(getAllByTestId('chart-error').length).toEqual(1);
97
- });
98
74
  });
99
75
  });