diff options
Diffstat (limited to 'packages')
-rw-r--r-- | packages/instant/public/index.html | 6 | ||||
-rw-r--r-- | packages/instant/src/index.umd.ts | 116 |
2 files changed, 87 insertions, 35 deletions
diff --git a/packages/instant/public/index.html b/packages/instant/public/index.html index 253cbb194..557cfa3dc 100644 --- a/packages/instant/public/index.html +++ b/packages/instant/public/index.html @@ -27,6 +27,10 @@ <body> <div id="zeroExInstantContainer"></div> <script> + // Simulate history + window.history.pushState({ page: 1 }, '0x Instant'); + window.history.pushState({ page: 2 }, '0x Instant'); + window.history.pushState({ page: 3 }, '0x Instant'); const removeUndefined = (obj) => { for (let k in obj) if (obj[k] === undefined) delete obj[k]; return obj; @@ -128,8 +132,10 @@ availableAssetDatas: availableAssetDatasString ? JSON.parse(availableAssetDatasString) : undefined, defaultSelectedAssetData: queryParams.getQueryParamValue('defaultSelectedAssetData'), affiliateInfo: affiliateInfoOverride, + shouldDisablePushToHistory: !!queryParams.getQueryParamValue('shouldDisablePushToHistory'), } const renderOptions = Object.assign({}, renderOptionsDefaults, removeUndefined(renderOptionsOverrides)); + window.onpopstate = () => console.log('Integrators onpopstate called'); zeroExInstant.render(renderOptions); </script> </body> diff --git a/packages/instant/src/index.umd.ts b/packages/instant/src/index.umd.ts index 0274db30c..64f888e00 100644 --- a/packages/instant/src/index.umd.ts +++ b/packages/instant/src/index.umd.ts @@ -5,52 +5,98 @@ import * as ReactDOM from 'react-dom'; import { DEFAULT_ZERO_EX_CONTAINER_SELECTOR, INJECTED_DIV_CLASS, INJECTED_DIV_ID } from './constants'; import { ZeroExInstantOverlay, ZeroExInstantOverlayProps } from './index'; import { assert } from './util/assert'; +import { util } from './util/util'; -export const render = (props: ZeroExInstantOverlayProps, selector: string = DEFAULT_ZERO_EX_CONTAINER_SELECTOR) => { - assert.isValidOrderSource('orderSource', props.orderSource); - if (!_.isUndefined(props.defaultSelectedAssetData)) { - assert.isHexString('defaultSelectedAssetData', props.defaultSelectedAssetData); +export interface ZeroExInstantConfig extends ZeroExInstantOverlayProps { + shouldDisablePushToHistory?: boolean; +} + +export const render = (config: ZeroExInstantConfig, selector: string = DEFAULT_ZERO_EX_CONTAINER_SELECTOR) => { + assert.isValidOrderSource('orderSource', config.orderSource); + if (!_.isUndefined(config.defaultSelectedAssetData)) { + assert.isHexString('defaultSelectedAssetData', config.defaultSelectedAssetData); + } + if (!_.isUndefined(config.additionalAssetMetaDataMap)) { + assert.isValidAssetMetaDataMap('additionalAssetMetaDataMap', config.additionalAssetMetaDataMap); } - if (!_.isUndefined(props.additionalAssetMetaDataMap)) { - assert.isValidAssetMetaDataMap('props.additionalAssetMetaDataMap', props.additionalAssetMetaDataMap); + if (!_.isUndefined(config.defaultAssetBuyAmount)) { + assert.isNumber('defaultAssetBuyAmount', config.defaultAssetBuyAmount); } - if (!_.isUndefined(props.defaultAssetBuyAmount)) { - assert.isNumber('props.defaultAssetBuyAmount', props.defaultAssetBuyAmount); + if (!_.isUndefined(config.networkId)) { + assert.isNumber('networkId', config.networkId); } - if (!_.isUndefined(props.networkId)) { - assert.isNumber('props.networkId', props.networkId); + if (!_.isUndefined(config.availableAssetDatas)) { + assert.areValidAssetDatas('availableAssetDatas', config.availableAssetDatas); } - if (!_.isUndefined(props.availableAssetDatas)) { - assert.areValidAssetDatas('availableAssetDatas', props.availableAssetDatas); + if (!_.isUndefined(config.onClose)) { + assert.isFunction('onClose', config.onClose); } - if (!_.isUndefined(props.onClose)) { - assert.isFunction('props.onClose', props.onClose); + if (!_.isUndefined(config.zIndex)) { + assert.isNumber('zIndex', config.zIndex); } - if (!_.isUndefined(props.zIndex)) { - assert.isNumber('props.zIndex', props.zIndex); + if (!_.isUndefined(config.affiliateInfo)) { + assert.isValidAffiliateInfo('affiliateInfo', config.affiliateInfo); } - if (!_.isUndefined(props.affiliateInfo)) { - assert.isValidAffiliateInfo('props.affiliateInfo', props.affiliateInfo); + if (!_.isUndefined(config.provider)) { + assert.isWeb3Provider('provider', config.provider); } - if (!_.isUndefined(props.provider)) { - assert.isWeb3Provider('props.provider', props.provider); + if (!_.isUndefined(config.shouldDisablePushToHistory)) { + assert.isBoolean('shouldDisablePushToHistory', config.shouldDisablePushToHistory); } assert.isString('selector', selector); - const appendToIfExists = document.querySelector(selector); - assert.assert(!_.isNull(appendToIfExists), `Could not find div with selector: ${selector}`); - const appendTo = appendToIfExists as Element; - const injectedDiv = document.createElement('div'); - injectedDiv.setAttribute('id', INJECTED_DIV_ID); - injectedDiv.setAttribute('class', INJECTED_DIV_CLASS); - appendTo.appendChild(injectedDiv); - const instantOverlayProps = { - ...props, - onClose: () => { - appendTo.removeChild(injectedDiv); - if (!_.isUndefined(props.onClose)) { - props.onClose(); + // Render instant and return a callback that allows you to remove it from the DOM. + const renderInstant = () => { + const appendToIfExists = document.querySelector(selector); + assert.assert(!_.isNull(appendToIfExists), `Could not find div with selector: ${selector}`); + const appendTo = appendToIfExists as Element; + const injectedDiv = document.createElement('div'); + injectedDiv.setAttribute('id', INJECTED_DIV_ID); + injectedDiv.setAttribute('class', INJECTED_DIV_CLASS); + appendTo.appendChild(injectedDiv); + const closeInstant = () => { + if (!_.isUndefined(config.onClose)) { + config.onClose(); } - }, + appendTo.removeChild(injectedDiv); + }; + const instantOverlayProps = { + ...config, + // If we are using the history API, just go back to close + onClose: () => (config.shouldDisablePushToHistory ? closeInstant() : window.history.back()), + }; + ReactDOM.render(React.createElement(ZeroExInstantOverlay, instantOverlayProps), injectedDiv); + return closeInstant; }; - ReactDOM.render(React.createElement(ZeroExInstantOverlay, instantOverlayProps), injectedDiv); + if (config.shouldDisablePushToHistory) { + if (!isInstantRendered()) { + renderInstant(); + } + } else { + // Before we render, push to history saying that instant is showing for this part of the history. + window.history.pushState({ zeroExInstantShowing: true }, '0x Instant'); + let removeInstant = renderInstant(); + + let prevOnPopState = util.boundNoop; + if (window.onpopstate) { + prevOnPopState = window.onpopstate.bind(window); + } + window.onpopstate = (e: PopStateEvent) => { + // Don't override integrators handler. + prevOnPopState(e); + // e.state represents the new state + if (e.state && e.state.zeroExInstantShowing) { + // We have returned to a history state that expects instant to be rendered. + if (!isInstantRendered()) { + removeInstant = renderInstant(); + } + } else { + // History has changed to a different state. + if (isInstantRendered()) { + removeInstant(); + } + } + }; + } }; + +const isInstantRendered = (): boolean => !!document.getElementById(INJECTED_DIV_ID); |