@concord-consortium/lara-interactive-api 1.9.3-pre.7 → 1.9.3-pre.8

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 (2) hide show
  1. package/index.js +1919 -1919
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -1751,854 +1751,335 @@ module.exports = function deepFreeze (o) {
1751
1751
 
1752
1752
  /***/ }),
1753
1753
 
1754
- /***/ "./node_modules/iframe-phone/lib/iframe-endpoint.js":
1755
- /*!**********************************************************!*\
1756
- !*** ./node_modules/iframe-phone/lib/iframe-endpoint.js ***!
1757
- \**********************************************************/
1754
+ /***/ "./node_modules/process/browser.js":
1755
+ /*!*****************************************!*\
1756
+ !*** ./node_modules/process/browser.js ***!
1757
+ \*****************************************/
1758
1758
  /*! no static exports found */
1759
- /***/ (function(module, exports, __webpack_require__) {
1759
+ /***/ (function(module, exports) {
1760
1760
 
1761
- var structuredClone = __webpack_require__(/*! ./structured-clone */ "./node_modules/iframe-phone/lib/structured-clone.js");
1762
- var HELLO_INTERVAL_LENGTH = 200;
1763
- var HELLO_TIMEOUT_LENGTH = 60000;
1761
+ // shim for using process in browser
1762
+ var process = module.exports = {};
1764
1763
 
1765
- function IFrameEndpoint() {
1766
- var listeners = {};
1767
- var isInitialized = false;
1768
- var connected = false;
1769
- var postMessageQueue = [];
1770
- var helloInterval;
1764
+ // cached from whatever global is present so that test runners that stub it
1765
+ // don't break things. But we need to wrap it in a try catch in case it is
1766
+ // wrapped in strict mode code which doesn't define any globals. It's inside a
1767
+ // function because try/catches deoptimize in certain engines.
1771
1768
 
1772
- function postToParent(message) {
1773
- // See http://dev.opera.com/articles/view/window-postmessage-messagechannel/#crossdoc
1774
- // https://github.com/Modernizr/Modernizr/issues/388
1775
- // http://jsfiddle.net/ryanseddon/uZTgD/2/
1776
- if (structuredClone.supported()) {
1777
- window.parent.postMessage(message, '*');
1778
- } else {
1779
- window.parent.postMessage(JSON.stringify(message), '*');
1780
- }
1781
- }
1769
+ var cachedSetTimeout;
1770
+ var cachedClearTimeout;
1782
1771
 
1783
- function post(type, content) {
1784
- var message;
1785
- // Message object can be constructed from 'type' and 'content' arguments or it can be passed
1786
- // as the first argument.
1787
- if (arguments.length === 1 && typeof type === 'object' && typeof type.type === 'string') {
1788
- message = type;
1789
- } else {
1790
- message = {
1791
- type: type,
1792
- content: content
1793
- };
1772
+ function defaultSetTimout() {
1773
+ throw new Error('setTimeout has not been defined');
1774
+ }
1775
+ function defaultClearTimeout () {
1776
+ throw new Error('clearTimeout has not been defined');
1777
+ }
1778
+ (function () {
1779
+ try {
1780
+ if (typeof setTimeout === 'function') {
1781
+ cachedSetTimeout = setTimeout;
1782
+ } else {
1783
+ cachedSetTimeout = defaultSetTimout;
1784
+ }
1785
+ } catch (e) {
1786
+ cachedSetTimeout = defaultSetTimout;
1794
1787
  }
1795
- if (connected) {
1796
- postToParent(message);
1797
- } else {
1798
- postMessageQueue.push(message);
1788
+ try {
1789
+ if (typeof clearTimeout === 'function') {
1790
+ cachedClearTimeout = clearTimeout;
1791
+ } else {
1792
+ cachedClearTimeout = defaultClearTimeout;
1793
+ }
1794
+ } catch (e) {
1795
+ cachedClearTimeout = defaultClearTimeout;
1796
+ }
1797
+ } ())
1798
+ function runTimeout(fun) {
1799
+ if (cachedSetTimeout === setTimeout) {
1800
+ //normal enviroments in sane situations
1801
+ return setTimeout(fun, 0);
1802
+ }
1803
+ // if setTimeout wasn't available but was latter defined
1804
+ if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {
1805
+ cachedSetTimeout = setTimeout;
1806
+ return setTimeout(fun, 0);
1807
+ }
1808
+ try {
1809
+ // when when somebody has screwed with setTimeout but no I.E. maddness
1810
+ return cachedSetTimeout(fun, 0);
1811
+ } catch(e){
1812
+ try {
1813
+ // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
1814
+ return cachedSetTimeout.call(null, fun, 0);
1815
+ } catch(e){
1816
+ // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error
1817
+ return cachedSetTimeout.call(this, fun, 0);
1818
+ }
1799
1819
  }
1800
- }
1801
-
1802
- function postHello() {
1803
- postToParent({
1804
- type: 'hello'
1805
- });
1806
- }
1807
1820
 
1808
- function addListener(type, fn) {
1809
- listeners[type] = fn;
1810
- }
1811
1821
 
1812
- function removeListener(type) {
1813
- delete listeners[type];
1814
- }
1822
+ }
1823
+ function runClearTimeout(marker) {
1824
+ if (cachedClearTimeout === clearTimeout) {
1825
+ //normal enviroments in sane situations
1826
+ return clearTimeout(marker);
1827
+ }
1828
+ // if clearTimeout wasn't available but was latter defined
1829
+ if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {
1830
+ cachedClearTimeout = clearTimeout;
1831
+ return clearTimeout(marker);
1832
+ }
1833
+ try {
1834
+ // when when somebody has screwed with setTimeout but no I.E. maddness
1835
+ return cachedClearTimeout(marker);
1836
+ } catch (e){
1837
+ try {
1838
+ // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
1839
+ return cachedClearTimeout.call(null, marker);
1840
+ } catch (e){
1841
+ // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.
1842
+ // Some versions of I.E. have different rules for clearTimeout vs setTimeout
1843
+ return cachedClearTimeout.call(this, marker);
1844
+ }
1845
+ }
1815
1846
 
1816
- function removeAllListeners() {
1817
- listeners = {};
1818
- }
1819
1847
 
1820
- function getListenerNames() {
1821
- return Object.keys(listeners);
1822
- }
1823
1848
 
1824
- function messageListener(message) {
1825
- // Anyone can send us a message. Only pay attention to messages from parent.
1826
- if (message.source !== window.parent) return;
1827
- var messageData = message.data;
1828
- if (typeof messageData === 'string') messageData = JSON.parse(messageData);
1849
+ }
1850
+ var queue = [];
1851
+ var draining = false;
1852
+ var currentQueue;
1853
+ var queueIndex = -1;
1829
1854
 
1830
- if (!connected && messageData.type === 'hello') {
1831
- connected = true;
1832
- stopPostingHello();
1833
- while (postMessageQueue.length > 0) {
1834
- post(postMessageQueue.shift());
1835
- }
1855
+ function cleanUpNextTick() {
1856
+ if (!draining || !currentQueue) {
1857
+ return;
1836
1858
  }
1837
-
1838
- if (connected && listeners[messageData.type]) {
1839
- listeners[messageData.type](messageData.content);
1859
+ draining = false;
1860
+ if (currentQueue.length) {
1861
+ queue = currentQueue.concat(queue);
1862
+ } else {
1863
+ queueIndex = -1;
1840
1864
  }
1841
- }
1842
-
1843
- function disconnect() {
1844
- connected = false;
1845
- stopPostingHello();
1846
- removeAllListeners();
1847
- window.removeEventListener('message', messageListener);
1848
- }
1849
-
1850
- /**
1851
- Initialize communication with the parent frame. This should not be called until the app's custom
1852
- listeners are registered (via our 'addListener' public method) because, once we open the
1853
- communication, the parent window may send any messages it may have queued. Messages for which
1854
- we don't have handlers will be silently ignored.
1855
- */
1856
- function initialize() {
1857
- if (isInitialized) {
1858
- return;
1865
+ if (queue.length) {
1866
+ drainQueue();
1859
1867
  }
1860
- isInitialized = true;
1861
- if (window.parent === window) return;
1862
-
1863
- // We kick off communication with the parent window by sending a "hello" message. Then we wait
1864
- // for a handshake (another "hello" message) from the parent window.
1865
- startPostingHello();
1866
- window.addEventListener('message', messageListener, false);
1867
- }
1868
+ }
1868
1869
 
1869
- function startPostingHello() {
1870
- if (helloInterval) {
1871
- stopPostingHello();
1870
+ function drainQueue() {
1871
+ if (draining) {
1872
+ return;
1872
1873
  }
1873
- helloInterval = window.setInterval(postHello, HELLO_INTERVAL_LENGTH);
1874
- window.setTimeout(stopPostingHello, HELLO_TIMEOUT_LENGTH);
1875
- // Post the first msg immediately.
1876
- postHello();
1877
- }
1878
-
1879
- function stopPostingHello() {
1880
- window.clearInterval(helloInterval);
1881
- helloInterval = null;
1882
- }
1874
+ var timeout = runTimeout(cleanUpNextTick);
1875
+ draining = true;
1883
1876
 
1884
- // Public API.
1885
- return {
1886
- initialize: initialize,
1887
- getListenerNames: getListenerNames,
1888
- addListener: addListener,
1889
- removeListener: removeListener,
1890
- removeAllListeners: removeAllListeners,
1891
- disconnect: disconnect,
1892
- post: post
1893
- };
1877
+ var len = queue.length;
1878
+ while(len) {
1879
+ currentQueue = queue;
1880
+ queue = [];
1881
+ while (++queueIndex < len) {
1882
+ if (currentQueue) {
1883
+ currentQueue[queueIndex].run();
1884
+ }
1885
+ }
1886
+ queueIndex = -1;
1887
+ len = queue.length;
1888
+ }
1889
+ currentQueue = null;
1890
+ draining = false;
1891
+ runClearTimeout(timeout);
1894
1892
  }
1895
1893
 
1896
- var instance = null;
1897
-
1898
- // IFrameEndpoint is a singleton, as iframe can't have multiple parents anyway.
1899
- module.exports = function getIFrameEndpoint() {
1900
- if (!instance) {
1901
- instance = new IFrameEndpoint();
1902
- }
1903
- return instance;
1894
+ process.nextTick = function (fun) {
1895
+ var args = new Array(arguments.length - 1);
1896
+ if (arguments.length > 1) {
1897
+ for (var i = 1; i < arguments.length; i++) {
1898
+ args[i - 1] = arguments[i];
1899
+ }
1900
+ }
1901
+ queue.push(new Item(fun, args));
1902
+ if (queue.length === 1 && !draining) {
1903
+ runTimeout(drainQueue);
1904
+ }
1904
1905
  };
1905
1906
 
1906
-
1907
- /***/ }),
1908
-
1909
- /***/ "./node_modules/iframe-phone/lib/iframe-phone-rpc-endpoint.js":
1910
- /*!********************************************************************!*\
1911
- !*** ./node_modules/iframe-phone/lib/iframe-phone-rpc-endpoint.js ***!
1912
- \********************************************************************/
1913
- /*! no static exports found */
1914
- /***/ (function(module, exports, __webpack_require__) {
1915
-
1916
- var ParentEndpoint = __webpack_require__(/*! ./parent-endpoint */ "./node_modules/iframe-phone/lib/parent-endpoint.js");
1917
- var getIFrameEndpoint = __webpack_require__(/*! ./iframe-endpoint */ "./node_modules/iframe-phone/lib/iframe-endpoint.js");
1918
-
1919
- // Not a real UUID as there's an RFC for that (needed for proper distributed computing).
1920
- // But in this fairly parochial situation, we just need to be fairly sure to avoid repeats.
1921
- function getPseudoUUID() {
1922
- var chars = 'abcdefghijklmnopqrstuvwxyz0123456789';
1923
- var len = chars.length;
1924
- var ret = [];
1925
-
1926
- for (var i = 0; i < 10; i++) {
1927
- ret.push(chars[Math.floor(Math.random() * len)]);
1928
- }
1929
- return ret.join('');
1907
+ // v8 likes predictible objects
1908
+ function Item(fun, array) {
1909
+ this.fun = fun;
1910
+ this.array = array;
1930
1911
  }
1912
+ Item.prototype.run = function () {
1913
+ this.fun.apply(null, this.array);
1914
+ };
1915
+ process.title = 'browser';
1916
+ process.browser = true;
1917
+ process.env = {};
1918
+ process.argv = [];
1919
+ process.version = ''; // empty string to avoid regexp issues
1920
+ process.versions = {};
1931
1921
 
1932
- module.exports = function IframePhoneRpcEndpoint(handler, namespace, targetWindow, targetOrigin, phone) {
1933
- var pendingCallbacks = Object.create({});
1934
-
1935
- // if it's a non-null object, rather than a function, 'handler' is really an options object
1936
- if (handler && typeof handler === 'object') {
1937
- namespace = handler.namespace;
1938
- targetWindow = handler.targetWindow;
1939
- targetOrigin = handler.targetOrigin;
1940
- phone = handler.phone;
1941
- handler = handler.handler;
1942
- }
1943
-
1944
- if (!phone) {
1945
- if (targetWindow === window.parent) {
1946
- phone = getIFrameEndpoint();
1947
- phone.initialize();
1948
- } else {
1949
- phone = new ParentEndpoint(targetWindow, targetOrigin);
1950
- }
1951
- }
1952
-
1953
- phone.addListener(namespace, function (message) {
1954
- var callbackObj;
1955
-
1956
- if (message.messageType === 'call' && typeof this.handler === 'function') {
1957
- this.handler.call(undefined, message.value, function (returnValue) {
1958
- phone.post(namespace, {
1959
- messageType: 'returnValue',
1960
- uuid: message.uuid,
1961
- value: returnValue
1962
- });
1963
- });
1964
- } else if (message.messageType === 'returnValue') {
1965
- callbackObj = pendingCallbacks[message.uuid];
1966
-
1967
- if (callbackObj) {
1968
- window.clearTimeout(callbackObj.timeout);
1969
- if (callbackObj.callback) {
1970
- callbackObj.callback.call(undefined, message.value);
1971
- }
1972
- pendingCallbacks[message.uuid] = null;
1973
- }
1974
- }
1975
- }.bind(this));
1976
-
1977
- function call(message, callback) {
1978
- var uuid = getPseudoUUID();
1922
+ function noop() {}
1979
1923
 
1980
- pendingCallbacks[uuid] = {
1981
- callback: callback,
1982
- timeout: window.setTimeout(function () {
1983
- if (callback) {
1984
- callback(undefined, new Error("IframePhone timed out waiting for reply"));
1985
- }
1986
- }, 2000)
1987
- };
1924
+ process.on = noop;
1925
+ process.addListener = noop;
1926
+ process.once = noop;
1927
+ process.off = noop;
1928
+ process.removeListener = noop;
1929
+ process.removeAllListeners = noop;
1930
+ process.emit = noop;
1931
+ process.prependListener = noop;
1932
+ process.prependOnceListener = noop;
1988
1933
 
1989
- phone.post(namespace, {
1990
- messageType: 'call',
1991
- uuid: uuid,
1992
- value: message
1993
- });
1994
- }
1934
+ process.listeners = function (name) { return [] }
1995
1935
 
1996
- function disconnect() {
1997
- phone.disconnect();
1998
- }
1936
+ process.binding = function (name) {
1937
+ throw new Error('process.binding is not supported');
1938
+ };
1999
1939
 
2000
- this.handler = handler;
2001
- this.call = call.bind(this);
2002
- this.disconnect = disconnect.bind(this);
1940
+ process.cwd = function () { return '/' };
1941
+ process.chdir = function (dir) {
1942
+ throw new Error('process.chdir is not supported');
2003
1943
  };
1944
+ process.umask = function() { return 0; };
2004
1945
 
2005
1946
 
2006
1947
  /***/ }),
2007
1948
 
2008
- /***/ "./node_modules/iframe-phone/lib/parent-endpoint.js":
2009
- /*!**********************************************************!*\
2010
- !*** ./node_modules/iframe-phone/lib/parent-endpoint.js ***!
2011
- \**********************************************************/
2012
- /*! no static exports found */
2013
- /***/ (function(module, exports, __webpack_require__) {
2014
-
2015
- var structuredClone = __webpack_require__(/*! ./structured-clone */ "./node_modules/iframe-phone/lib/structured-clone.js");
1949
+ /***/ "./node_modules/resize-observer-polyfill/dist/ResizeObserver.es.js":
1950
+ /*!*************************************************************************!*\
1951
+ !*** ./node_modules/resize-observer-polyfill/dist/ResizeObserver.es.js ***!
1952
+ \*************************************************************************/
1953
+ /*! exports provided: default */
1954
+ /***/ (function(module, __webpack_exports__, __webpack_require__) {
2016
1955
 
2017
- /**
2018
- Call as:
2019
- new ParentEndpoint(targetWindow, targetOrigin, afterConnectedCallback)
2020
- targetWindow is a WindowProxy object. (Messages will be sent to it)
1956
+ "use strict";
1957
+ __webpack_require__.r(__webpack_exports__);
1958
+ /* WEBPACK VAR INJECTION */(function(global) {/**
1959
+ * A collection of shims that provide minimal functionality of the ES6 collections.
1960
+ *
1961
+ * These implementations are not meant to be used outside of the ResizeObserver
1962
+ * modules as they cover only a limited range of use cases.
1963
+ */
1964
+ /* eslint-disable require-jsdoc, valid-jsdoc */
1965
+ var MapShim = (function () {
1966
+ if (typeof Map !== 'undefined') {
1967
+ return Map;
1968
+ }
1969
+ /**
1970
+ * Returns index in provided array that matches the specified key.
1971
+ *
1972
+ * @param {Array<Array>} arr
1973
+ * @param {*} key
1974
+ * @returns {number}
1975
+ */
1976
+ function getIndex(arr, key) {
1977
+ var result = -1;
1978
+ arr.some(function (entry, index) {
1979
+ if (entry[0] === key) {
1980
+ result = index;
1981
+ return true;
1982
+ }
1983
+ return false;
1984
+ });
1985
+ return result;
1986
+ }
1987
+ return /** @class */ (function () {
1988
+ function class_1() {
1989
+ this.__entries__ = [];
1990
+ }
1991
+ Object.defineProperty(class_1.prototype, "size", {
1992
+ /**
1993
+ * @returns {boolean}
1994
+ */
1995
+ get: function () {
1996
+ return this.__entries__.length;
1997
+ },
1998
+ enumerable: true,
1999
+ configurable: true
2000
+ });
2001
+ /**
2002
+ * @param {*} key
2003
+ * @returns {*}
2004
+ */
2005
+ class_1.prototype.get = function (key) {
2006
+ var index = getIndex(this.__entries__, key);
2007
+ var entry = this.__entries__[index];
2008
+ return entry && entry[1];
2009
+ };
2010
+ /**
2011
+ * @param {*} key
2012
+ * @param {*} value
2013
+ * @returns {void}
2014
+ */
2015
+ class_1.prototype.set = function (key, value) {
2016
+ var index = getIndex(this.__entries__, key);
2017
+ if (~index) {
2018
+ this.__entries__[index][1] = value;
2019
+ }
2020
+ else {
2021
+ this.__entries__.push([key, value]);
2022
+ }
2023
+ };
2024
+ /**
2025
+ * @param {*} key
2026
+ * @returns {void}
2027
+ */
2028
+ class_1.prototype.delete = function (key) {
2029
+ var entries = this.__entries__;
2030
+ var index = getIndex(entries, key);
2031
+ if (~index) {
2032
+ entries.splice(index, 1);
2033
+ }
2034
+ };
2035
+ /**
2036
+ * @param {*} key
2037
+ * @returns {void}
2038
+ */
2039
+ class_1.prototype.has = function (key) {
2040
+ return !!~getIndex(this.__entries__, key);
2041
+ };
2042
+ /**
2043
+ * @returns {void}
2044
+ */
2045
+ class_1.prototype.clear = function () {
2046
+ this.__entries__.splice(0);
2047
+ };
2048
+ /**
2049
+ * @param {Function} callback
2050
+ * @param {*} [ctx=null]
2051
+ * @returns {void}
2052
+ */
2053
+ class_1.prototype.forEach = function (callback, ctx) {
2054
+ if (ctx === void 0) { ctx = null; }
2055
+ for (var _i = 0, _a = this.__entries__; _i < _a.length; _i++) {
2056
+ var entry = _a[_i];
2057
+ callback.call(ctx, entry[1], entry[0]);
2058
+ }
2059
+ };
2060
+ return class_1;
2061
+ }());
2062
+ })();
2021
2063
 
2022
- targetOrigin is the origin of the targetWindow. (Messages will be restricted to this origin)
2064
+ /**
2065
+ * Detects whether window and document objects are available in current environment.
2066
+ */
2067
+ var isBrowser = typeof window !== 'undefined' && typeof document !== 'undefined' && window.document === document;
2023
2068
 
2024
- afterConnectedCallback is an optional callback function to be called when the connection is
2025
- established.
2026
-
2027
- OR (less secure):
2028
- new ParentEndpoint(targetIframe, afterConnectedCallback)
2029
-
2030
- targetIframe is a DOM object (HTMLIframeElement); messages will be sent to its contentWindow.
2031
-
2032
- afterConnectedCallback is an optional callback function
2033
-
2034
- In this latter case, targetOrigin will be inferred from the value of the src attribute of the
2035
- provided DOM object at the time of the constructor invocation. This is less secure because the
2036
- iframe might have been navigated to an unexpected domain before constructor invocation.
2037
-
2038
- Note that it is important to specify the expected origin of the iframe's content to safeguard
2039
- against sending messages to an unexpected domain. This might happen if our iframe is navigated to
2040
- a third-party URL unexpectedly. Furthermore, having a reference to Window object (as in the first
2041
- form of the constructor) does not protect against sending a message to the wrong domain. The
2042
- window object is actualy a WindowProxy which transparently proxies the Window object of the
2043
- underlying iframe, so that when the iframe is navigated, the "same" WindowProxy now references a
2044
- completely differeent Window object, possibly controlled by a hostile domain.
2045
-
2046
- See http://www.esdiscuss.org/topic/a-dom-use-case-that-can-t-be-emulated-with-direct-proxies for
2047
- more about this weird behavior of WindowProxies (the type returned by <iframe>.contentWindow).
2048
- */
2049
-
2050
- module.exports = function ParentEndpoint(targetWindowOrIframeEl, targetOrigin, afterConnectedCallback) {
2051
- var postMessageQueue = [];
2052
- var connected = false;
2053
- var handlers = {};
2054
- var targetWindowIsIframeElement;
2055
-
2056
- function getIframeOrigin(iframe) {
2057
- return iframe.src.match(/(.*?\/\/.*?)\//)[1];
2058
- }
2059
-
2060
- function post(type, content) {
2061
- var message;
2062
- // Message object can be constructed from 'type' and 'content' arguments or it can be passed
2063
- // as the first argument.
2064
- if (arguments.length === 1 && typeof type === 'object' && typeof type.type === 'string') {
2065
- message = type;
2066
- } else {
2067
- message = {
2068
- type: type,
2069
- content: content
2070
- };
2071
- }
2072
- if (connected) {
2073
- var tWindow = getTargetWindow();
2074
- // if we are laready connected ... send the message
2075
- // See http://dev.opera.com/articles/view/window-postmessage-messagechannel/#crossdoc
2076
- // https://github.com/Modernizr/Modernizr/issues/388
2077
- // http://jsfiddle.net/ryanseddon/uZTgD/2/
2078
- if (structuredClone.supported()) {
2079
- tWindow.postMessage(message, targetOrigin);
2080
- } else {
2081
- tWindow.postMessage(JSON.stringify(message), targetOrigin);
2082
- }
2083
- } else {
2084
- // else queue up the messages to send after connection complete.
2085
- postMessageQueue.push(message);
2086
- }
2087
- }
2088
-
2089
- function addListener(messageName, func) {
2090
- handlers[messageName] = func;
2091
- }
2092
-
2093
- function removeListener(messageName) {
2094
- delete handlers[messageName];
2095
- }
2096
-
2097
- function removeAllListeners() {
2098
- handlers = {};
2099
- }
2100
-
2101
- // Note that this function can't be used when IFrame element hasn't been added to DOM yet
2102
- // (.contentWindow would be null). At the moment risk is purely theoretical, as the parent endpoint
2103
- // only listens for an incoming 'hello' message and the first time we call this function
2104
- // is in #receiveMessage handler (so iframe had to be initialized before, as it could send 'hello').
2105
- // It would become important when we decide to refactor the way how communication is initialized.
2106
- function getTargetWindow() {
2107
- if (targetWindowIsIframeElement) {
2108
- var tWindow = targetWindowOrIframeEl.contentWindow;
2109
- if (!tWindow) {
2110
- throw "IFrame element needs to be added to DOM before communication " +
2111
- "can be started (.contentWindow is not available)";
2112
- }
2113
- return tWindow;
2114
- }
2115
- return targetWindowOrIframeEl;
2116
- }
2117
-
2118
- function receiveMessage(message) {
2119
- var messageData;
2120
- if (message.source === getTargetWindow() && (targetOrigin === '*' || message.origin === targetOrigin)) {
2121
- messageData = message.data;
2122
- if (typeof messageData === 'string') {
2123
- messageData = JSON.parse(messageData);
2124
- }
2125
- if (handlers[messageData.type]) {
2126
- handlers[messageData.type](messageData.content);
2127
- } else {
2128
- console.log("cant handle type: " + messageData.type);
2129
- }
2130
- }
2131
- }
2132
-
2133
- function disconnect() {
2134
- connected = false;
2135
- removeAllListeners();
2136
- window.removeEventListener('message', receiveMessage);
2137
- }
2138
-
2139
- // handle the case that targetWindowOrIframeEl is actually an <iframe> rather than a Window(Proxy) object
2140
- // Note that if it *is* a WindowProxy, this probe will throw a SecurityException, but in that case
2141
- // we also don't need to do anything
2142
- try {
2143
- targetWindowIsIframeElement = targetWindowOrIframeEl.constructor === HTMLIFrameElement;
2144
- } catch (e) {
2145
- targetWindowIsIframeElement = false;
2146
- }
2147
-
2148
- if (targetWindowIsIframeElement) {
2149
- // Infer the origin ONLY if the user did not supply an explicit origin, i.e., if the second
2150
- // argument is empty or is actually a callback (meaning it is supposed to be the
2151
- // afterConnectionCallback)
2152
- if (!targetOrigin || targetOrigin.constructor === Function) {
2153
- afterConnectedCallback = targetOrigin;
2154
- targetOrigin = getIframeOrigin(targetWindowOrIframeEl);
2155
- }
2156
- }
2157
-
2158
- // Handle pages served through file:// protocol. Behaviour varies in different browsers. Safari sets origin
2159
- // to 'file://' and everything works fine, but Chrome and Safari set message.origin to null.
2160
- // Also, https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage says:
2161
- // > Lastly, posting a message to a page at a file: URL currently requires that the targetOrigin argument be "*".
2162
- // > file:// cannot be used as a security restriction; this restriction may be modified in the future.
2163
- // So, using '*' seems like the only possible solution.
2164
- if (targetOrigin === 'file://') {
2165
- targetOrigin = '*';
2166
- }
2167
-
2168
- // when we receive 'hello':
2169
- addListener('hello', function () {
2170
- connected = true;
2171
-
2172
- // send hello response
2173
- post({
2174
- type: 'hello',
2175
- // `origin` property isn't used by IframeEndpoint anymore (>= 1.2.0), but it's being sent to be
2176
- // backward compatible with old IframeEndpoint versions (< v1.2.0).
2177
- origin: window.location.href.match(/(.*?\/\/.*?)\//)[1]
2178
- });
2179
-
2180
- // give the user a chance to do things now that we are connected
2181
- // note that is will happen before any queued messages
2182
- if (afterConnectedCallback && typeof afterConnectedCallback === "function") {
2183
- afterConnectedCallback();
2184
- }
2185
-
2186
- // Now send any messages that have been queued up ...
2187
- while (postMessageQueue.length > 0) {
2188
- post(postMessageQueue.shift());
2189
- }
2190
- });
2191
-
2192
- window.addEventListener('message', receiveMessage, false);
2193
-
2194
- // Public API.
2195
- return {
2196
- post: post,
2197
- addListener: addListener,
2198
- removeListener: removeListener,
2199
- removeAllListeners: removeAllListeners,
2200
- disconnect: disconnect,
2201
- getTargetWindow: getTargetWindow,
2202
- targetOrigin: targetOrigin
2203
- };
2204
- };
2205
-
2206
-
2207
- /***/ }),
2208
-
2209
- /***/ "./node_modules/iframe-phone/lib/structured-clone.js":
2210
- /*!***********************************************************!*\
2211
- !*** ./node_modules/iframe-phone/lib/structured-clone.js ***!
2212
- \***********************************************************/
2213
- /*! no static exports found */
2214
- /***/ (function(module, exports) {
2215
-
2216
- var featureSupported = {
2217
- 'structuredClones': 0
2218
- };
2219
-
2220
- (function () {
2221
- var result = 0;
2222
-
2223
- if (!!window.postMessage) {
2224
- try {
2225
- // Spec states you can't transmit DOM nodes and it will throw an error
2226
- // postMessage implementations that support cloned data will throw.
2227
- window.postMessage(document.createElement("a"), "*");
2228
- } catch (e) {
2229
- // BBOS6 throws but doesn't pass through the correct exception
2230
- // so check error message
2231
- result = (e.DATA_CLONE_ERR || e.message === "Cannot post cyclic structures.") ? 1 : 0;
2232
- featureSupported = {
2233
- 'structuredClones': result
2234
- };
2235
- }
2236
- }
2237
- }());
2238
-
2239
- exports.supported = function supported() {
2240
- return featureSupported && featureSupported.structuredClones > 0;
2241
- };
2242
-
2243
-
2244
- /***/ }),
2245
-
2246
- /***/ "./node_modules/iframe-phone/main.js":
2247
- /*!*******************************************!*\
2248
- !*** ./node_modules/iframe-phone/main.js ***!
2249
- \*******************************************/
2250
- /*! no static exports found */
2251
- /***/ (function(module, exports, __webpack_require__) {
2252
-
2253
- module.exports = {
2254
- /**
2255
- * Allows to communicate with an iframe.
2256
- */
2257
- ParentEndpoint: __webpack_require__(/*! ./lib/parent-endpoint */ "./node_modules/iframe-phone/lib/parent-endpoint.js"),
2258
- /**
2259
- * Allows to communicate with a parent page.
2260
- * IFrameEndpoint is a singleton, as iframe can't have multiple parents anyway.
2261
- */
2262
- getIFrameEndpoint: __webpack_require__(/*! ./lib/iframe-endpoint */ "./node_modules/iframe-phone/lib/iframe-endpoint.js"),
2263
- structuredClone: __webpack_require__(/*! ./lib/structured-clone */ "./node_modules/iframe-phone/lib/structured-clone.js"),
2264
-
2265
- // TODO: May be misnamed
2266
- IframePhoneRpcEndpoint: __webpack_require__(/*! ./lib/iframe-phone-rpc-endpoint */ "./node_modules/iframe-phone/lib/iframe-phone-rpc-endpoint.js")
2267
-
2268
- };
2269
-
2270
-
2271
- /***/ }),
2272
-
2273
- /***/ "./node_modules/process/browser.js":
2274
- /*!*****************************************!*\
2275
- !*** ./node_modules/process/browser.js ***!
2276
- \*****************************************/
2277
- /*! no static exports found */
2278
- /***/ (function(module, exports) {
2279
-
2280
- // shim for using process in browser
2281
- var process = module.exports = {};
2282
-
2283
- // cached from whatever global is present so that test runners that stub it
2284
- // don't break things. But we need to wrap it in a try catch in case it is
2285
- // wrapped in strict mode code which doesn't define any globals. It's inside a
2286
- // function because try/catches deoptimize in certain engines.
2287
-
2288
- var cachedSetTimeout;
2289
- var cachedClearTimeout;
2290
-
2291
- function defaultSetTimout() {
2292
- throw new Error('setTimeout has not been defined');
2293
- }
2294
- function defaultClearTimeout () {
2295
- throw new Error('clearTimeout has not been defined');
2296
- }
2297
- (function () {
2298
- try {
2299
- if (typeof setTimeout === 'function') {
2300
- cachedSetTimeout = setTimeout;
2301
- } else {
2302
- cachedSetTimeout = defaultSetTimout;
2303
- }
2304
- } catch (e) {
2305
- cachedSetTimeout = defaultSetTimout;
2306
- }
2307
- try {
2308
- if (typeof clearTimeout === 'function') {
2309
- cachedClearTimeout = clearTimeout;
2310
- } else {
2311
- cachedClearTimeout = defaultClearTimeout;
2312
- }
2313
- } catch (e) {
2314
- cachedClearTimeout = defaultClearTimeout;
2315
- }
2316
- } ())
2317
- function runTimeout(fun) {
2318
- if (cachedSetTimeout === setTimeout) {
2319
- //normal enviroments in sane situations
2320
- return setTimeout(fun, 0);
2321
- }
2322
- // if setTimeout wasn't available but was latter defined
2323
- if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {
2324
- cachedSetTimeout = setTimeout;
2325
- return setTimeout(fun, 0);
2326
- }
2327
- try {
2328
- // when when somebody has screwed with setTimeout but no I.E. maddness
2329
- return cachedSetTimeout(fun, 0);
2330
- } catch(e){
2331
- try {
2332
- // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
2333
- return cachedSetTimeout.call(null, fun, 0);
2334
- } catch(e){
2335
- // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error
2336
- return cachedSetTimeout.call(this, fun, 0);
2337
- }
2338
- }
2339
-
2340
-
2341
- }
2342
- function runClearTimeout(marker) {
2343
- if (cachedClearTimeout === clearTimeout) {
2344
- //normal enviroments in sane situations
2345
- return clearTimeout(marker);
2346
- }
2347
- // if clearTimeout wasn't available but was latter defined
2348
- if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {
2349
- cachedClearTimeout = clearTimeout;
2350
- return clearTimeout(marker);
2351
- }
2352
- try {
2353
- // when when somebody has screwed with setTimeout but no I.E. maddness
2354
- return cachedClearTimeout(marker);
2355
- } catch (e){
2356
- try {
2357
- // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
2358
- return cachedClearTimeout.call(null, marker);
2359
- } catch (e){
2360
- // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.
2361
- // Some versions of I.E. have different rules for clearTimeout vs setTimeout
2362
- return cachedClearTimeout.call(this, marker);
2363
- }
2364
- }
2365
-
2366
-
2367
-
2368
- }
2369
- var queue = [];
2370
- var draining = false;
2371
- var currentQueue;
2372
- var queueIndex = -1;
2373
-
2374
- function cleanUpNextTick() {
2375
- if (!draining || !currentQueue) {
2376
- return;
2377
- }
2378
- draining = false;
2379
- if (currentQueue.length) {
2380
- queue = currentQueue.concat(queue);
2381
- } else {
2382
- queueIndex = -1;
2383
- }
2384
- if (queue.length) {
2385
- drainQueue();
2386
- }
2387
- }
2388
-
2389
- function drainQueue() {
2390
- if (draining) {
2391
- return;
2392
- }
2393
- var timeout = runTimeout(cleanUpNextTick);
2394
- draining = true;
2395
-
2396
- var len = queue.length;
2397
- while(len) {
2398
- currentQueue = queue;
2399
- queue = [];
2400
- while (++queueIndex < len) {
2401
- if (currentQueue) {
2402
- currentQueue[queueIndex].run();
2403
- }
2404
- }
2405
- queueIndex = -1;
2406
- len = queue.length;
2407
- }
2408
- currentQueue = null;
2409
- draining = false;
2410
- runClearTimeout(timeout);
2411
- }
2412
-
2413
- process.nextTick = function (fun) {
2414
- var args = new Array(arguments.length - 1);
2415
- if (arguments.length > 1) {
2416
- for (var i = 1; i < arguments.length; i++) {
2417
- args[i - 1] = arguments[i];
2418
- }
2419
- }
2420
- queue.push(new Item(fun, args));
2421
- if (queue.length === 1 && !draining) {
2422
- runTimeout(drainQueue);
2423
- }
2424
- };
2425
-
2426
- // v8 likes predictible objects
2427
- function Item(fun, array) {
2428
- this.fun = fun;
2429
- this.array = array;
2430
- }
2431
- Item.prototype.run = function () {
2432
- this.fun.apply(null, this.array);
2433
- };
2434
- process.title = 'browser';
2435
- process.browser = true;
2436
- process.env = {};
2437
- process.argv = [];
2438
- process.version = ''; // empty string to avoid regexp issues
2439
- process.versions = {};
2440
-
2441
- function noop() {}
2442
-
2443
- process.on = noop;
2444
- process.addListener = noop;
2445
- process.once = noop;
2446
- process.off = noop;
2447
- process.removeListener = noop;
2448
- process.removeAllListeners = noop;
2449
- process.emit = noop;
2450
- process.prependListener = noop;
2451
- process.prependOnceListener = noop;
2452
-
2453
- process.listeners = function (name) { return [] }
2454
-
2455
- process.binding = function (name) {
2456
- throw new Error('process.binding is not supported');
2457
- };
2458
-
2459
- process.cwd = function () { return '/' };
2460
- process.chdir = function (dir) {
2461
- throw new Error('process.chdir is not supported');
2462
- };
2463
- process.umask = function() { return 0; };
2464
-
2465
-
2466
- /***/ }),
2467
-
2468
- /***/ "./node_modules/resize-observer-polyfill/dist/ResizeObserver.es.js":
2469
- /*!*************************************************************************!*\
2470
- !*** ./node_modules/resize-observer-polyfill/dist/ResizeObserver.es.js ***!
2471
- \*************************************************************************/
2472
- /*! exports provided: default */
2473
- /***/ (function(module, __webpack_exports__, __webpack_require__) {
2474
-
2475
- "use strict";
2476
- __webpack_require__.r(__webpack_exports__);
2477
- /* WEBPACK VAR INJECTION */(function(global) {/**
2478
- * A collection of shims that provide minimal functionality of the ES6 collections.
2479
- *
2480
- * These implementations are not meant to be used outside of the ResizeObserver
2481
- * modules as they cover only a limited range of use cases.
2482
- */
2483
- /* eslint-disable require-jsdoc, valid-jsdoc */
2484
- var MapShim = (function () {
2485
- if (typeof Map !== 'undefined') {
2486
- return Map;
2487
- }
2488
- /**
2489
- * Returns index in provided array that matches the specified key.
2490
- *
2491
- * @param {Array<Array>} arr
2492
- * @param {*} key
2493
- * @returns {number}
2494
- */
2495
- function getIndex(arr, key) {
2496
- var result = -1;
2497
- arr.some(function (entry, index) {
2498
- if (entry[0] === key) {
2499
- result = index;
2500
- return true;
2501
- }
2502
- return false;
2503
- });
2504
- return result;
2505
- }
2506
- return /** @class */ (function () {
2507
- function class_1() {
2508
- this.__entries__ = [];
2509
- }
2510
- Object.defineProperty(class_1.prototype, "size", {
2511
- /**
2512
- * @returns {boolean}
2513
- */
2514
- get: function () {
2515
- return this.__entries__.length;
2516
- },
2517
- enumerable: true,
2518
- configurable: true
2519
- });
2520
- /**
2521
- * @param {*} key
2522
- * @returns {*}
2523
- */
2524
- class_1.prototype.get = function (key) {
2525
- var index = getIndex(this.__entries__, key);
2526
- var entry = this.__entries__[index];
2527
- return entry && entry[1];
2528
- };
2529
- /**
2530
- * @param {*} key
2531
- * @param {*} value
2532
- * @returns {void}
2533
- */
2534
- class_1.prototype.set = function (key, value) {
2535
- var index = getIndex(this.__entries__, key);
2536
- if (~index) {
2537
- this.__entries__[index][1] = value;
2538
- }
2539
- else {
2540
- this.__entries__.push([key, value]);
2541
- }
2542
- };
2543
- /**
2544
- * @param {*} key
2545
- * @returns {void}
2546
- */
2547
- class_1.prototype.delete = function (key) {
2548
- var entries = this.__entries__;
2549
- var index = getIndex(entries, key);
2550
- if (~index) {
2551
- entries.splice(index, 1);
2552
- }
2553
- };
2554
- /**
2555
- * @param {*} key
2556
- * @returns {void}
2557
- */
2558
- class_1.prototype.has = function (key) {
2559
- return !!~getIndex(this.__entries__, key);
2560
- };
2561
- /**
2562
- * @returns {void}
2563
- */
2564
- class_1.prototype.clear = function () {
2565
- this.__entries__.splice(0);
2566
- };
2567
- /**
2568
- * @param {Function} callback
2569
- * @param {*} [ctx=null]
2570
- * @returns {void}
2571
- */
2572
- class_1.prototype.forEach = function (callback, ctx) {
2573
- if (ctx === void 0) { ctx = null; }
2574
- for (var _i = 0, _a = this.__entries__; _i < _a.length; _i++) {
2575
- var entry = _a[_i];
2576
- callback.call(ctx, entry[1], entry[0]);
2577
- }
2578
- };
2579
- return class_1;
2580
- }());
2581
- })();
2582
-
2583
- /**
2584
- * Detects whether window and document objects are available in current environment.
2585
- */
2586
- var isBrowser = typeof window !== 'undefined' && typeof document !== 'undefined' && window.document === document;
2587
-
2588
- // Returns global object of a current environment.
2589
- var global$1 = (function () {
2590
- if (typeof global !== 'undefined' && global.Math === Math) {
2591
- return global;
2592
- }
2593
- if (typeof self !== 'undefined' && self.Math === Math) {
2594
- return self;
2595
- }
2596
- if (typeof window !== 'undefined' && window.Math === Math) {
2597
- return window;
2598
- }
2599
- // eslint-disable-next-line no-new-func
2600
- return Function('return this')();
2601
- })();
2069
+ // Returns global object of a current environment.
2070
+ var global$1 = (function () {
2071
+ if (typeof global !== 'undefined' && global.Math === Math) {
2072
+ return global;
2073
+ }
2074
+ if (typeof self !== 'undefined' && self.Math === Math) {
2075
+ return self;
2076
+ }
2077
+ if (typeof window !== 'undefined' && window.Math === Math) {
2078
+ return window;
2079
+ }
2080
+ // eslint-disable-next-line no-new-func
2081
+ return Function('return this')();
2082
+ })();
2602
2083
 
2603
2084
  /**
2604
2085
  * A shim for the requestAnimationFrame which falls back to the setTimeout if
@@ -4568,1237 +4049,1756 @@ var __assign = (this && this.__assign) || function () {
4568
4049
  }
4569
4050
  return t;
4570
4051
  };
4571
- return __assign.apply(this, arguments);
4052
+ return __assign.apply(this, arguments);
4053
+ };
4054
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
4055
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4056
+ return new (P || (P = Promise))(function (resolve, reject) {
4057
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
4058
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
4059
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
4060
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
4061
+ });
4062
+ };
4063
+ var __generator = (this && this.__generator) || function (thisArg, body) {
4064
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
4065
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
4066
+ function verb(n) { return function (v) { return step([n, v]); }; }
4067
+ function step(op) {
4068
+ if (f) throw new TypeError("Generator is already executing.");
4069
+ while (_) try {
4070
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
4071
+ if (y = 0, t) op = [op[0] & 2, t.value];
4072
+ switch (op[0]) {
4073
+ case 0: case 1: t = op; break;
4074
+ case 4: _.label++; return { value: op[1], done: false };
4075
+ case 5: _.label++; y = op[1]; op = [0]; continue;
4076
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
4077
+ default:
4078
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
4079
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
4080
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
4081
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
4082
+ if (t[2]) _.ops.pop();
4083
+ _.trys.pop(); continue;
4084
+ }
4085
+ op = body.call(thisArg, _);
4086
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
4087
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
4088
+ }
4089
+ };
4090
+ var __rest = (this && this.__rest) || function (s, e) {
4091
+ var t = {};
4092
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
4093
+ t[p] = s[p];
4094
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
4095
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
4096
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
4097
+ t[p[i]] = s[p[i]];
4098
+ }
4099
+ return t;
4100
+ };
4101
+ Object.defineProperty(exports, "__esModule", { value: true });
4102
+ exports.sendCustomMessage = exports.setOnUnload = exports.sendReportItemAnswer = exports.getAttachmentUrl = exports.readAttachment = exports.writeAttachment = exports.getLibraryInteractiveList = exports.getInteractiveSnapshot = exports.setLinkedInteractives = exports.getInteractiveList = exports.closeModal = exports.showModal = exports.removeLinkedInteractiveStateListener = exports.addLinkedInteractiveStateListener = exports.removeGlobalInteractiveStateListener = exports.addGlobalInteractiveStateListener = exports.removeAuthoredStateListener = exports.addAuthoredStateListener = exports.removeInteractiveStateListener = exports.addInteractiveStateListener = exports.log = exports.getFirebaseJwt = exports.getAuthInfo = exports.setNavigation = exports.setHint = exports.postDecoratedContentEvent = exports.setHeight = exports.setSupportedFeatures = exports.notifyReportItemClientReady = exports.removeGetReportItemAnswerListener = exports.addGetReportItemAnswerListener = exports.removeDecorateContentListener = exports.addDecorateContentListener = exports.removeCustomMessageListener = exports.addCustomMessageListener = exports.setGlobalInteractiveState = exports.getGlobalInteractiveState = exports.setAuthoredState = exports.getAuthoredState = exports.flushStateUpdates = exports.setInteractiveState = exports.setInteractiveStateTimeout = exports.getInteractiveState = exports.getMode = exports.getInitInteractiveMessage = void 0;
4103
+ var client_1 = __webpack_require__(/*! ./client */ "./src/interactive-api-client/client.ts");
4104
+ var uuid_1 = __webpack_require__(/*! uuid */ "./node_modules/uuid/dist/esm-browser/index.js");
4105
+ var THROW_NOT_IMPLEMENTED_YET = function (method) {
4106
+ throw new Error(method + " is not yet implemented in the client!");
4107
+ };
4108
+ var getInitInteractiveMessage = function () {
4109
+ var client = (0, client_1.getClient)();
4110
+ return new Promise(function (resolve) {
4111
+ if (client.managedState.initMessage) {
4112
+ resolve(client.managedState.initMessage);
4113
+ }
4114
+ else {
4115
+ client.managedState.once("initInteractive", function () { return resolve(client.managedState.initMessage); });
4116
+ }
4117
+ });
4118
+ };
4119
+ exports.getInitInteractiveMessage = getInitInteractiveMessage;
4120
+ var getMode = function () {
4121
+ return (0, exports.getInitInteractiveMessage)().then(function (initInteractiveMessage) { return initInteractiveMessage === null || initInteractiveMessage === void 0 ? void 0 : initInteractiveMessage.mode; });
4122
+ };
4123
+ exports.getMode = getMode;
4124
+ var getInteractiveState = function () {
4125
+ return (0, client_1.getClient)().managedState.interactiveState;
4126
+ };
4127
+ exports.getInteractiveState = getInteractiveState;
4128
+ var setInteractiveStateTimeoutId;
4129
+ var delayedInteractiveStateUpdate = null;
4130
+ exports.setInteractiveStateTimeout = 2000; // ms
4131
+ /**
4132
+ * Note that state will become frozen and should never be mutated.
4133
+ * Each time you update state, make sure that a new object is passed.
4134
+ *
4135
+ * Good:
4136
+ * ```
4137
+ * setInteractiveState(Object.assign({}, previousState, {someProperty: "a new value"}));
4138
+ * // or
4139
+ * setInteractiveState({...previousState, someProperty: "a new value"});
4140
+ * ```
4141
+ *
4142
+ * Bad:
4143
+ * ```
4144
+ * previousState.someProperty = "a new value";
4145
+ * setInteractiveState(previousState);
4146
+ * ```
4147
+ */
4148
+ var setInteractiveState = function (newInteractiveState) {
4149
+ var client = (0, client_1.getClient)();
4150
+ client.managedState.interactiveState = newInteractiveState;
4151
+ window.clearTimeout(setInteractiveStateTimeoutId);
4152
+ delayedInteractiveStateUpdate = function () {
4153
+ client.post("interactiveState", newInteractiveState);
4154
+ client.managedState.interactiveStateDirty = false;
4155
+ delayedInteractiveStateUpdate = null;
4156
+ };
4157
+ setInteractiveStateTimeoutId = window.setTimeout(function () {
4158
+ // Note that delayedInteractiveStateUpdate might be equal to null if it was executed before using .flush()
4159
+ delayedInteractiveStateUpdate === null || delayedInteractiveStateUpdate === void 0 ? void 0 : delayedInteractiveStateUpdate();
4160
+ }, exports.setInteractiveStateTimeout);
4161
+ };
4162
+ exports.setInteractiveState = setInteractiveState;
4163
+ /**
4164
+ * Useful in rare cases when it's not desirable to wait for the delayed state updates (at this point it only applies
4165
+ * to interactive state updates). Internally used by the showModal and closeModal functions, as opening modal
4166
+ * usually means reloading interactive. It's necessary to make sure that the state is up to date before it happens.
4167
+ */
4168
+ var flushStateUpdates = function () {
4169
+ // Note that if delayedInteractiveStateUpdate was set, it should set itself to null and setTimeout will ignore it.
4170
+ delayedInteractiveStateUpdate === null || delayedInteractiveStateUpdate === void 0 ? void 0 : delayedInteractiveStateUpdate();
4171
+ window.clearTimeout(setInteractiveStateTimeoutId);
4172
+ };
4173
+ exports.flushStateUpdates = flushStateUpdates;
4174
+ var getAuthoredState = function () {
4175
+ return (0, client_1.getClient)().managedState.authoredState;
4176
+ };
4177
+ exports.getAuthoredState = getAuthoredState;
4178
+ /**
4179
+ * Note that state will become frozen and should never be mutated.
4180
+ * Each time you update state, make sure that a new object is passed.
4181
+ *
4182
+ * Good:
4183
+ * ```
4184
+ * setAuthoredState(Object.assign({}, previousState, {someProperty: "a new value"}));
4185
+ * // or
4186
+ * setAuthoredState({...previousState, someProperty: "a new value"});
4187
+ * ```
4188
+ *
4189
+ * Bad:
4190
+ * ```
4191
+ * previousState.someProperty = "a new value";
4192
+ * setAuthoredState(previousState);
4193
+ * ```
4194
+ */
4195
+ var setAuthoredState = function (newAuthoredState) {
4196
+ var client = (0, client_1.getClient)();
4197
+ client.managedState.authoredState = newAuthoredState;
4198
+ client.post("authoredState", newAuthoredState);
4199
+ };
4200
+ exports.setAuthoredState = setAuthoredState;
4201
+ var getGlobalInteractiveState = function () {
4202
+ return (0, client_1.getClient)().managedState.globalInteractiveState;
4203
+ };
4204
+ exports.getGlobalInteractiveState = getGlobalInteractiveState;
4205
+ /**
4206
+ * Note that state will become frozen and should never be mutated.
4207
+ * Each time you update state, make sure that a new object is passed.
4208
+ *
4209
+ * Good:
4210
+ * ```
4211
+ * setGlobalInteractiveState(Object.assign({}, previousState, {someProperty: "a new value"}));
4212
+ * // or
4213
+ * setGlobalInteractiveState({...previousState, someProperty: "a new value"});
4214
+ * ```
4215
+ *
4216
+ * Bad:
4217
+ * ```
4218
+ * previousState.someProperty = "a new value";
4219
+ * setGlobalInteractiveState(previousState);
4220
+ * ```
4221
+ */
4222
+ var setGlobalInteractiveState = function (newGlobalState) {
4223
+ var client = (0, client_1.getClient)();
4224
+ client.managedState.globalInteractiveState = newGlobalState;
4225
+ client.post("interactiveStateGlobal", newGlobalState);
4226
+ };
4227
+ exports.setGlobalInteractiveState = setGlobalInteractiveState;
4228
+ var addCustomMessageListener = function (callback, handles) {
4229
+ var client = (0, client_1.getClient)();
4230
+ if (handles) {
4231
+ client.customMessagesHandled = handles;
4232
+ }
4233
+ client.addListener("customMessage", callback);
4234
+ };
4235
+ exports.addCustomMessageListener = addCustomMessageListener;
4236
+ var removeCustomMessageListener = function () {
4237
+ return (0, client_1.getClient)().removeListener("customMessage");
4238
+ };
4239
+ exports.removeCustomMessageListener = removeCustomMessageListener;
4240
+ var addDecorateContentListener = function (callback) {
4241
+ (0, client_1.getClient)().addListener("decorateContent", function (msg) {
4242
+ callback({
4243
+ words: msg.words,
4244
+ replace: msg.replace,
4245
+ wordClass: msg.wordClass,
4246
+ eventListeners: msg.listenerTypes.map(function (listener) {
4247
+ return {
4248
+ type: listener.type,
4249
+ listener: function (evt) {
4250
+ var wordElement = evt.srcElement;
4251
+ if (!wordElement) {
4252
+ return;
4253
+ }
4254
+ var clickedWord = (wordElement.textContent || "").toLowerCase();
4255
+ (0, exports.postDecoratedContentEvent)({ type: listener.type,
4256
+ text: clickedWord,
4257
+ bounds: wordElement.getBoundingClientRect() });
4258
+ }
4259
+ };
4260
+ })
4261
+ });
4262
+ });
4263
+ };
4264
+ exports.addDecorateContentListener = addDecorateContentListener;
4265
+ var removeDecorateContentListener = function () {
4266
+ (0, client_1.getClient)().removeListener("decorateContent");
4267
+ };
4268
+ exports.removeDecorateContentListener = removeDecorateContentListener;
4269
+ // tslint:disable-next-line:max-line-length
4270
+ var addGetReportItemAnswerListener = function (callback) {
4271
+ (0, client_1.getClient)().addListener("getReportItemAnswer", callback);
4272
+ };
4273
+ exports.addGetReportItemAnswerListener = addGetReportItemAnswerListener;
4274
+ var removeGetReportItemAnswerListener = function () {
4275
+ (0, client_1.getClient)().removeListener("getReportItemAnswer");
4276
+ };
4277
+ exports.removeGetReportItemAnswerListener = removeGetReportItemAnswerListener;
4278
+ var notifyReportItemClientReady = function (metadata) {
4279
+ (0, client_1.getClient)().post("reportItemClientReady", metadata);
4280
+ };
4281
+ exports.notifyReportItemClientReady = notifyReportItemClientReady;
4282
+ var setSupportedFeatures = function (features) {
4283
+ var request = {
4284
+ apiVersion: 1,
4285
+ features: features
4286
+ };
4287
+ (0, client_1.getClient)().setSupportedFeatures(request);
4572
4288
  };
4573
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
4574
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4575
- return new (P || (P = Promise))(function (resolve, reject) {
4576
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
4577
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
4578
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
4579
- step((generator = generator.apply(thisArg, _arguments || [])).next());
4289
+ exports.setSupportedFeatures = setSupportedFeatures;
4290
+ var setHeight = function (height) {
4291
+ (0, client_1.getClient)().post("height", height);
4292
+ };
4293
+ exports.setHeight = setHeight;
4294
+ var postDecoratedContentEvent = function (msg) {
4295
+ (0, client_1.getClient)().post("decoratedContentEvent", msg);
4296
+ };
4297
+ exports.postDecoratedContentEvent = postDecoratedContentEvent;
4298
+ /**
4299
+ * Providing empty string or null disables hint.
4300
+ */
4301
+ var setHint = function (hint) {
4302
+ var request = { text: hint };
4303
+ (0, client_1.getClient)().post("hint", request);
4304
+ };
4305
+ exports.setHint = setHint;
4306
+ var setNavigation = function (options) {
4307
+ (0, client_1.getClient)().post("navigation", options);
4308
+ };
4309
+ exports.setNavigation = setNavigation;
4310
+ var getAuthInfo = function () {
4311
+ return new Promise(function (resolve, reject) {
4312
+ var listener = function (authInfo) {
4313
+ resolve(authInfo);
4314
+ };
4315
+ var client = (0, client_1.getClient)();
4316
+ var requestId = client.getNextRequestId();
4317
+ var request = {
4318
+ requestId: requestId
4319
+ };
4320
+ client.addListener("authInfo", listener, requestId);
4321
+ client.post("getAuthInfo", request);
4580
4322
  });
4581
4323
  };
4582
- var __generator = (this && this.__generator) || function (thisArg, body) {
4583
- var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
4584
- return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
4585
- function verb(n) { return function (v) { return step([n, v]); }; }
4586
- function step(op) {
4587
- if (f) throw new TypeError("Generator is already executing.");
4588
- while (_) try {
4589
- if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
4590
- if (y = 0, t) op = [op[0] & 2, t.value];
4591
- switch (op[0]) {
4592
- case 0: case 1: t = op; break;
4593
- case 4: _.label++; return { value: op[1], done: false };
4594
- case 5: _.label++; y = op[1]; op = [0]; continue;
4595
- case 7: op = _.ops.pop(); _.trys.pop(); continue;
4596
- default:
4597
- if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
4598
- if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
4599
- if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
4600
- if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
4601
- if (t[2]) _.ops.pop();
4602
- _.trys.pop(); continue;
4324
+ exports.getAuthInfo = getAuthInfo;
4325
+ var getFirebaseJwt = function (firebaseApp) {
4326
+ return new Promise(function (resolve, reject) {
4327
+ (0, exports.getInitInteractiveMessage)().then(function (initMsg) {
4328
+ var _a, _b;
4329
+ if (((_b = (_a = initMsg === null || initMsg === void 0 ? void 0 : initMsg.hostFeatures) === null || _a === void 0 ? void 0 : _a.getFirebaseJwt) === null || _b === void 0 ? void 0 : _b.version) === "1.0.0") {
4330
+ var listener = function (response) {
4331
+ if (response.response_type === "ERROR") {
4332
+ reject(response.message || "Error getting Firebase JWT");
4333
+ }
4334
+ else if (response.token) {
4335
+ try {
4336
+ var claimsJson = atob(response.token.split(".")[1]);
4337
+ resolve({ token: response.token, claims: JSON.parse(claimsJson) });
4338
+ }
4339
+ catch (error) {
4340
+ reject("Unable to parse JWT Token");
4341
+ }
4342
+ }
4343
+ else {
4344
+ reject("Empty token");
4345
+ }
4346
+ };
4347
+ var client = (0, client_1.getClient)();
4348
+ var requestId = client.getNextRequestId();
4349
+ var request = {
4350
+ requestId: requestId,
4351
+ firebase_app: firebaseApp
4352
+ };
4353
+ client.addListener("firebaseJWT", listener, requestId);
4354
+ client.post("getFirebaseJWT", request);
4603
4355
  }
4604
- op = body.call(thisArg, _);
4605
- } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
4606
- if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
4607
- }
4356
+ else {
4357
+ reject("getFirebaseJwt not supported by the host environment");
4358
+ }
4359
+ });
4360
+ });
4608
4361
  };
4609
- var __rest = (this && this.__rest) || function (s, e) {
4610
- var t = {};
4611
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
4612
- t[p] = s[p];
4613
- if (s != null && typeof Object.getOwnPropertySymbols === "function")
4614
- for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
4615
- if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
4616
- t[p[i]] = s[p[i]];
4617
- }
4618
- return t;
4362
+ exports.getFirebaseJwt = getFirebaseJwt;
4363
+ var log = function (action, data) {
4364
+ (0, client_1.getClient)().post("log", { action: action, data: data });
4619
4365
  };
4620
- Object.defineProperty(exports, "__esModule", { value: true });
4621
- exports.sendCustomMessage = exports.setOnUnload = exports.sendReportItemAnswer = exports.getAttachmentUrl = exports.readAttachment = exports.writeAttachment = exports.getLibraryInteractiveList = exports.getInteractiveSnapshot = exports.setLinkedInteractives = exports.getInteractiveList = exports.closeModal = exports.showModal = exports.removeLinkedInteractiveStateListener = exports.addLinkedInteractiveStateListener = exports.removeGlobalInteractiveStateListener = exports.addGlobalInteractiveStateListener = exports.removeAuthoredStateListener = exports.addAuthoredStateListener = exports.removeInteractiveStateListener = exports.addInteractiveStateListener = exports.log = exports.getFirebaseJwt = exports.getAuthInfo = exports.setNavigation = exports.setHint = exports.postDecoratedContentEvent = exports.setHeight = exports.setSupportedFeatures = exports.notifyReportItemClientReady = exports.removeGetReportItemAnswerListener = exports.addGetReportItemAnswerListener = exports.removeDecorateContentListener = exports.addDecorateContentListener = exports.removeCustomMessageListener = exports.addCustomMessageListener = exports.setGlobalInteractiveState = exports.getGlobalInteractiveState = exports.setAuthoredState = exports.getAuthoredState = exports.flushStateUpdates = exports.setInteractiveState = exports.setInteractiveStateTimeout = exports.getInteractiveState = exports.getMode = exports.getInitInteractiveMessage = void 0;
4622
- var client_1 = __webpack_require__(/*! ./client */ "./src/interactive-api-client/client.ts");
4623
- var uuid_1 = __webpack_require__(/*! uuid */ "./node_modules/uuid/dist/esm-browser/index.js");
4624
- var THROW_NOT_IMPLEMENTED_YET = function (method) {
4625
- throw new Error(method + " is not yet implemented in the client!");
4366
+ exports.log = log;
4367
+ // tslint:disable-next-line:max-line-length
4368
+ var addInteractiveStateListener = function (listener) {
4369
+ (0, client_1.getClient)().managedState.on("interactiveStateUpdated", listener);
4626
4370
  };
4627
- var getInitInteractiveMessage = function () {
4628
- var client = (0, client_1.getClient)();
4629
- return new Promise(function (resolve) {
4630
- if (client.managedState.initMessage) {
4631
- resolve(client.managedState.initMessage);
4632
- }
4633
- else {
4634
- client.managedState.once("initInteractive", function () { return resolve(client.managedState.initMessage); });
4635
- }
4636
- });
4371
+ exports.addInteractiveStateListener = addInteractiveStateListener;
4372
+ // tslint:disable-next-line:max-line-length
4373
+ var removeInteractiveStateListener = function (listener) {
4374
+ (0, client_1.getClient)().managedState.off("interactiveStateUpdated", listener);
4637
4375
  };
4638
- exports.getInitInteractiveMessage = getInitInteractiveMessage;
4639
- var getMode = function () {
4640
- return (0, exports.getInitInteractiveMessage)().then(function (initInteractiveMessage) { return initInteractiveMessage === null || initInteractiveMessage === void 0 ? void 0 : initInteractiveMessage.mode; });
4376
+ exports.removeInteractiveStateListener = removeInteractiveStateListener;
4377
+ var addAuthoredStateListener = function (listener) {
4378
+ (0, client_1.getClient)().managedState.on("authoredStateUpdated", listener);
4641
4379
  };
4642
- exports.getMode = getMode;
4643
- var getInteractiveState = function () {
4644
- return (0, client_1.getClient)().managedState.interactiveState;
4380
+ exports.addAuthoredStateListener = addAuthoredStateListener;
4381
+ var removeAuthoredStateListener = function (listener) {
4382
+ (0, client_1.getClient)().managedState.off("authoredStateUpdated", listener);
4645
4383
  };
4646
- exports.getInteractiveState = getInteractiveState;
4647
- var setInteractiveStateTimeoutId;
4648
- var delayedInteractiveStateUpdate = null;
4649
- exports.setInteractiveStateTimeout = 2000; // ms
4384
+ exports.removeAuthoredStateListener = removeAuthoredStateListener;
4385
+ // tslint:disable-next-line:max-line-length
4386
+ var addGlobalInteractiveStateListener = function (listener) {
4387
+ (0, client_1.getClient)().managedState.on("globalInteractiveStateUpdated", listener);
4388
+ };
4389
+ exports.addGlobalInteractiveStateListener = addGlobalInteractiveStateListener;
4390
+ // tslint:disable-next-line:max-line-length
4391
+ var removeGlobalInteractiveStateListener = function (listener) {
4392
+ (0, client_1.getClient)().managedState.off("globalInteractiveStateUpdated", listener);
4393
+ };
4394
+ exports.removeGlobalInteractiveStateListener = removeGlobalInteractiveStateListener;
4395
+ // Mapping between external listener and internal listener, so it's possible to remove linkedInteractiveState listeners.
4396
+ var _linkedInteractiveStateListeners = new Map();
4650
4397
  /**
4651
- * Note that state will become frozen and should never be mutated.
4652
- * Each time you update state, make sure that a new object is passed.
4653
- *
4654
- * Good:
4655
- * ```
4656
- * setInteractiveState(Object.assign({}, previousState, {someProperty: "a new value"}));
4657
- * // or
4658
- * setInteractiveState({...previousState, someProperty: "a new value"});
4659
- * ```
4660
- *
4661
- * Bad:
4662
- * ```
4663
- * previousState.someProperty = "a new value";
4664
- * setInteractiveState(previousState);
4665
- * ```
4398
+ * The listener should be called immediately after it is added with any state of the linked
4399
+ * interactive that the host currently knows about. This first call might not happen
4400
+ * synchronously it could be slightly delayed. And then the listener should be called again
4401
+ * whenever the state of the linked interactive changes.
4666
4402
  */
4667
- var setInteractiveState = function (newInteractiveState) {
4403
+ var addLinkedInteractiveStateListener = function (listener, options) {
4668
4404
  var client = (0, client_1.getClient)();
4669
- client.managedState.interactiveState = newInteractiveState;
4670
- window.clearTimeout(setInteractiveStateTimeoutId);
4671
- delayedInteractiveStateUpdate = function () {
4672
- client.post("interactiveState", newInteractiveState);
4673
- client.managedState.interactiveStateDirty = false;
4674
- delayedInteractiveStateUpdate = null;
4405
+ var listenerId = (0, uuid_1.v4)();
4406
+ var internalListener = function (response) {
4407
+ if (response.listenerId === listenerId) {
4408
+ listener(response.interactiveState);
4409
+ }
4675
4410
  };
4676
- setInteractiveStateTimeoutId = window.setTimeout(function () {
4677
- // Note that delayedInteractiveStateUpdate might be equal to null if it was executed before using .flush()
4678
- delayedInteractiveStateUpdate === null || delayedInteractiveStateUpdate === void 0 ? void 0 : delayedInteractiveStateUpdate();
4679
- }, exports.setInteractiveStateTimeout);
4411
+ client.addListener("linkedInteractiveState", internalListener);
4412
+ // Initialize observing in the host environment.
4413
+ var request = __assign(__assign({}, options), { listenerId: listenerId });
4414
+ client.post("addLinkedInteractiveStateListener", request);
4415
+ // Save wrappedInternalListener so it's possible to remove it later.
4416
+ _linkedInteractiveStateListeners.set(listener, {
4417
+ listenerId: request.listenerId,
4418
+ internalListener: internalListener
4419
+ });
4680
4420
  };
4681
- exports.setInteractiveState = setInteractiveState;
4421
+ exports.addLinkedInteractiveStateListener = addLinkedInteractiveStateListener;
4422
+ var removeLinkedInteractiveStateListener = function (listener) {
4423
+ var client = (0, client_1.getClient)();
4424
+ if (_linkedInteractiveStateListeners.has(listener)) {
4425
+ var _a = _linkedInteractiveStateListeners.get(listener), internalListener = _a.internalListener, listenerId = _a.listenerId;
4426
+ // Remove local message handler. Theoretically it's not necessary if host implementation is correct
4427
+ // (no more messages with this listenerId should be sent), but just to keep things cleaner.
4428
+ client.removeListener("linkedInteractiveState", undefined, internalListener);
4429
+ // Stop observing in the host environment.
4430
+ var request = { listenerId: listenerId };
4431
+ client.post("removeLinkedInteractiveStateListener", request);
4432
+ _linkedInteractiveStateListeners.delete(listener);
4433
+ }
4434
+ };
4435
+ exports.removeLinkedInteractiveStateListener = removeLinkedInteractiveStateListener;
4682
4436
  /**
4683
- * Useful in rare cases when it's not desirable to wait for the delayed state updates (at this point it only applies
4684
- * to interactive state updates). Internally used by the showModal and closeModal functions, as opening modal
4685
- * usually means reloading interactive. It's necessary to make sure that the state is up to date before it happens.
4437
+ * "lightbox" type is used for displaying images or generic iframes (e.g. help page, but NOT dynamic interactives).
4438
+ * "dialog" is used for showing dynamic interactives. It'll be initialized correctly by the host environment and
4439
+ * all the runtime features will be supported.
4686
4440
  */
4687
- var flushStateUpdates = function () {
4688
- // Note that if delayedInteractiveStateUpdate was set, it should set itself to null and setTimeout will ignore it.
4689
- delayedInteractiveStateUpdate === null || delayedInteractiveStateUpdate === void 0 ? void 0 : delayedInteractiveStateUpdate();
4690
- window.clearTimeout(setInteractiveStateTimeoutId);
4441
+ var showModal = function (options) {
4442
+ // Opening modal usually means reloading interactive. It's necessary to make sure that the state is up to date
4443
+ // before it happens.
4444
+ (0, exports.flushStateUpdates)();
4445
+ (0, client_1.getClient)().post("showModal", options);
4691
4446
  };
4692
- exports.flushStateUpdates = flushStateUpdates;
4693
- var getAuthoredState = function () {
4694
- return (0, client_1.getClient)().managedState.authoredState;
4447
+ exports.showModal = showModal;
4448
+ var closeModal = function (options) {
4449
+ // Opening modal usually means reloading interactive. It's necessary to make sure that the state is up to date
4450
+ // before it happens.
4451
+ (0, exports.flushStateUpdates)();
4452
+ (0, client_1.getClient)().post("closeModal", options);
4695
4453
  };
4696
- exports.getAuthoredState = getAuthoredState;
4697
- /**
4698
- * Note that state will become frozen and should never be mutated.
4699
- * Each time you update state, make sure that a new object is passed.
4700
- *
4701
- * Good:
4702
- * ```
4703
- * setAuthoredState(Object.assign({}, previousState, {someProperty: "a new value"}));
4704
- * // or
4705
- * setAuthoredState({...previousState, someProperty: "a new value"});
4706
- * ```
4707
- *
4708
- * Bad:
4709
- * ```
4710
- * previousState.someProperty = "a new value";
4711
- * setAuthoredState(previousState);
4712
- * ```
4713
- */
4714
- var setAuthoredState = function (newAuthoredState) {
4715
- var client = (0, client_1.getClient)();
4716
- client.managedState.authoredState = newAuthoredState;
4717
- client.post("authoredState", newAuthoredState);
4454
+ exports.closeModal = closeModal;
4455
+ var getInteractiveList = function (options) {
4456
+ return new Promise(function (resolve, reject) {
4457
+ return (0, exports.getMode)()
4458
+ .then(function (mode) {
4459
+ if (mode === "authoring") {
4460
+ var client = (0, client_1.getClient)();
4461
+ var requestId = client.getNextRequestId();
4462
+ var request = __assign({ requestId: requestId }, options);
4463
+ client.addListener("interactiveList", resolve, requestId);
4464
+ client.post("getInteractiveList", request);
4465
+ }
4466
+ else {
4467
+ reject("getInteractiveList is only available in authoring mode");
4468
+ }
4469
+ });
4470
+ });
4718
4471
  };
4719
- exports.setAuthoredState = setAuthoredState;
4720
- var getGlobalInteractiveState = function () {
4721
- return (0, client_1.getClient)().managedState.globalInteractiveState;
4472
+ exports.getInteractiveList = getInteractiveList;
4473
+ var setLinkedInteractives = function (options) {
4474
+ (0, client_1.getClient)().post("setLinkedInteractives", options);
4722
4475
  };
4723
- exports.getGlobalInteractiveState = getGlobalInteractiveState;
4476
+ exports.setLinkedInteractives = setLinkedInteractives;
4477
+ var getInteractiveSnapshot = function (options) {
4478
+ return new Promise(function (resolve, reject) {
4479
+ var listener = function (snapshotResponse) {
4480
+ resolve(snapshotResponse);
4481
+ };
4482
+ var client = (0, client_1.getClient)();
4483
+ var requestId = client.getNextRequestId();
4484
+ var request = __assign({ requestId: requestId }, options);
4485
+ client.addListener("interactiveSnapshot", listener, requestId);
4486
+ client.post("getInteractiveSnapshot", request);
4487
+ });
4488
+ };
4489
+ exports.getInteractiveSnapshot = getInteractiveSnapshot;
4724
4490
  /**
4725
- * Note that state will become frozen and should never be mutated.
4726
- * Each time you update state, make sure that a new object is passed.
4727
- *
4728
- * Good:
4729
- * ```
4730
- * setGlobalInteractiveState(Object.assign({}, previousState, {someProperty: "a new value"}));
4731
- * // or
4732
- * setGlobalInteractiveState({...previousState, someProperty: "a new value"});
4733
- * ```
4734
- *
4735
- * Bad:
4736
- * ```
4737
- * previousState.someProperty = "a new value";
4738
- * setGlobalInteractiveState(previousState);
4739
- * ```
4491
+ * @todo Implement this function.
4740
4492
  */
4741
- var setGlobalInteractiveState = function (newGlobalState) {
4742
- var client = (0, client_1.getClient)();
4743
- client.managedState.globalInteractiveState = newGlobalState;
4744
- client.post("interactiveStateGlobal", newGlobalState);
4745
- };
4746
- exports.setGlobalInteractiveState = setGlobalInteractiveState;
4747
- var addCustomMessageListener = function (callback, handles) {
4748
- var client = (0, client_1.getClient)();
4749
- if (handles) {
4750
- client.customMessagesHandled = handles;
4751
- }
4752
- client.addListener("customMessage", callback);
4493
+ var getLibraryInteractiveList = function (options) {
4494
+ THROW_NOT_IMPLEMENTED_YET("getLibraryInteractiveList");
4753
4495
  };
4754
- exports.addCustomMessageListener = addCustomMessageListener;
4755
- var removeCustomMessageListener = function () {
4756
- return (0, client_1.getClient)().removeListener("customMessage");
4496
+ exports.getLibraryInteractiveList = getLibraryInteractiveList;
4497
+ var writeAttachment = function (params) {
4498
+ return new Promise(function (resolve, reject) {
4499
+ var client = (0, client_1.getClient)();
4500
+ var content = params.content, _a = params.options, options = _a === void 0 ? {} : _a, others = __rest(params, ["content", "options"]);
4501
+ var _b = params.contentType, contentType = _b === void 0 ? "text/plain" : _b;
4502
+ var request = __assign(__assign({}, others), { operation: "write", requestId: client.getNextRequestId() });
4503
+ client.addListener("attachmentUrl", function (response) { return __awaiter(void 0, void 0, void 0, function () {
4504
+ var headers, _a, e_1;
4505
+ return __generator(this, function (_b) {
4506
+ switch (_b.label) {
4507
+ case 0:
4508
+ if (!response.url) return [3 /*break*/, 5];
4509
+ headers = __assign({}, options.headers);
4510
+ headers["Content-Type"] = contentType;
4511
+ options.headers = headers;
4512
+ _b.label = 1;
4513
+ case 1:
4514
+ _b.trys.push([1, 3, , 4]);
4515
+ // resolves with the fetch Response object, so clients can check status
4516
+ _a = resolve;
4517
+ return [4 /*yield*/, fetch(response.url, __assign(__assign({}, options), { method: "PUT", body: content }))];
4518
+ case 2:
4519
+ // resolves with the fetch Response object, so clients can check status
4520
+ _a.apply(void 0, [_b.sent()]);
4521
+ return [3 /*break*/, 4];
4522
+ case 3:
4523
+ e_1 = _b.sent();
4524
+ reject(e_1);
4525
+ return [3 /*break*/, 4];
4526
+ case 4: return [3 /*break*/, 6];
4527
+ case 5:
4528
+ reject(new Error(response.error || "error writing attachment"));
4529
+ _b.label = 6;
4530
+ case 6: return [2 /*return*/];
4531
+ }
4532
+ });
4533
+ }); }, request.requestId);
4534
+ client.post("getAttachmentUrl", request);
4535
+ });
4757
4536
  };
4758
- exports.removeCustomMessageListener = removeCustomMessageListener;
4759
- var addDecorateContentListener = function (callback) {
4760
- (0, client_1.getClient)().addListener("decorateContent", function (msg) {
4761
- callback({
4762
- words: msg.words,
4763
- replace: msg.replace,
4764
- wordClass: msg.wordClass,
4765
- eventListeners: msg.listenerTypes.map(function (listener) {
4766
- return {
4767
- type: listener.type,
4768
- listener: function (evt) {
4769
- var wordElement = evt.srcElement;
4770
- if (!wordElement) {
4771
- return;
4772
- }
4773
- var clickedWord = (wordElement.textContent || "").toLowerCase();
4774
- (0, exports.postDecoratedContentEvent)({ type: listener.type,
4775
- text: clickedWord,
4776
- bounds: wordElement.getBoundingClientRect() });
4777
- }
4778
- };
4779
- })
4780
- });
4537
+ exports.writeAttachment = writeAttachment;
4538
+ var readAttachment = function (params) {
4539
+ return new Promise(function (resolve, reject) {
4540
+ // set up response listener
4541
+ var client = (0, client_1.getClient)();
4542
+ var request = __assign(__assign({}, params), { operation: "read", requestId: client.getNextRequestId() });
4543
+ client.addListener("attachmentUrl", function (response) { return __awaiter(void 0, void 0, void 0, function () {
4544
+ var _a, e_2;
4545
+ return __generator(this, function (_b) {
4546
+ switch (_b.label) {
4547
+ case 0:
4548
+ if (!response.url) return [3 /*break*/, 5];
4549
+ _b.label = 1;
4550
+ case 1:
4551
+ _b.trys.push([1, 3, , 4]);
4552
+ // resolves with the fetch Response object, so clients can check status
4553
+ // or convert to JSON or text or something else.
4554
+ _a = resolve;
4555
+ return [4 /*yield*/, fetch(response.url)];
4556
+ case 2:
4557
+ // resolves with the fetch Response object, so clients can check status
4558
+ // or convert to JSON or text or something else.
4559
+ _a.apply(void 0, [_b.sent()]);
4560
+ return [3 /*break*/, 4];
4561
+ case 3:
4562
+ e_2 = _b.sent();
4563
+ reject(e_2);
4564
+ return [3 /*break*/, 4];
4565
+ case 4: return [3 /*break*/, 6];
4566
+ case 5:
4567
+ reject(new Error(response.error || "error reading attachment"));
4568
+ _b.label = 6;
4569
+ case 6: return [2 /*return*/];
4570
+ }
4571
+ });
4572
+ }); }, request.requestId);
4573
+ client.post("getAttachmentUrl", request);
4781
4574
  });
4782
4575
  };
4783
- exports.addDecorateContentListener = addDecorateContentListener;
4784
- var removeDecorateContentListener = function () {
4785
- (0, client_1.getClient)().removeListener("decorateContent");
4576
+ exports.readAttachment = readAttachment;
4577
+ var getAttachmentUrl = function (params) {
4578
+ return new Promise(function (resolve, reject) {
4579
+ // set up response listener
4580
+ var client = (0, client_1.getClient)();
4581
+ var requestId = client.getNextRequestId();
4582
+ var request = __assign(__assign({}, params), { operation: "read", requestId: requestId });
4583
+ client.addListener("attachmentUrl", function (response) { return __awaiter(void 0, void 0, void 0, function () {
4584
+ return __generator(this, function (_a) {
4585
+ if (response.url) {
4586
+ resolve(response.url);
4587
+ }
4588
+ else {
4589
+ reject(new Error(response.error || "error getting attachment url"));
4590
+ }
4591
+ return [2 /*return*/];
4592
+ });
4593
+ }); }, request.requestId);
4594
+ client.post("getAttachmentUrl", request);
4595
+ });
4786
4596
  };
4787
- exports.removeDecorateContentListener = removeDecorateContentListener;
4788
- // tslint:disable-next-line:max-line-length
4789
- var addGetReportItemAnswerListener = function (callback) {
4790
- (0, client_1.getClient)().addListener("getReportItemAnswer", callback);
4597
+ exports.getAttachmentUrl = getAttachmentUrl;
4598
+ var sendReportItemAnswer = function (request) {
4599
+ (0, client_1.getClient)().post("reportItemAnswer", request);
4791
4600
  };
4792
- exports.addGetReportItemAnswerListener = addGetReportItemAnswerListener;
4793
- var removeGetReportItemAnswerListener = function () {
4794
- (0, client_1.getClient)().removeListener("getReportItemAnswer");
4601
+ exports.sendReportItemAnswer = sendReportItemAnswer;
4602
+ var setOnUnload = function (onUnload) {
4603
+ (0, client_1.getClient)().setOnUnload(onUnload);
4795
4604
  };
4796
- exports.removeGetReportItemAnswerListener = removeGetReportItemAnswerListener;
4797
- var notifyReportItemClientReady = function (metadata) {
4798
- (0, client_1.getClient)().post("reportItemClientReady", metadata);
4605
+ exports.setOnUnload = setOnUnload;
4606
+ var sendCustomMessage = function (customMessage) {
4607
+ (0, client_1.getClient)().post("customMessage", customMessage);
4799
4608
  };
4800
- exports.notifyReportItemClientReady = notifyReportItemClientReady;
4801
- var setSupportedFeatures = function (features) {
4802
- var request = {
4803
- apiVersion: 1,
4804
- features: features
4609
+ exports.sendCustomMessage = sendCustomMessage;
4610
+
4611
+
4612
+ /***/ }),
4613
+
4614
+ /***/ "./src/interactive-api-client/client.ts":
4615
+ /*!**********************************************!*\
4616
+ !*** ./src/interactive-api-client/client.ts ***!
4617
+ \**********************************************/
4618
+ /*! no static exports found */
4619
+ /***/ (function(module, exports, __webpack_require__) {
4620
+
4621
+ "use strict";
4622
+
4623
+ var __assign = (this && this.__assign) || function () {
4624
+ __assign = Object.assign || function(t) {
4625
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
4626
+ s = arguments[i];
4627
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
4628
+ t[p] = s[p];
4629
+ }
4630
+ return t;
4805
4631
  };
4806
- (0, client_1.getClient)().setSupportedFeatures(request);
4632
+ return __assign.apply(this, arguments);
4807
4633
  };
4808
- exports.setSupportedFeatures = setSupportedFeatures;
4809
- var setHeight = function (height) {
4810
- (0, client_1.getClient)().post("height", height);
4634
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
4635
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4636
+ return new (P || (P = Promise))(function (resolve, reject) {
4637
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
4638
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
4639
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
4640
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
4641
+ });
4811
4642
  };
4812
- exports.setHeight = setHeight;
4813
- var postDecoratedContentEvent = function (msg) {
4814
- (0, client_1.getClient)().post("decoratedContentEvent", msg);
4643
+ var __generator = (this && this.__generator) || function (thisArg, body) {
4644
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
4645
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
4646
+ function verb(n) { return function (v) { return step([n, v]); }; }
4647
+ function step(op) {
4648
+ if (f) throw new TypeError("Generator is already executing.");
4649
+ while (_) try {
4650
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
4651
+ if (y = 0, t) op = [op[0] & 2, t.value];
4652
+ switch (op[0]) {
4653
+ case 0: case 1: t = op; break;
4654
+ case 4: _.label++; return { value: op[1], done: false };
4655
+ case 5: _.label++; y = op[1]; op = [0]; continue;
4656
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
4657
+ default:
4658
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
4659
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
4660
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
4661
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
4662
+ if (t[2]) _.ops.pop();
4663
+ _.trys.pop(); continue;
4664
+ }
4665
+ op = body.call(thisArg, _);
4666
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
4667
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
4668
+ }
4815
4669
  };
4816
- exports.postDecoratedContentEvent = postDecoratedContentEvent;
4817
- /**
4818
- * Providing empty string or null disables hint.
4819
- */
4820
- var setHint = function (hint) {
4821
- var request = { text: hint };
4822
- (0, client_1.getClient)().post("hint", request);
4670
+ var __rest = (this && this.__rest) || function (s, e) {
4671
+ var t = {};
4672
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
4673
+ t[p] = s[p];
4674
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
4675
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
4676
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
4677
+ t[p[i]] = s[p[i]];
4678
+ }
4679
+ return t;
4823
4680
  };
4824
- exports.setHint = setHint;
4825
- var setNavigation = function (options) {
4826
- (0, client_1.getClient)().post("navigation", options);
4681
+ Object.defineProperty(exports, "__esModule", { value: true });
4682
+ exports.Client = exports.getClient = void 0;
4683
+ // iframe phone uses 1 listener per message type so we multiplex over 1 listener in this code
4684
+ // to allow callbacks to optionally be tied to a requestId. This allows us to have multiple listeners
4685
+ // to the same message and auto-removing listeners when a requestId is given.
4686
+ var iframePhone = __webpack_require__(/*! iframe-phone */ "./src/interactive-api-client/node_modules/iframe-phone/main.js");
4687
+ var in_frame_1 = __webpack_require__(/*! ./in-frame */ "./src/interactive-api-client/in-frame.ts");
4688
+ var managed_state_1 = __webpack_require__(/*! ./managed-state */ "./src/interactive-api-client/managed-state.ts");
4689
+ var parseJSONIfString = function (data) {
4690
+ // Note that we don't want to call JSON.parse for an empty string.
4691
+ try {
4692
+ return typeof data === "string" ? JSON.parse(data) : data;
4693
+ }
4694
+ catch (_a) {
4695
+ // If JSON string is malformed, it's an empty string, or not a JSON at all, return the original value.
4696
+ return data;
4697
+ }
4827
4698
  };
4828
- exports.setNavigation = setNavigation;
4829
- var getAuthInfo = function () {
4830
- return new Promise(function (resolve, reject) {
4831
- var listener = function (authInfo) {
4832
- resolve(authInfo);
4699
+ var phoneInitialized = function () { return iframePhone.getIFrameEndpoint().getListenerNames().length > 0; };
4700
+ var clientInstance;
4701
+ var getClient = function () {
4702
+ // !phoneInitialized() part isn't really necessary. But it's fine in web browser and it helps in testing environment.
4703
+ // Tests can reset mock iframe phone and get new Client instance.
4704
+ if (!clientInstance || !phoneInitialized()) {
4705
+ clientInstance = new Client();
4706
+ }
4707
+ return clientInstance;
4708
+ };
4709
+ exports.getClient = getClient;
4710
+ /**
4711
+ * This class is intended to provide basic helpers (like `post()` or `add/removeListener`), maintain client-specific
4712
+ * state, and generally be as minimal as possible. Most of the client-specific helpers and logic can be implemented
4713
+ * in api.ts or hooks.ts (or both so the client app has choice).
4714
+ */
4715
+ var Client = /** @class */ (function () {
4716
+ function Client() {
4717
+ var _this = this;
4718
+ this.phone = iframePhone.getIFrameEndpoint();
4719
+ this.managedState = new managed_state_1.ManagedState();
4720
+ this.listeners = {};
4721
+ this.requestId = 1;
4722
+ this.onUnload = undefined;
4723
+ this.setSupportedFeatures = function (request) {
4724
+ var newRequest = request;
4725
+ if (_this.customMessagesHandled) {
4726
+ var features = request.features, others = __rest(request, ["features"]);
4727
+ features.customMessages = { handles: _this.customMessagesHandled };
4728
+ newRequest = __assign({ features: features }, others);
4729
+ }
4730
+ _this.post("supportedFeatures", newRequest);
4833
4731
  };
4834
- var client = (0, client_1.getClient)();
4835
- var requestId = client.getNextRequestId();
4836
- var request = {
4837
- requestId: requestId
4732
+ this.setOnUnload = function (onUnload) {
4733
+ _this.onUnload = onUnload;
4838
4734
  };
4839
- client.addListener("authInfo", listener, requestId);
4840
- client.post("getAuthInfo", request);
4841
- });
4842
- };
4843
- exports.getAuthInfo = getAuthInfo;
4844
- var getFirebaseJwt = function (firebaseApp) {
4845
- return new Promise(function (resolve, reject) {
4846
- (0, exports.getInitInteractiveMessage)().then(function (initMsg) {
4847
- var _a, _b;
4848
- if (((_b = (_a = initMsg === null || initMsg === void 0 ? void 0 : initMsg.hostFeatures) === null || _a === void 0 ? void 0 : _a.getFirebaseJwt) === null || _b === void 0 ? void 0 : _b.version) === "1.0.0") {
4849
- var listener = function (response) {
4850
- if (response.response_type === "ERROR") {
4851
- reject(response.message || "Error getting Firebase JWT");
4735
+ if (!(0, in_frame_1.inIframe)()) {
4736
+ // tslint:disable-next-line:no-console
4737
+ console.warn("Interactive API is meant to be used in iframe");
4738
+ }
4739
+ if (phoneInitialized()) {
4740
+ throw new Error("IframePhone has been initialized previously. Only one Client instance is allowed.");
4741
+ }
4742
+ this.connect();
4743
+ // Warn users when they want to reload page before the data gets sent to LARA.
4744
+ window.addEventListener("beforeunload", function (e) {
4745
+ if (_this.managedState.interactiveStateDirty) {
4746
+ // Browser will display different message anyway, but returnValue must be set.
4747
+ e.returnValue = "State has not been saved. Are you sure you want to leave this page?";
4748
+ }
4749
+ return e;
4750
+ });
4751
+ }
4752
+ Client.prototype.getNextRequestId = function () {
4753
+ return this.requestId++;
4754
+ };
4755
+ Client.prototype.post = function (message, content) {
4756
+ this.phone.post(message, content);
4757
+ };
4758
+ Client.prototype.addListener = function (message, callback, requestId) {
4759
+ var _this = this;
4760
+ if (this.phone) {
4761
+ // add either a generic message listener (no requestId) or an auto-removing request listener
4762
+ // note: we may have multiple listeners on the same generic message
4763
+ this.listeners[message] = this.listeners[message] || [];
4764
+ var noExistingListener = this.listeners[message].length === 0;
4765
+ this.listeners[message].push({ requestId: requestId, callback: callback });
4766
+ // iframe-phone only handles 1 listener per message so add the listener if we haven't already
4767
+ if (noExistingListener) {
4768
+ this.phone.addListener(message, function (content) {
4769
+ // strip requestId from the response so callbacks don't see it
4770
+ var contentRequestId = content ? content.requestId : undefined;
4771
+ if (content) {
4772
+ delete content.requestId;
4852
4773
  }
4853
- else if (response.token) {
4854
- try {
4855
- var claimsJson = atob(response.token.split(".")[1]);
4856
- resolve({ token: response.token, claims: JSON.parse(claimsJson) });
4857
- }
4858
- catch (error) {
4859
- reject("Unable to parse JWT Token");
4774
+ _this.listeners[message].forEach(function (listener) {
4775
+ // note: requestId can be undefined for listeners to Lara messages
4776
+ // that aren't responses to one-time requests
4777
+ if (listener.requestId === contentRequestId) {
4778
+ listener.callback(content);
4860
4779
  }
4780
+ });
4781
+ // if a request id was returned by lara auto-remove it from the listeners as it is a
4782
+ // response to a one-time request
4783
+ if (contentRequestId) {
4784
+ _this.removeListener(message, contentRequestId);
4861
4785
  }
4862
- else {
4863
- reject("Empty token");
4864
- }
4865
- };
4866
- var client = (0, client_1.getClient)();
4867
- var requestId = client.getNextRequestId();
4868
- var request = {
4869
- requestId: requestId,
4870
- firebase_app: firebaseApp
4871
- };
4872
- client.addListener("firebaseJWT", listener, requestId);
4873
- client.post("getFirebaseJWT", request);
4786
+ });
4787
+ }
4788
+ return true;
4789
+ }
4790
+ return false;
4791
+ };
4792
+ Client.prototype.removeListener = function (message, requestId, callback) {
4793
+ if (this.listeners[message]) {
4794
+ // When callback is provided, remove this particular callback.
4795
+ // Otherwise try to use requestId.
4796
+ if (callback) {
4797
+ this.listeners[message] = this.listeners[message].filter(function (l) { return l.callback !== callback; });
4874
4798
  }
4875
4799
  else {
4876
- reject("getFirebaseJwt not supported by the host environment");
4800
+ // note: requestId can be undefined when using it as a generic listener
4801
+ this.listeners[message] = this.listeners[message].filter(function (l) { return l.requestId !== requestId; });
4877
4802
  }
4878
- });
4879
- });
4880
- };
4881
- exports.getFirebaseJwt = getFirebaseJwt;
4882
- var log = function (action, data) {
4883
- (0, client_1.getClient)().post("log", { action: action, data: data });
4884
- };
4885
- exports.log = log;
4886
- // tslint:disable-next-line:max-line-length
4887
- var addInteractiveStateListener = function (listener) {
4888
- (0, client_1.getClient)().managedState.on("interactiveStateUpdated", listener);
4889
- };
4890
- exports.addInteractiveStateListener = addInteractiveStateListener;
4891
- // tslint:disable-next-line:max-line-length
4892
- var removeInteractiveStateListener = function (listener) {
4893
- (0, client_1.getClient)().managedState.off("interactiveStateUpdated", listener);
4894
- };
4895
- exports.removeInteractiveStateListener = removeInteractiveStateListener;
4896
- var addAuthoredStateListener = function (listener) {
4897
- (0, client_1.getClient)().managedState.on("authoredStateUpdated", listener);
4898
- };
4899
- exports.addAuthoredStateListener = addAuthoredStateListener;
4900
- var removeAuthoredStateListener = function (listener) {
4901
- (0, client_1.getClient)().managedState.off("authoredStateUpdated", listener);
4902
- };
4903
- exports.removeAuthoredStateListener = removeAuthoredStateListener;
4904
- // tslint:disable-next-line:max-line-length
4905
- var addGlobalInteractiveStateListener = function (listener) {
4906
- (0, client_1.getClient)().managedState.on("globalInteractiveStateUpdated", listener);
4907
- };
4908
- exports.addGlobalInteractiveStateListener = addGlobalInteractiveStateListener;
4909
- // tslint:disable-next-line:max-line-length
4910
- var removeGlobalInteractiveStateListener = function (listener) {
4911
- (0, client_1.getClient)().managedState.off("globalInteractiveStateUpdated", listener);
4912
- };
4913
- exports.removeGlobalInteractiveStateListener = removeGlobalInteractiveStateListener;
4914
- // Mapping between external listener and internal listener, so it's possible to remove linkedInteractiveState listeners.
4915
- var _linkedInteractiveStateListeners = new Map();
4916
- /**
4917
- * The listener should be called immediately after it is added with any state of the linked
4918
- * interactive that the host currently knows about. This first call might not happen
4919
- * synchronously it could be slightly delayed. And then the listener should be called again
4920
- * whenever the state of the linked interactive changes.
4921
- */
4922
- var addLinkedInteractiveStateListener = function (listener, options) {
4923
- var client = (0, client_1.getClient)();
4924
- var listenerId = (0, uuid_1.v4)();
4925
- var internalListener = function (response) {
4926
- if (response.listenerId === listenerId) {
4927
- listener(response.interactiveState);
4803
+ // if no more local listeners exist remove it from iframe-phone
4804
+ if (this.listeners[message].length === 0) {
4805
+ this.phone.removeListener(message);
4806
+ }
4807
+ return true;
4928
4808
  }
4809
+ return false;
4929
4810
  };
4930
- client.addListener("linkedInteractiveState", internalListener);
4931
- // Initialize observing in the host environment.
4932
- var request = __assign(__assign({}, options), { listenerId: listenerId });
4933
- client.post("addLinkedInteractiveStateListener", request);
4934
- // Save wrappedInternalListener so it's possible to remove it later.
4935
- _linkedInteractiveStateListeners.set(listener, {
4936
- listenerId: request.listenerId,
4937
- internalListener: internalListener
4938
- });
4939
- };
4940
- exports.addLinkedInteractiveStateListener = addLinkedInteractiveStateListener;
4941
- var removeLinkedInteractiveStateListener = function (listener) {
4942
- var client = (0, client_1.getClient)();
4943
- if (_linkedInteractiveStateListeners.has(listener)) {
4944
- var _a = _linkedInteractiveStateListeners.get(listener), internalListener = _a.internalListener, listenerId = _a.listenerId;
4945
- // Remove local message handler. Theoretically it's not necessary if host implementation is correct
4946
- // (no more messages with this listenerId should be sent), but just to keep things cleaner.
4947
- client.removeListener("linkedInteractiveState", undefined, internalListener);
4948
- // Stop observing in the host environment.
4949
- var request = { listenerId: listenerId };
4950
- client.post("removeLinkedInteractiveStateListener", request);
4951
- _linkedInteractiveStateListeners.delete(listener);
4952
- }
4953
- };
4954
- exports.removeLinkedInteractiveStateListener = removeLinkedInteractiveStateListener;
4955
- /**
4956
- * "lightbox" type is used for displaying images or generic iframes (e.g. help page, but NOT dynamic interactives).
4957
- * "dialog" is used for showing dynamic interactives. It'll be initialized correctly by the host environment and
4958
- * all the runtime features will be supported.
4959
- */
4960
- var showModal = function (options) {
4961
- // Opening modal usually means reloading interactive. It's necessary to make sure that the state is up to date
4962
- // before it happens.
4963
- (0, exports.flushStateUpdates)();
4964
- (0, client_1.getClient)().post("showModal", options);
4965
- };
4966
- exports.showModal = showModal;
4967
- var closeModal = function (options) {
4968
- // Opening modal usually means reloading interactive. It's necessary to make sure that the state is up to date
4969
- // before it happens.
4970
- (0, exports.flushStateUpdates)();
4971
- (0, client_1.getClient)().post("closeModal", options);
4972
- };
4973
- exports.closeModal = closeModal;
4974
- var getInteractiveList = function (options) {
4975
- return new Promise(function (resolve, reject) {
4976
- return (0, exports.getMode)()
4977
- .then(function (mode) {
4978
- if (mode === "authoring") {
4979
- var client = (0, client_1.getClient)();
4980
- var requestId = client.getNextRequestId();
4981
- var request = __assign({ requestId: requestId }, options);
4982
- client.addListener("interactiveList", resolve, requestId);
4983
- client.post("getInteractiveList", request);
4811
+ Client.prototype.connect = function () {
4812
+ var _this = this;
4813
+ this.phone = iframePhone.getIFrameEndpoint();
4814
+ this.addListener("initInteractive", function (newInitMessage) {
4815
+ _this.managedState.initMessage = newInitMessage;
4816
+ // parseJSONIfString is used below quite a few times, as LARA and report are not consistent about format.
4817
+ // Sometimes they send string (report page), sometimes already parsed JSON (authoring, runtime).
4818
+ if (newInitMessage.mode === "reportItem") {
4819
+ _this.managedState.authoredState = {};
4984
4820
  }
4985
4821
  else {
4986
- reject("getInteractiveList is only available in authoring mode");
4822
+ _this.managedState.authoredState = parseJSONIfString(newInitMessage.authoredState);
4823
+ }
4824
+ if (newInitMessage.mode === "runtime" || newInitMessage.mode === "report") {
4825
+ _this.managedState.interactiveState = parseJSONIfString(newInitMessage.interactiveState);
4826
+ // Don't consider initial state to be dirty, as user would see warnings while trying to leave page even
4827
+ // without making any change.
4828
+ _this.managedState.interactiveStateDirty = false;
4829
+ }
4830
+ if (newInitMessage.mode === "runtime") {
4831
+ _this.managedState.globalInteractiveState = parseJSONIfString(newInitMessage.globalInteractiveState);
4832
+ }
4833
+ });
4834
+ this.addListener("getInteractiveState", function (options) { return __awaiter(_this, void 0, void 0, function () {
4835
+ var finalState;
4836
+ return __generator(this, function (_a) {
4837
+ switch (_a.label) {
4838
+ case 0:
4839
+ if (!((options === null || options === void 0 ? void 0 : options.unloading) && this.onUnload)) return [3 /*break*/, 2];
4840
+ return [4 /*yield*/, this.onUnload(options)];
4841
+ case 1:
4842
+ finalState = _a.sent();
4843
+ if (finalState) {
4844
+ this.managedState.interactiveState = finalState;
4845
+ }
4846
+ _a.label = 2;
4847
+ case 2:
4848
+ this.post("interactiveState", this.managedState.interactiveState);
4849
+ this.managedState.interactiveStateDirty = false;
4850
+ return [2 /*return*/];
4851
+ }
4852
+ });
4853
+ }); });
4854
+ this.addListener("loadInteractiveGlobal", function (globalState) {
4855
+ _this.managedState.globalInteractiveState = parseJSONIfString(globalState);
4856
+ });
4857
+ this.phone.initialize();
4858
+ };
4859
+ return Client;
4860
+ }());
4861
+ exports.Client = Client;
4862
+
4863
+
4864
+ /***/ }),
4865
+
4866
+ /***/ "./src/interactive-api-client/hooks.ts":
4867
+ /*!*********************************************!*\
4868
+ !*** ./src/interactive-api-client/hooks.ts ***!
4869
+ \*********************************************/
4870
+ /*! no static exports found */
4871
+ /***/ (function(module, exports, __webpack_require__) {
4872
+
4873
+ "use strict";
4874
+
4875
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
4876
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4877
+ return new (P || (P = Promise))(function (resolve, reject) {
4878
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
4879
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
4880
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
4881
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
4882
+ });
4883
+ };
4884
+ var __generator = (this && this.__generator) || function (thisArg, body) {
4885
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
4886
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
4887
+ function verb(n) { return function (v) { return step([n, v]); }; }
4888
+ function step(op) {
4889
+ if (f) throw new TypeError("Generator is already executing.");
4890
+ while (_) try {
4891
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
4892
+ if (y = 0, t) op = [op[0] & 2, t.value];
4893
+ switch (op[0]) {
4894
+ case 0: case 1: t = op; break;
4895
+ case 4: _.label++; return { value: op[1], done: false };
4896
+ case 5: _.label++; y = op[1]; op = [0]; continue;
4897
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
4898
+ default:
4899
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
4900
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
4901
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
4902
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
4903
+ if (t[2]) _.ops.pop();
4904
+ _.trys.pop(); continue;
4987
4905
  }
4988
- });
4989
- });
4906
+ op = body.call(thisArg, _);
4907
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
4908
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
4909
+ }
4990
4910
  };
4991
- exports.getInteractiveList = getInteractiveList;
4992
- var setLinkedInteractives = function (options) {
4993
- (0, client_1.getClient)().post("setLinkedInteractives", options);
4911
+ Object.defineProperty(exports, "__esModule", { value: true });
4912
+ exports.useAccessibility = exports.DefaultAccessibilitySettings = exports.useReportItem = exports.useAutoSetHeight = exports.useDecorateContent = exports.useCustomMessages = exports.useInitMessage = exports.useGlobalInteractiveState = exports.useAuthoredState = exports.useInteractiveState = void 0;
4913
+ var react_1 = __webpack_require__(/*! react */ "react");
4914
+ var resize_observer_polyfill_1 = __webpack_require__(/*! resize-observer-polyfill */ "./node_modules/resize-observer-polyfill/dist/ResizeObserver.es.js");
4915
+ var client = __webpack_require__(/*! ./api */ "./src/interactive-api-client/api.ts");
4916
+ var accessibility_1 = __webpack_require__(/*! ../shared/accessibility */ "./src/shared/accessibility.ts");
4917
+ var handleUpdate = function (newStateOrUpdateFunc, prevState) {
4918
+ if (typeof newStateOrUpdateFunc === "function") {
4919
+ return newStateOrUpdateFunc(prevState);
4920
+ }
4921
+ else {
4922
+ return newStateOrUpdateFunc;
4923
+ }
4994
4924
  };
4995
- exports.setLinkedInteractives = setLinkedInteractives;
4996
- var getInteractiveSnapshot = function (options) {
4997
- return new Promise(function (resolve, reject) {
4998
- var listener = function (snapshotResponse) {
4999
- resolve(snapshotResponse);
4925
+ var useInteractiveState = function () {
4926
+ var _a = (0, react_1.useState)(null), interactiveState = _a[0], setInteractiveState = _a[1];
4927
+ (0, react_1.useEffect)(function () {
4928
+ setInteractiveState(client.getInteractiveState());
4929
+ // Setup client event listeners. They will ensure that another instance of this hook (or anything else
4930
+ // using client directly) makes changes to interactive state, this hook will receive these changes.
4931
+ var handleStateUpdate = function (newState) {
4932
+ setInteractiveState(newState);
5000
4933
  };
5001
- var client = (0, client_1.getClient)();
5002
- var requestId = client.getNextRequestId();
5003
- var request = __assign({ requestId: requestId }, options);
5004
- client.addListener("interactiveSnapshot", listener, requestId);
5005
- client.post("getInteractiveSnapshot", request);
5006
- });
4934
+ client.addInteractiveStateListener(handleStateUpdate);
4935
+ return function () {
4936
+ client.removeInteractiveStateListener(handleStateUpdate);
4937
+ };
4938
+ }, []);
4939
+ var handleSetInteractiveState = (0, react_1.useCallback)(function (stateOrUpdateFunc) {
4940
+ // Use client-managed state, as it should be up to date. React-managed state might not be the most recent version.
4941
+ var newState = handleUpdate(stateOrUpdateFunc, client.getInteractiveState());
4942
+ setInteractiveState(newState);
4943
+ client.setInteractiveState(newState);
4944
+ }, []);
4945
+ return { interactiveState: interactiveState, setInteractiveState: handleSetInteractiveState };
5007
4946
  };
5008
- exports.getInteractiveSnapshot = getInteractiveSnapshot;
5009
- /**
5010
- * @todo Implement this function.
5011
- */
5012
- var getLibraryInteractiveList = function (options) {
5013
- THROW_NOT_IMPLEMENTED_YET("getLibraryInteractiveList");
4947
+ exports.useInteractiveState = useInteractiveState;
4948
+ var useAuthoredState = function () {
4949
+ var _a = (0, react_1.useState)(null), authoredState = _a[0], setAuthoredState = _a[1];
4950
+ (0, react_1.useEffect)(function () {
4951
+ // Note that we need to update authoredState exactly in this moment, right before setting up event listeners.
4952
+ // It can't be done above using initial useState value. There's a little delay between initial render and calling
4953
+ // useEffect. If client's authoredState gets updated before the listener is added, this hook will have outdated
4954
+ // value. It's not only a theoretical issue, it was actually happening in Safari:
4955
+ // https://www.pivotaltracker.com/story/show/174154314
4956
+ // initInteractive message that includes authoredAuthored message was received between initial render and calling
4957
+ // client.addAuthoredStateListener, so the state update was lost.
4958
+ setAuthoredState(client.getAuthoredState());
4959
+ // Setup client event listeners. They will ensure that another instance of this hook (or anything else
4960
+ // using client directly) makes changes to authored state, this hook will receive these changes.
4961
+ var handleStateUpdate = function (newState) {
4962
+ setAuthoredState(newState);
4963
+ };
4964
+ client.addAuthoredStateListener(handleStateUpdate);
4965
+ return function () {
4966
+ client.removeAuthoredStateListener(handleStateUpdate);
4967
+ };
4968
+ }, []);
4969
+ var handleSetAuthoredState = (0, react_1.useCallback)(function (stateOrUpdateFunc) {
4970
+ // Use client-managed state, as it should be up to date. React-managed state might not be the most recent version.
4971
+ var newState = handleUpdate(stateOrUpdateFunc, client.getAuthoredState());
4972
+ setAuthoredState(newState);
4973
+ client.setAuthoredState(newState);
4974
+ }, []);
4975
+ return { authoredState: authoredState, setAuthoredState: handleSetAuthoredState };
5014
4976
  };
5015
- exports.getLibraryInteractiveList = getLibraryInteractiveList;
5016
- var writeAttachment = function (params) {
5017
- return new Promise(function (resolve, reject) {
5018
- var client = (0, client_1.getClient)();
5019
- var content = params.content, _a = params.options, options = _a === void 0 ? {} : _a, others = __rest(params, ["content", "options"]);
5020
- var _b = params.contentType, contentType = _b === void 0 ? "text/plain" : _b;
5021
- var request = __assign(__assign({}, others), { operation: "write", requestId: client.getNextRequestId() });
5022
- client.addListener("attachmentUrl", function (response) { return __awaiter(void 0, void 0, void 0, function () {
5023
- var headers, _a, e_1;
5024
- return __generator(this, function (_b) {
5025
- switch (_b.label) {
5026
- case 0:
5027
- if (!response.url) return [3 /*break*/, 5];
5028
- headers = __assign({}, options.headers);
5029
- headers["Content-Type"] = contentType;
5030
- options.headers = headers;
5031
- _b.label = 1;
5032
- case 1:
5033
- _b.trys.push([1, 3, , 4]);
5034
- // resolves with the fetch Response object, so clients can check status
5035
- _a = resolve;
5036
- return [4 /*yield*/, fetch(response.url, __assign(__assign({}, options), { method: "PUT", body: content }))];
5037
- case 2:
5038
- // resolves with the fetch Response object, so clients can check status
5039
- _a.apply(void 0, [_b.sent()]);
5040
- return [3 /*break*/, 4];
5041
- case 3:
5042
- e_1 = _b.sent();
5043
- reject(e_1);
5044
- return [3 /*break*/, 4];
5045
- case 4: return [3 /*break*/, 6];
5046
- case 5:
5047
- reject(new Error(response.error || "error writing attachment"));
5048
- _b.label = 6;
5049
- case 6: return [2 /*return*/];
5050
- }
5051
- });
5052
- }); }, request.requestId);
5053
- client.post("getAttachmentUrl", request);
5054
- });
4977
+ exports.useAuthoredState = useAuthoredState;
4978
+ var useGlobalInteractiveState = function () {
4979
+ var _a = (0, react_1.useState)(null), globalInteractiveState = _a[0], setGlobalInteractiveState = _a[1];
4980
+ (0, react_1.useEffect)(function () {
4981
+ setGlobalInteractiveState(client.getGlobalInteractiveState());
4982
+ // Setup client event listeners. They will ensure that another instance of this hook (or anything else
4983
+ // using client directly) makes changes to global interactive state, this hook will receive these changes.
4984
+ var handleStateUpdate = function (newState) {
4985
+ setGlobalInteractiveState(newState);
4986
+ };
4987
+ client.addGlobalInteractiveStateListener(handleStateUpdate);
4988
+ return function () {
4989
+ client.removeGlobalInteractiveStateListener(handleStateUpdate);
4990
+ };
4991
+ }, []);
4992
+ // tslint:disable-next-line:max-line-length
4993
+ var handleSetGlobalInteractiveState = (0, react_1.useCallback)(function (stateOrUpdateFunc) {
4994
+ // Use client-managed state, as it should be up to date. React-managed state might not be the most recent version.
4995
+ var newState = handleUpdate(stateOrUpdateFunc, client.getGlobalInteractiveState());
4996
+ setGlobalInteractiveState(newState);
4997
+ client.setGlobalInteractiveState(newState);
4998
+ }, []);
4999
+ return { globalInteractiveState: globalInteractiveState, setGlobalInteractiveState: handleSetGlobalInteractiveState };
5055
5000
  };
5056
- exports.writeAttachment = writeAttachment;
5057
- var readAttachment = function (params) {
5058
- return new Promise(function (resolve, reject) {
5059
- // set up response listener
5060
- var client = (0, client_1.getClient)();
5061
- var request = __assign(__assign({}, params), { operation: "read", requestId: client.getNextRequestId() });
5062
- client.addListener("attachmentUrl", function (response) { return __awaiter(void 0, void 0, void 0, function () {
5063
- var _a, e_2;
5064
- return __generator(this, function (_b) {
5065
- switch (_b.label) {
5066
- case 0:
5067
- if (!response.url) return [3 /*break*/, 5];
5068
- _b.label = 1;
5001
+ exports.useGlobalInteractiveState = useGlobalInteractiveState;
5002
+ // tslint:disable-next-line:max-line-length
5003
+ var useInitMessage = function () {
5004
+ var _a = (0, react_1.useState)(null), initMessage = _a[0], setInitMessage = _a[1];
5005
+ (0, react_1.useEffect)(function () {
5006
+ // useEffect callback can't be async.
5007
+ (function () { return __awaiter(void 0, void 0, void 0, function () {
5008
+ var initMsg;
5009
+ return __generator(this, function (_a) {
5010
+ switch (_a.label) {
5011
+ case 0: return [4 /*yield*/, client.getInitInteractiveMessage()];
5069
5012
  case 1:
5070
- _b.trys.push([1, 3, , 4]);
5071
- // resolves with the fetch Response object, so clients can check status
5072
- // or convert to JSON or text or something else.
5073
- _a = resolve;
5074
- return [4 /*yield*/, fetch(response.url)];
5075
- case 2:
5076
- // resolves with the fetch Response object, so clients can check status
5077
- // or convert to JSON or text or something else.
5078
- _a.apply(void 0, [_b.sent()]);
5079
- return [3 /*break*/, 4];
5080
- case 3:
5081
- e_2 = _b.sent();
5082
- reject(e_2);
5083
- return [3 /*break*/, 4];
5084
- case 4: return [3 /*break*/, 6];
5085
- case 5:
5086
- reject(new Error(response.error || "error reading attachment"));
5087
- _b.label = 6;
5088
- case 6: return [2 /*return*/];
5013
+ initMsg = _a.sent();
5014
+ setInitMessage(initMsg);
5015
+ return [2 /*return*/];
5089
5016
  }
5090
5017
  });
5091
- }); }, request.requestId);
5092
- client.post("getAttachmentUrl", request);
5093
- });
5018
+ }); })();
5019
+ }, []);
5020
+ return initMessage;
5094
5021
  };
5095
- exports.readAttachment = readAttachment;
5096
- var getAttachmentUrl = function (params) {
5097
- return new Promise(function (resolve, reject) {
5098
- // set up response listener
5099
- var client = (0, client_1.getClient)();
5100
- var requestId = client.getNextRequestId();
5101
- var request = __assign(__assign({}, params), { operation: "read", requestId: requestId });
5102
- client.addListener("attachmentUrl", function (response) { return __awaiter(void 0, void 0, void 0, function () {
5103
- return __generator(this, function (_a) {
5104
- if (response.url) {
5105
- resolve(response.url);
5106
- }
5107
- else {
5108
- reject(new Error(response.error || "error getting attachment url"));
5109
- }
5110
- return [2 /*return*/];
5111
- });
5112
- }); }, request.requestId);
5113
- client.post("getAttachmentUrl", request);
5114
- });
5022
+ exports.useInitMessage = useInitMessage;
5023
+ var useCustomMessages = function (callback, handles) {
5024
+ (0, react_1.useEffect)(function () {
5025
+ client.addCustomMessageListener(callback, handles);
5026
+ return function () { client.removeCustomMessageListener(); };
5027
+ }, []);
5028
+ };
5029
+ exports.useCustomMessages = useCustomMessages;
5030
+ var useDecorateContent = function (callback) {
5031
+ (0, react_1.useEffect)(function () {
5032
+ client.addDecorateContentListener(callback);
5033
+ return function () { return client.removeDecorateContentListener(); };
5034
+ }, []);
5035
+ };
5036
+ exports.useDecorateContent = useDecorateContent;
5037
+ var useAutoSetHeight = function () {
5038
+ var initMessage = (0, exports.useInitMessage)();
5039
+ (0, react_1.useEffect)(function () {
5040
+ if (initMessage) {
5041
+ var body_1 = document.body;
5042
+ var html_1 = document.documentElement;
5043
+ var updateHeight_1 = function () {
5044
+ var height = Math.max(body_1.scrollHeight, body_1.offsetHeight, html_1.clientHeight, html_1.scrollHeight, html_1.offsetHeight);
5045
+ client.setHeight(height);
5046
+ };
5047
+ var observer_1 = new resize_observer_polyfill_1.default(function () { return updateHeight_1(); });
5048
+ if (body_1) {
5049
+ observer_1.observe(body_1);
5050
+ }
5051
+ return function () { return observer_1.disconnect(); };
5052
+ }
5053
+ }, [initMessage]);
5115
5054
  };
5116
- exports.getAttachmentUrl = getAttachmentUrl;
5117
- var sendReportItemAnswer = function (request) {
5118
- (0, client_1.getClient)().post("reportItemAnswer", request);
5055
+ exports.useAutoSetHeight = useAutoSetHeight;
5056
+ // tslint:disable-next-line:max-line-length
5057
+ var useReportItem = function (_a) {
5058
+ var metadata = _a.metadata, handler = _a.handler;
5059
+ (0, react_1.useEffect)(function () {
5060
+ client.addGetReportItemAnswerListener(handler);
5061
+ client.notifyReportItemClientReady(metadata);
5062
+ return function () { return client.removeGetReportItemAnswerListener(); };
5063
+ }, []);
5119
5064
  };
5120
- exports.sendReportItemAnswer = sendReportItemAnswer;
5121
- var setOnUnload = function (onUnload) {
5122
- (0, client_1.getClient)().setOnUnload(onUnload);
5065
+ exports.useReportItem = useReportItem;
5066
+ exports.DefaultAccessibilitySettings = {
5067
+ fontSize: "normal",
5068
+ fontSizeInPx: 16,
5069
+ fontType: "normal",
5070
+ fontFamilyForType: (0, accessibility_1.getFamilyForFontType)("normal"),
5123
5071
  };
5124
- exports.setOnUnload = setOnUnload;
5125
- var sendCustomMessage = function (customMessage) {
5126
- (0, client_1.getClient)().post("customMessage", customMessage);
5072
+ var useAccessibility = function (props) {
5073
+ var _a = props || {}, updateHtmlFontSize = _a.updateHtmlFontSize, addBodyClass = _a.addBodyClass, fontFamilySelector = _a.fontFamilySelector;
5074
+ var initMessage = (0, exports.useInitMessage)();
5075
+ var _b = (0, react_1.useState)(exports.DefaultAccessibilitySettings), accessibility = _b[0], setAccessibility = _b[1];
5076
+ // text may be optional while font type setting is rolled out from staging to production through AP
5077
+ var normalizeClass = function (text) { return (text || "").toLowerCase().replace(/\s/, "-"); };
5078
+ (0, react_1.useEffect)(function () {
5079
+ var _a;
5080
+ if (initMessage && initMessage.mode === "runtime") {
5081
+ var _accessibility = initMessage.accessibility || exports.DefaultAccessibilitySettings;
5082
+ var fontSize = _accessibility.fontSize, fontSizeInPx = _accessibility.fontSizeInPx, fontType = _accessibility.fontType, fontFamilyForType = _accessibility.fontFamilyForType;
5083
+ setAccessibility(_accessibility);
5084
+ if (updateHtmlFontSize || addBodyClass || fontFamilySelector) {
5085
+ var html = document.getElementsByTagName("html").item(0);
5086
+ var body = document.getElementsByTagName("body").item(0);
5087
+ if (updateHtmlFontSize && html && fontSizeInPx) {
5088
+ html.style.fontSize = fontSizeInPx + "px";
5089
+ }
5090
+ if (addBodyClass && body) {
5091
+ body.classList.add("font-size-" + normalizeClass(fontSize));
5092
+ body.classList.add("font-type-" + normalizeClass(fontType));
5093
+ }
5094
+ if (fontFamilySelector && fontFamilyForType) {
5095
+ var style = document.createElement("style");
5096
+ document.head.appendChild(style);
5097
+ (_a = style.sheet) === null || _a === void 0 ? void 0 : _a.insertRule(fontFamilySelector + " { font-family: " + fontFamilyForType + "; }", 0);
5098
+ }
5099
+ }
5100
+ }
5101
+ }, [initMessage, updateHtmlFontSize, addBodyClass, fontFamilySelector]);
5102
+ return accessibility;
5127
5103
  };
5128
- exports.sendCustomMessage = sendCustomMessage;
5104
+ exports.useAccessibility = useAccessibility;
5129
5105
 
5130
5106
 
5131
5107
  /***/ }),
5132
5108
 
5133
- /***/ "./src/interactive-api-client/client.ts":
5134
- /*!**********************************************!*\
5135
- !*** ./src/interactive-api-client/client.ts ***!
5136
- \**********************************************/
5109
+ /***/ "./src/interactive-api-client/in-frame.ts":
5110
+ /*!************************************************!*\
5111
+ !*** ./src/interactive-api-client/in-frame.ts ***!
5112
+ \************************************************/
5137
5113
  /*! no static exports found */
5138
5114
  /***/ (function(module, exports, __webpack_require__) {
5139
5115
 
5140
5116
  "use strict";
5141
5117
 
5142
- var __assign = (this && this.__assign) || function () {
5143
- __assign = Object.assign || function(t) {
5144
- for (var s, i = 1, n = arguments.length; i < n; i++) {
5145
- s = arguments[i];
5146
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
5147
- t[p] = s[p];
5148
- }
5149
- return t;
5150
- };
5151
- return __assign.apply(this, arguments);
5152
- };
5153
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
5154
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
5155
- return new (P || (P = Promise))(function (resolve, reject) {
5156
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5157
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
5158
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
5159
- step((generator = generator.apply(thisArg, _arguments || [])).next());
5160
- });
5161
- };
5162
- var __generator = (this && this.__generator) || function (thisArg, body) {
5163
- var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
5164
- return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
5165
- function verb(n) { return function (v) { return step([n, v]); }; }
5166
- function step(op) {
5167
- if (f) throw new TypeError("Generator is already executing.");
5168
- while (_) try {
5169
- if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
5170
- if (y = 0, t) op = [op[0] & 2, t.value];
5171
- switch (op[0]) {
5172
- case 0: case 1: t = op; break;
5173
- case 4: _.label++; return { value: op[1], done: false };
5174
- case 5: _.label++; y = op[1]; op = [0]; continue;
5175
- case 7: op = _.ops.pop(); _.trys.pop(); continue;
5176
- default:
5177
- if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
5178
- if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
5179
- if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
5180
- if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
5181
- if (t[2]) _.ops.pop();
5182
- _.trys.pop(); continue;
5183
- }
5184
- op = body.call(thisArg, _);
5185
- } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
5186
- if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
5187
- }
5188
- };
5189
- var __rest = (this && this.__rest) || function (s, e) {
5190
- var t = {};
5191
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
5192
- t[p] = s[p];
5193
- if (s != null && typeof Object.getOwnPropertySymbols === "function")
5194
- for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
5195
- if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
5196
- t[p[i]] = s[p[i]];
5197
- }
5198
- return t;
5199
- };
5200
5118
  Object.defineProperty(exports, "__esModule", { value: true });
5201
- exports.Client = exports.getClient = void 0;
5202
- // iframe phone uses 1 listener per message type so we multiplex over 1 listener in this code
5203
- // to allow callbacks to optionally be tied to a requestId. This allows us to have multiple listeners
5204
- // to the same message and auto-removing listeners when a requestId is given.
5205
- var iframePhone = __webpack_require__(/*! iframe-phone */ "./node_modules/iframe-phone/main.js");
5206
- var in_frame_1 = __webpack_require__(/*! ./in-frame */ "./src/interactive-api-client/in-frame.ts");
5207
- var managed_state_1 = __webpack_require__(/*! ./managed-state */ "./src/interactive-api-client/managed-state.ts");
5208
- var parseJSONIfString = function (data) {
5209
- // Note that we don't want to call JSON.parse for an empty string.
5119
+ exports.inIframe = void 0;
5120
+ var _inIframe = (function () {
5210
5121
  try {
5211
- return typeof data === "string" ? JSON.parse(data) : data;
5212
- }
5213
- catch (_a) {
5214
- // If JSON string is malformed, it's an empty string, or not a JSON at all, return the original value.
5215
- return data;
5122
+ return window.self !== window.top;
5216
5123
  }
5217
- };
5218
- var phoneInitialized = function () { return iframePhone.getIFrameEndpoint().getListenerNames().length > 0; };
5219
- var clientInstance;
5220
- var getClient = function () {
5221
- // !phoneInitialized() part isn't really necessary. But it's fine in web browser and it helps in testing environment.
5222
- // Tests can reset mock iframe phone and get new Client instance.
5223
- if (!clientInstance || !phoneInitialized()) {
5224
- clientInstance = new Client();
5124
+ catch (e) {
5125
+ return true;
5225
5126
  }
5226
- return clientInstance;
5127
+ })();
5128
+ var inIframe = function () { return _inIframe; };
5129
+ exports.inIframe = inIframe;
5130
+
5131
+
5132
+ /***/ }),
5133
+
5134
+ /***/ "./src/interactive-api-client/index.ts":
5135
+ /*!*********************************************!*\
5136
+ !*** ./src/interactive-api-client/index.ts ***!
5137
+ \*********************************************/
5138
+ /*! no static exports found */
5139
+ /***/ (function(module, exports, __webpack_require__) {
5140
+
5141
+ "use strict";
5142
+
5143
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
5144
+ if (k2 === undefined) k2 = k;
5145
+ Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
5146
+ }) : (function(o, m, k, k2) {
5147
+ if (k2 === undefined) k2 = k;
5148
+ o[k2] = m[k];
5149
+ }));
5150
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
5151
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
5227
5152
  };
5228
- exports.getClient = getClient;
5229
- /**
5230
- * This class is intended to provide basic helpers (like `post()` or `add/removeListener`), maintain client-specific
5231
- * state, and generally be as minimal as possible. Most of the client-specific helpers and logic can be implemented
5232
- * in api.ts or hooks.ts (or both so the client app has choice).
5233
- */
5234
- var Client = /** @class */ (function () {
5235
- function Client() {
5236
- var _this = this;
5237
- this.phone = iframePhone.getIFrameEndpoint();
5238
- this.managedState = new managed_state_1.ManagedState();
5239
- this.listeners = {};
5240
- this.requestId = 1;
5241
- this.onUnload = undefined;
5242
- this.setSupportedFeatures = function (request) {
5243
- var newRequest = request;
5244
- if (_this.customMessagesHandled) {
5245
- var features = request.features, others = __rest(request, ["features"]);
5246
- features.customMessages = { handles: _this.customMessagesHandled };
5247
- newRequest = __assign({ features: features }, others);
5248
- }
5249
- _this.post("supportedFeatures", newRequest);
5250
- };
5251
- this.setOnUnload = function (onUnload) {
5252
- _this.onUnload = onUnload;
5253
- };
5254
- if (!(0, in_frame_1.inIframe)()) {
5255
- // tslint:disable-next-line:no-console
5256
- console.warn("Interactive API is meant to be used in iframe");
5257
- }
5258
- if (phoneInitialized()) {
5259
- throw new Error("IframePhone has been initialized previously. Only one Client instance is allowed.");
5260
- }
5261
- this.connect();
5262
- // Warn users when they want to reload page before the data gets sent to LARA.
5263
- window.addEventListener("beforeunload", function (e) {
5264
- if (_this.managedState.interactiveStateDirty) {
5265
- // Browser will display different message anyway, but returnValue must be set.
5266
- e.returnValue = "State has not been saved. Are you sure you want to leave this page?";
5267
- }
5268
- return e;
5269
- });
5270
- }
5271
- Client.prototype.getNextRequestId = function () {
5272
- return this.requestId++;
5273
- };
5274
- Client.prototype.post = function (message, content) {
5275
- this.phone.post(message, content);
5276
- };
5277
- Client.prototype.addListener = function (message, callback, requestId) {
5278
- var _this = this;
5279
- if (this.phone) {
5280
- // add either a generic message listener (no requestId) or an auto-removing request listener
5281
- // note: we may have multiple listeners on the same generic message
5282
- this.listeners[message] = this.listeners[message] || [];
5283
- var noExistingListener = this.listeners[message].length === 0;
5284
- this.listeners[message].push({ requestId: requestId, callback: callback });
5285
- // iframe-phone only handles 1 listener per message so add the listener if we haven't already
5286
- if (noExistingListener) {
5287
- this.phone.addListener(message, function (content) {
5288
- // strip requestId from the response so callbacks don't see it
5289
- var contentRequestId = content ? content.requestId : undefined;
5290
- if (content) {
5291
- delete content.requestId;
5292
- }
5293
- _this.listeners[message].forEach(function (listener) {
5294
- // note: requestId can be undefined for listeners to Lara messages
5295
- // that aren't responses to one-time requests
5296
- if (listener.requestId === contentRequestId) {
5297
- listener.callback(content);
5298
- }
5299
- });
5300
- // if a request id was returned by lara auto-remove it from the listeners as it is a
5301
- // response to a one-time request
5302
- if (contentRequestId) {
5303
- _this.removeListener(message, contentRequestId);
5304
- }
5305
- });
5153
+ Object.defineProperty(exports, "__esModule", { value: true });
5154
+ __exportStar(__webpack_require__(/*! ./types */ "./src/interactive-api-client/types.ts"), exports);
5155
+ __exportStar(__webpack_require__(/*! ./metadata-types */ "./src/interactive-api-client/metadata-types.ts"), exports);
5156
+ __exportStar(__webpack_require__(/*! ./in-frame */ "./src/interactive-api-client/in-frame.ts"), exports);
5157
+ __exportStar(__webpack_require__(/*! ./api */ "./src/interactive-api-client/api.ts"), exports);
5158
+ __exportStar(__webpack_require__(/*! ./hooks */ "./src/interactive-api-client/hooks.ts"), exports);
5159
+ __exportStar(__webpack_require__(/*! ./client */ "./src/interactive-api-client/client.ts"), exports);
5160
+
5161
+
5162
+ /***/ }),
5163
+
5164
+ /***/ "./src/interactive-api-client/managed-state.ts":
5165
+ /*!*****************************************************!*\
5166
+ !*** ./src/interactive-api-client/managed-state.ts ***!
5167
+ \*****************************************************/
5168
+ /*! no static exports found */
5169
+ /***/ (function(module, exports, __webpack_require__) {
5170
+
5171
+ "use strict";
5172
+
5173
+ Object.defineProperty(exports, "__esModule", { value: true });
5174
+ exports.ManagedState = void 0;
5175
+ var eventemitter2_1 = __webpack_require__(/*! eventemitter2 */ "./node_modules/eventemitter2/lib/eventemitter2.js");
5176
+ var deepFreeze = __webpack_require__(/*! deep-freeze */ "./node_modules/deep-freeze/index.js");
5177
+ var ManagedState = /** @class */ (function () {
5178
+ function ManagedState() {
5179
+ this.interactiveStateDirty = false;
5180
+ this._initMessage = null;
5181
+ // State variables are kept separately from initMessage, as they might get updated. For client user convenience,
5182
+ // this state is kept here and all the updates emit appropriate event.
5183
+ this._interactiveState = null;
5184
+ this._authoredState = null;
5185
+ this._globalInteractiveState = null;
5186
+ this.emitter = new eventemitter2_1.EventEmitter2({
5187
+ maxListeners: Infinity
5188
+ });
5189
+ }
5190
+ Object.defineProperty(ManagedState.prototype, "initMessage", {
5191
+ get: function () {
5192
+ return this._initMessage;
5193
+ },
5194
+ set: function (value) {
5195
+ // null is an object too.
5196
+ if (value !== null && typeof value === "object") {
5197
+ value = deepFreeze(value);
5306
5198
  }
5307
- return true;
5308
- }
5309
- return false;
5310
- };
5311
- Client.prototype.removeListener = function (message, requestId, callback) {
5312
- if (this.listeners[message]) {
5313
- // When callback is provided, remove this particular callback.
5314
- // Otherwise try to use requestId.
5315
- if (callback) {
5316
- this.listeners[message] = this.listeners[message].filter(function (l) { return l.callback !== callback; });
5199
+ this._initMessage = value;
5200
+ this.emit("initInteractive", value);
5201
+ },
5202
+ enumerable: false,
5203
+ configurable: true
5204
+ });
5205
+ Object.defineProperty(ManagedState.prototype, "interactiveState", {
5206
+ get: function () {
5207
+ return this._interactiveState;
5208
+ },
5209
+ set: function (value) {
5210
+ // null is an object too.
5211
+ if (value !== null && typeof value === "object") {
5212
+ value = deepFreeze(value);
5317
5213
  }
5318
- else {
5319
- // note: requestId can be undefined when using it as a generic listener
5320
- this.listeners[message] = this.listeners[message].filter(function (l) { return l.requestId !== requestId; });
5214
+ this._interactiveState = value;
5215
+ this.emit("interactiveStateUpdated", value);
5216
+ this.interactiveStateDirty = true;
5217
+ },
5218
+ enumerable: false,
5219
+ configurable: true
5220
+ });
5221
+ Object.defineProperty(ManagedState.prototype, "authoredState", {
5222
+ get: function () {
5223
+ return this._authoredState;
5224
+ },
5225
+ set: function (value) {
5226
+ // null is an object too.
5227
+ if (value !== null && typeof value === "object") {
5228
+ value = deepFreeze(value);
5321
5229
  }
5322
- // if no more local listeners exist remove it from iframe-phone
5323
- if (this.listeners[message].length === 0) {
5324
- this.phone.removeListener(message);
5230
+ this._authoredState = value;
5231
+ this.emit("authoredStateUpdated", value);
5232
+ },
5233
+ enumerable: false,
5234
+ configurable: true
5235
+ });
5236
+ Object.defineProperty(ManagedState.prototype, "globalInteractiveState", {
5237
+ get: function () {
5238
+ return this._globalInteractiveState;
5239
+ },
5240
+ set: function (value) {
5241
+ // null is an object too.
5242
+ if (value !== null && typeof value === "object") {
5243
+ value = deepFreeze(value);
5325
5244
  }
5326
- return true;
5327
- }
5328
- return false;
5245
+ this._globalInteractiveState = value;
5246
+ this.emit("globalInteractiveStateUpdated", value);
5247
+ },
5248
+ enumerable: false,
5249
+ configurable: true
5250
+ });
5251
+ ManagedState.prototype.emit = function (event, content) {
5252
+ this.emitter.emit(event, content);
5329
5253
  };
5330
- Client.prototype.connect = function () {
5331
- var _this = this;
5332
- this.phone = iframePhone.getIFrameEndpoint();
5333
- this.addListener("initInteractive", function (newInitMessage) {
5334
- _this.managedState.initMessage = newInitMessage;
5335
- // parseJSONIfString is used below quite a few times, as LARA and report are not consistent about format.
5336
- // Sometimes they send string (report page), sometimes already parsed JSON (authoring, runtime).
5337
- if (newInitMessage.mode === "reportItem") {
5338
- _this.managedState.authoredState = {};
5339
- }
5340
- else {
5341
- _this.managedState.authoredState = parseJSONIfString(newInitMessage.authoredState);
5342
- }
5343
- if (newInitMessage.mode === "runtime" || newInitMessage.mode === "report") {
5344
- _this.managedState.interactiveState = parseJSONIfString(newInitMessage.interactiveState);
5345
- // Don't consider initial state to be dirty, as user would see warnings while trying to leave page even
5346
- // without making any change.
5347
- _this.managedState.interactiveStateDirty = false;
5348
- }
5349
- if (newInitMessage.mode === "runtime") {
5350
- _this.managedState.globalInteractiveState = parseJSONIfString(newInitMessage.globalInteractiveState);
5351
- }
5352
- });
5353
- this.addListener("getInteractiveState", function (options) { return __awaiter(_this, void 0, void 0, function () {
5354
- var finalState;
5355
- return __generator(this, function (_a) {
5356
- switch (_a.label) {
5357
- case 0:
5358
- if (!((options === null || options === void 0 ? void 0 : options.unloading) && this.onUnload)) return [3 /*break*/, 2];
5359
- return [4 /*yield*/, this.onUnload(options)];
5360
- case 1:
5361
- finalState = _a.sent();
5362
- if (finalState) {
5363
- this.managedState.interactiveState = finalState;
5364
- }
5365
- _a.label = 2;
5366
- case 2:
5367
- this.post("interactiveState", this.managedState.interactiveState);
5368
- this.managedState.interactiveStateDirty = false;
5369
- return [2 /*return*/];
5370
- }
5371
- });
5372
- }); });
5373
- this.addListener("loadInteractiveGlobal", function (globalState) {
5374
- _this.managedState.globalInteractiveState = parseJSONIfString(globalState);
5375
- });
5376
- this.phone.initialize();
5254
+ ManagedState.prototype.on = function (event, handler) {
5255
+ this.emitter.on(event, handler);
5377
5256
  };
5378
- return Client;
5257
+ ManagedState.prototype.off = function (event, handler) {
5258
+ this.emitter.off(event, handler);
5259
+ };
5260
+ ManagedState.prototype.once = function (event, handler) {
5261
+ this.emitter.once(event, handler);
5262
+ };
5263
+ return ManagedState;
5379
5264
  }());
5380
- exports.Client = Client;
5265
+ exports.ManagedState = ManagedState;
5266
+
5267
+
5268
+ /***/ }),
5269
+
5270
+ /***/ "./src/interactive-api-client/metadata-types.ts":
5271
+ /*!******************************************************!*\
5272
+ !*** ./src/interactive-api-client/metadata-types.ts ***!
5273
+ \******************************************************/
5274
+ /*! no static exports found */
5275
+ /***/ (function(module, exports, __webpack_require__) {
5276
+
5277
+ "use strict";
5278
+
5279
+ // Each time these interfaces are updated, it might be necessary to also update base_interactive.rb
5280
+ // and interactive_run_state.rb files that process this data passed from interactives and send
5281
+ // to report service and portal.
5282
+ Object.defineProperty(exports, "__esModule", { value: true });
5283
+
5284
+
5285
+ /***/ }),
5286
+
5287
+ /***/ "./src/interactive-api-client/node_modules/iframe-phone/lib/iframe-endpoint.js":
5288
+ /*!*************************************************************************************!*\
5289
+ !*** ./src/interactive-api-client/node_modules/iframe-phone/lib/iframe-endpoint.js ***!
5290
+ \*************************************************************************************/
5291
+ /*! no static exports found */
5292
+ /***/ (function(module, exports, __webpack_require__) {
5293
+
5294
+ var structuredClone = __webpack_require__(/*! ./structured-clone */ "./src/interactive-api-client/node_modules/iframe-phone/lib/structured-clone.js");
5295
+ var HELLO_INTERVAL_LENGTH = 200;
5296
+ var HELLO_TIMEOUT_LENGTH = 60000;
5297
+
5298
+ function IFrameEndpoint() {
5299
+ var listeners = {};
5300
+ var isInitialized = false;
5301
+ var connected = false;
5302
+ var postMessageQueue = [];
5303
+ var helloInterval;
5304
+
5305
+ function postToParent(message) {
5306
+ // See http://dev.opera.com/articles/view/window-postmessage-messagechannel/#crossdoc
5307
+ // https://github.com/Modernizr/Modernizr/issues/388
5308
+ // http://jsfiddle.net/ryanseddon/uZTgD/2/
5309
+ if (structuredClone.supported()) {
5310
+ window.parent.postMessage(message, '*');
5311
+ } else {
5312
+ window.parent.postMessage(JSON.stringify(message), '*');
5313
+ }
5314
+ }
5315
+
5316
+ function post(type, content) {
5317
+ var message;
5318
+ // Message object can be constructed from 'type' and 'content' arguments or it can be passed
5319
+ // as the first argument.
5320
+ if (arguments.length === 1 && typeof type === 'object' && typeof type.type === 'string') {
5321
+ message = type;
5322
+ } else {
5323
+ message = {
5324
+ type: type,
5325
+ content: content
5326
+ };
5327
+ }
5328
+ if (connected) {
5329
+ postToParent(message);
5330
+ } else {
5331
+ postMessageQueue.push(message);
5332
+ }
5333
+ }
5334
+
5335
+ function postHello() {
5336
+ postToParent({
5337
+ type: 'hello'
5338
+ });
5339
+ }
5340
+
5341
+ function addListener(type, fn) {
5342
+ listeners[type] = fn;
5343
+ }
5344
+
5345
+ function removeListener(type) {
5346
+ delete listeners[type];
5347
+ }
5348
+
5349
+ function removeAllListeners() {
5350
+ listeners = {};
5351
+ }
5352
+
5353
+ function getListenerNames() {
5354
+ return Object.keys(listeners);
5355
+ }
5381
5356
 
5357
+ function messageListener(message) {
5358
+ // Anyone can send us a message. Only pay attention to messages from parent.
5359
+ if (message.source !== window.parent) return;
5360
+ var messageData = message.data;
5361
+ if (typeof messageData === 'string') messageData = JSON.parse(messageData);
5382
5362
 
5383
- /***/ }),
5363
+ if (!connected && messageData.type === 'hello') {
5364
+ connected = true;
5365
+ stopPostingHello();
5366
+ while (postMessageQueue.length > 0) {
5367
+ post(postMessageQueue.shift());
5368
+ }
5369
+ }
5384
5370
 
5385
- /***/ "./src/interactive-api-client/hooks.ts":
5386
- /*!*********************************************!*\
5387
- !*** ./src/interactive-api-client/hooks.ts ***!
5388
- \*********************************************/
5389
- /*! no static exports found */
5390
- /***/ (function(module, exports, __webpack_require__) {
5371
+ if (connected && listeners[messageData.type]) {
5372
+ listeners[messageData.type](messageData.content);
5373
+ }
5374
+ }
5391
5375
 
5392
- "use strict";
5376
+ function disconnect() {
5377
+ connected = false;
5378
+ stopPostingHello();
5379
+ removeAllListeners();
5380
+ window.removeEventListener('message', messageListener);
5381
+ }
5393
5382
 
5394
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
5395
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
5396
- return new (P || (P = Promise))(function (resolve, reject) {
5397
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5398
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
5399
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
5400
- step((generator = generator.apply(thisArg, _arguments || [])).next());
5401
- });
5402
- };
5403
- var __generator = (this && this.__generator) || function (thisArg, body) {
5404
- var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
5405
- return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
5406
- function verb(n) { return function (v) { return step([n, v]); }; }
5407
- function step(op) {
5408
- if (f) throw new TypeError("Generator is already executing.");
5409
- while (_) try {
5410
- if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
5411
- if (y = 0, t) op = [op[0] & 2, t.value];
5412
- switch (op[0]) {
5413
- case 0: case 1: t = op; break;
5414
- case 4: _.label++; return { value: op[1], done: false };
5415
- case 5: _.label++; y = op[1]; op = [0]; continue;
5416
- case 7: op = _.ops.pop(); _.trys.pop(); continue;
5417
- default:
5418
- if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
5419
- if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
5420
- if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
5421
- if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
5422
- if (t[2]) _.ops.pop();
5423
- _.trys.pop(); continue;
5424
- }
5425
- op = body.call(thisArg, _);
5426
- } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
5427
- if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
5428
- }
5429
- };
5430
- Object.defineProperty(exports, "__esModule", { value: true });
5431
- exports.useAccessibility = exports.DefaultAccessibilitySettings = exports.useReportItem = exports.useAutoSetHeight = exports.useDecorateContent = exports.useCustomMessages = exports.useInitMessage = exports.useGlobalInteractiveState = exports.useAuthoredState = exports.useInteractiveState = void 0;
5432
- var react_1 = __webpack_require__(/*! react */ "react");
5433
- var resize_observer_polyfill_1 = __webpack_require__(/*! resize-observer-polyfill */ "./node_modules/resize-observer-polyfill/dist/ResizeObserver.es.js");
5434
- var client = __webpack_require__(/*! ./api */ "./src/interactive-api-client/api.ts");
5435
- var accessibility_1 = __webpack_require__(/*! ../shared/accessibility */ "./src/shared/accessibility.ts");
5436
- var handleUpdate = function (newStateOrUpdateFunc, prevState) {
5437
- if (typeof newStateOrUpdateFunc === "function") {
5438
- return newStateOrUpdateFunc(prevState);
5383
+ /**
5384
+ Initialize communication with the parent frame. This should not be called until the app's custom
5385
+ listeners are registered (via our 'addListener' public method) because, once we open the
5386
+ communication, the parent window may send any messages it may have queued. Messages for which
5387
+ we don't have handlers will be silently ignored.
5388
+ */
5389
+ function initialize() {
5390
+ if (isInitialized) {
5391
+ return;
5439
5392
  }
5440
- else {
5441
- return newStateOrUpdateFunc;
5393
+ isInitialized = true;
5394
+ if (window.parent === window) return;
5395
+
5396
+ // We kick off communication with the parent window by sending a "hello" message. Then we wait
5397
+ // for a handshake (another "hello" message) from the parent window.
5398
+ startPostingHello();
5399
+ window.addEventListener('message', messageListener, false);
5400
+ }
5401
+
5402
+ function startPostingHello() {
5403
+ if (helloInterval) {
5404
+ stopPostingHello();
5442
5405
  }
5406
+ helloInterval = window.setInterval(postHello, HELLO_INTERVAL_LENGTH);
5407
+ window.setTimeout(stopPostingHello, HELLO_TIMEOUT_LENGTH);
5408
+ // Post the first msg immediately.
5409
+ postHello();
5410
+ }
5411
+
5412
+ function stopPostingHello() {
5413
+ window.clearInterval(helloInterval);
5414
+ helloInterval = null;
5415
+ }
5416
+
5417
+ // Public API.
5418
+ return {
5419
+ initialize: initialize,
5420
+ getListenerNames: getListenerNames,
5421
+ addListener: addListener,
5422
+ removeListener: removeListener,
5423
+ removeAllListeners: removeAllListeners,
5424
+ disconnect: disconnect,
5425
+ post: post
5426
+ };
5427
+ }
5428
+
5429
+ var instance = null;
5430
+
5431
+ // IFrameEndpoint is a singleton, as iframe can't have multiple parents anyway.
5432
+ module.exports = function getIFrameEndpoint() {
5433
+ if (!instance) {
5434
+ instance = new IFrameEndpoint();
5435
+ }
5436
+ return instance;
5443
5437
  };
5444
- var useInteractiveState = function () {
5445
- var _a = (0, react_1.useState)(null), interactiveState = _a[0], setInteractiveState = _a[1];
5446
- (0, react_1.useEffect)(function () {
5447
- setInteractiveState(client.getInteractiveState());
5448
- // Setup client event listeners. They will ensure that another instance of this hook (or anything else
5449
- // using client directly) makes changes to interactive state, this hook will receive these changes.
5450
- var handleStateUpdate = function (newState) {
5451
- setInteractiveState(newState);
5452
- };
5453
- client.addInteractiveStateListener(handleStateUpdate);
5454
- return function () {
5455
- client.removeInteractiveStateListener(handleStateUpdate);
5456
- };
5457
- }, []);
5458
- var handleSetInteractiveState = (0, react_1.useCallback)(function (stateOrUpdateFunc) {
5459
- // Use client-managed state, as it should be up to date. React-managed state might not be the most recent version.
5460
- var newState = handleUpdate(stateOrUpdateFunc, client.getInteractiveState());
5461
- setInteractiveState(newState);
5462
- client.setInteractiveState(newState);
5463
- }, []);
5464
- return { interactiveState: interactiveState, setInteractiveState: handleSetInteractiveState };
5465
- };
5466
- exports.useInteractiveState = useInteractiveState;
5467
- var useAuthoredState = function () {
5468
- var _a = (0, react_1.useState)(null), authoredState = _a[0], setAuthoredState = _a[1];
5469
- (0, react_1.useEffect)(function () {
5470
- // Note that we need to update authoredState exactly in this moment, right before setting up event listeners.
5471
- // It can't be done above using initial useState value. There's a little delay between initial render and calling
5472
- // useEffect. If client's authoredState gets updated before the listener is added, this hook will have outdated
5473
- // value. It's not only a theoretical issue, it was actually happening in Safari:
5474
- // https://www.pivotaltracker.com/story/show/174154314
5475
- // initInteractive message that includes authoredAuthored message was received between initial render and calling
5476
- // client.addAuthoredStateListener, so the state update was lost.
5477
- setAuthoredState(client.getAuthoredState());
5478
- // Setup client event listeners. They will ensure that another instance of this hook (or anything else
5479
- // using client directly) makes changes to authored state, this hook will receive these changes.
5480
- var handleStateUpdate = function (newState) {
5481
- setAuthoredState(newState);
5482
- };
5483
- client.addAuthoredStateListener(handleStateUpdate);
5484
- return function () {
5485
- client.removeAuthoredStateListener(handleStateUpdate);
5486
- };
5487
- }, []);
5488
- var handleSetAuthoredState = (0, react_1.useCallback)(function (stateOrUpdateFunc) {
5489
- // Use client-managed state, as it should be up to date. React-managed state might not be the most recent version.
5490
- var newState = handleUpdate(stateOrUpdateFunc, client.getAuthoredState());
5491
- setAuthoredState(newState);
5492
- client.setAuthoredState(newState);
5493
- }, []);
5494
- return { authoredState: authoredState, setAuthoredState: handleSetAuthoredState };
5495
- };
5496
- exports.useAuthoredState = useAuthoredState;
5497
- var useGlobalInteractiveState = function () {
5498
- var _a = (0, react_1.useState)(null), globalInteractiveState = _a[0], setGlobalInteractiveState = _a[1];
5499
- (0, react_1.useEffect)(function () {
5500
- setGlobalInteractiveState(client.getGlobalInteractiveState());
5501
- // Setup client event listeners. They will ensure that another instance of this hook (or anything else
5502
- // using client directly) makes changes to global interactive state, this hook will receive these changes.
5503
- var handleStateUpdate = function (newState) {
5504
- setGlobalInteractiveState(newState);
5505
- };
5506
- client.addGlobalInteractiveStateListener(handleStateUpdate);
5507
- return function () {
5508
- client.removeGlobalInteractiveStateListener(handleStateUpdate);
5509
- };
5510
- }, []);
5511
- // tslint:disable-next-line:max-line-length
5512
- var handleSetGlobalInteractiveState = (0, react_1.useCallback)(function (stateOrUpdateFunc) {
5513
- // Use client-managed state, as it should be up to date. React-managed state might not be the most recent version.
5514
- var newState = handleUpdate(stateOrUpdateFunc, client.getGlobalInteractiveState());
5515
- setGlobalInteractiveState(newState);
5516
- client.setGlobalInteractiveState(newState);
5517
- }, []);
5518
- return { globalInteractiveState: globalInteractiveState, setGlobalInteractiveState: handleSetGlobalInteractiveState };
5519
- };
5520
- exports.useGlobalInteractiveState = useGlobalInteractiveState;
5521
- // tslint:disable-next-line:max-line-length
5522
- var useInitMessage = function () {
5523
- var _a = (0, react_1.useState)(null), initMessage = _a[0], setInitMessage = _a[1];
5524
- (0, react_1.useEffect)(function () {
5525
- // useEffect callback can't be async.
5526
- (function () { return __awaiter(void 0, void 0, void 0, function () {
5527
- var initMsg;
5528
- return __generator(this, function (_a) {
5529
- switch (_a.label) {
5530
- case 0: return [4 /*yield*/, client.getInitInteractiveMessage()];
5531
- case 1:
5532
- initMsg = _a.sent();
5533
- setInitMessage(initMsg);
5534
- return [2 /*return*/];
5535
- }
5536
- });
5537
- }); })();
5538
- }, []);
5539
- return initMessage;
5540
- };
5541
- exports.useInitMessage = useInitMessage;
5542
- var useCustomMessages = function (callback, handles) {
5543
- (0, react_1.useEffect)(function () {
5544
- client.addCustomMessageListener(callback, handles);
5545
- return function () { client.removeCustomMessageListener(); };
5546
- }, []);
5547
- };
5548
- exports.useCustomMessages = useCustomMessages;
5549
- var useDecorateContent = function (callback) {
5550
- (0, react_1.useEffect)(function () {
5551
- client.addDecorateContentListener(callback);
5552
- return function () { return client.removeDecorateContentListener(); };
5553
- }, []);
5554
- };
5555
- exports.useDecorateContent = useDecorateContent;
5556
- var useAutoSetHeight = function () {
5557
- var initMessage = (0, exports.useInitMessage)();
5558
- (0, react_1.useEffect)(function () {
5559
- if (initMessage) {
5560
- var body_1 = document.body;
5561
- var html_1 = document.documentElement;
5562
- var updateHeight_1 = function () {
5563
- var height = Math.max(body_1.scrollHeight, body_1.offsetHeight, html_1.clientHeight, html_1.scrollHeight, html_1.offsetHeight);
5564
- client.setHeight(height);
5565
- };
5566
- var observer_1 = new resize_observer_polyfill_1.default(function () { return updateHeight_1(); });
5567
- if (body_1) {
5568
- observer_1.observe(body_1);
5569
- }
5570
- return function () { return observer_1.disconnect(); };
5571
- }
5572
- }, [initMessage]);
5573
- };
5574
- exports.useAutoSetHeight = useAutoSetHeight;
5575
- // tslint:disable-next-line:max-line-length
5576
- var useReportItem = function (_a) {
5577
- var metadata = _a.metadata, handler = _a.handler;
5578
- (0, react_1.useEffect)(function () {
5579
- client.addGetReportItemAnswerListener(handler);
5580
- client.notifyReportItemClientReady(metadata);
5581
- return function () { return client.removeGetReportItemAnswerListener(); };
5582
- }, []);
5583
- };
5584
- exports.useReportItem = useReportItem;
5585
- exports.DefaultAccessibilitySettings = {
5586
- fontSize: "normal",
5587
- fontSizeInPx: 16,
5588
- fontType: "normal",
5589
- fontFamilyForType: (0, accessibility_1.getFamilyForFontType)("normal"),
5590
- };
5591
- var useAccessibility = function (props) {
5592
- var _a = props || {}, updateHtmlFontSize = _a.updateHtmlFontSize, addBodyClass = _a.addBodyClass, fontFamilySelector = _a.fontFamilySelector;
5593
- var initMessage = (0, exports.useInitMessage)();
5594
- var _b = (0, react_1.useState)(exports.DefaultAccessibilitySettings), accessibility = _b[0], setAccessibility = _b[1];
5595
- // text may be optional while font type setting is rolled out from staging to production through AP
5596
- var normalizeClass = function (text) { return (text || "").toLowerCase().replace(/\s/, "-"); };
5597
- (0, react_1.useEffect)(function () {
5598
- var _a;
5599
- if (initMessage && initMessage.mode === "runtime") {
5600
- var _accessibility = initMessage.accessibility || exports.DefaultAccessibilitySettings;
5601
- var fontSize = _accessibility.fontSize, fontSizeInPx = _accessibility.fontSizeInPx, fontType = _accessibility.fontType, fontFamilyForType = _accessibility.fontFamilyForType;
5602
- setAccessibility(_accessibility);
5603
- if (updateHtmlFontSize || addBodyClass || fontFamilySelector) {
5604
- var html = document.getElementsByTagName("html").item(0);
5605
- var body = document.getElementsByTagName("body").item(0);
5606
- if (updateHtmlFontSize && html && fontSizeInPx) {
5607
- html.style.fontSize = fontSizeInPx + "px";
5608
- }
5609
- if (addBodyClass && body) {
5610
- body.classList.add("font-size-" + normalizeClass(fontSize));
5611
- body.classList.add("font-type-" + normalizeClass(fontType));
5612
- }
5613
- if (fontFamilySelector && fontFamilyForType) {
5614
- var style = document.createElement("style");
5615
- document.head.appendChild(style);
5616
- (_a = style.sheet) === null || _a === void 0 ? void 0 : _a.insertRule(fontFamilySelector + " { font-family: " + fontFamilyForType + "; }", 0);
5617
- }
5618
- }
5438
+
5439
+
5440
+ /***/ }),
5441
+
5442
+ /***/ "./src/interactive-api-client/node_modules/iframe-phone/lib/iframe-phone-rpc-endpoint.js":
5443
+ /*!***********************************************************************************************!*\
5444
+ !*** ./src/interactive-api-client/node_modules/iframe-phone/lib/iframe-phone-rpc-endpoint.js ***!
5445
+ \***********************************************************************************************/
5446
+ /*! no static exports found */
5447
+ /***/ (function(module, exports, __webpack_require__) {
5448
+
5449
+ var ParentEndpoint = __webpack_require__(/*! ./parent-endpoint */ "./src/interactive-api-client/node_modules/iframe-phone/lib/parent-endpoint.js");
5450
+ var getIFrameEndpoint = __webpack_require__(/*! ./iframe-endpoint */ "./src/interactive-api-client/node_modules/iframe-phone/lib/iframe-endpoint.js");
5451
+
5452
+ // Not a real UUID as there's an RFC for that (needed for proper distributed computing).
5453
+ // But in this fairly parochial situation, we just need to be fairly sure to avoid repeats.
5454
+ function getPseudoUUID() {
5455
+ var chars = 'abcdefghijklmnopqrstuvwxyz0123456789';
5456
+ var len = chars.length;
5457
+ var ret = [];
5458
+
5459
+ for (var i = 0; i < 10; i++) {
5460
+ ret.push(chars[Math.floor(Math.random() * len)]);
5461
+ }
5462
+ return ret.join('');
5463
+ }
5464
+
5465
+ module.exports = function IframePhoneRpcEndpoint(handler, namespace, targetWindow, targetOrigin, phone) {
5466
+ var pendingCallbacks = Object.create({});
5467
+
5468
+ // if it's a non-null object, rather than a function, 'handler' is really an options object
5469
+ if (handler && typeof handler === 'object') {
5470
+ namespace = handler.namespace;
5471
+ targetWindow = handler.targetWindow;
5472
+ targetOrigin = handler.targetOrigin;
5473
+ phone = handler.phone;
5474
+ handler = handler.handler;
5475
+ }
5476
+
5477
+ if (!phone) {
5478
+ if (targetWindow === window.parent) {
5479
+ phone = getIFrameEndpoint();
5480
+ phone.initialize();
5481
+ } else {
5482
+ phone = new ParentEndpoint(targetWindow, targetOrigin);
5483
+ }
5484
+ }
5485
+
5486
+ phone.addListener(namespace, function (message) {
5487
+ var callbackObj;
5488
+
5489
+ if (message.messageType === 'call' && typeof this.handler === 'function') {
5490
+ this.handler.call(undefined, message.value, function (returnValue) {
5491
+ phone.post(namespace, {
5492
+ messageType: 'returnValue',
5493
+ uuid: message.uuid,
5494
+ value: returnValue
5495
+ });
5496
+ });
5497
+ } else if (message.messageType === 'returnValue') {
5498
+ callbackObj = pendingCallbacks[message.uuid];
5499
+
5500
+ if (callbackObj) {
5501
+ window.clearTimeout(callbackObj.timeout);
5502
+ if (callbackObj.callback) {
5503
+ callbackObj.callback.call(undefined, message.value);
5619
5504
  }
5620
- }, [initMessage, updateHtmlFontSize, addBodyClass, fontFamilySelector]);
5621
- return accessibility;
5505
+ pendingCallbacks[message.uuid] = null;
5506
+ }
5507
+ }
5508
+ }.bind(this));
5509
+
5510
+ function call(message, callback) {
5511
+ var uuid = getPseudoUUID();
5512
+
5513
+ pendingCallbacks[uuid] = {
5514
+ callback: callback,
5515
+ timeout: window.setTimeout(function () {
5516
+ if (callback) {
5517
+ callback(undefined, new Error("IframePhone timed out waiting for reply"));
5518
+ }
5519
+ }, 2000)
5520
+ };
5521
+
5522
+ phone.post(namespace, {
5523
+ messageType: 'call',
5524
+ uuid: uuid,
5525
+ value: message
5526
+ });
5527
+ }
5528
+
5529
+ function disconnect() {
5530
+ phone.disconnect();
5531
+ }
5532
+
5533
+ this.handler = handler;
5534
+ this.call = call.bind(this);
5535
+ this.disconnect = disconnect.bind(this);
5622
5536
  };
5623
- exports.useAccessibility = useAccessibility;
5624
5537
 
5625
5538
 
5626
- /***/ }),
5539
+ /***/ }),
5540
+
5541
+ /***/ "./src/interactive-api-client/node_modules/iframe-phone/lib/parent-endpoint.js":
5542
+ /*!*************************************************************************************!*\
5543
+ !*** ./src/interactive-api-client/node_modules/iframe-phone/lib/parent-endpoint.js ***!
5544
+ \*************************************************************************************/
5545
+ /*! no static exports found */
5546
+ /***/ (function(module, exports, __webpack_require__) {
5547
+
5548
+ var structuredClone = __webpack_require__(/*! ./structured-clone */ "./src/interactive-api-client/node_modules/iframe-phone/lib/structured-clone.js");
5549
+
5550
+ /**
5551
+ Call as:
5552
+ new ParentEndpoint(targetWindow, targetOrigin, afterConnectedCallback)
5553
+ targetWindow is a WindowProxy object. (Messages will be sent to it)
5554
+
5555
+ targetOrigin is the origin of the targetWindow. (Messages will be restricted to this origin)
5556
+
5557
+ afterConnectedCallback is an optional callback function to be called when the connection is
5558
+ established.
5559
+
5560
+ OR (less secure):
5561
+ new ParentEndpoint(targetIframe, afterConnectedCallback)
5562
+
5563
+ targetIframe is a DOM object (HTMLIframeElement); messages will be sent to its contentWindow.
5564
+
5565
+ afterConnectedCallback is an optional callback function
5566
+
5567
+ In this latter case, targetOrigin will be inferred from the value of the src attribute of the
5568
+ provided DOM object at the time of the constructor invocation. This is less secure because the
5569
+ iframe might have been navigated to an unexpected domain before constructor invocation.
5570
+
5571
+ Note that it is important to specify the expected origin of the iframe's content to safeguard
5572
+ against sending messages to an unexpected domain. This might happen if our iframe is navigated to
5573
+ a third-party URL unexpectedly. Furthermore, having a reference to Window object (as in the first
5574
+ form of the constructor) does not protect against sending a message to the wrong domain. The
5575
+ window object is actualy a WindowProxy which transparently proxies the Window object of the
5576
+ underlying iframe, so that when the iframe is navigated, the "same" WindowProxy now references a
5577
+ completely differeent Window object, possibly controlled by a hostile domain.
5578
+
5579
+ See http://www.esdiscuss.org/topic/a-dom-use-case-that-can-t-be-emulated-with-direct-proxies for
5580
+ more about this weird behavior of WindowProxies (the type returned by <iframe>.contentWindow).
5581
+ */
5582
+
5583
+ module.exports = function ParentEndpoint(targetWindowOrIframeEl, targetOrigin, afterConnectedCallback) {
5584
+ var postMessageQueue = [];
5585
+ var connected = false;
5586
+ var handlers = {};
5587
+ var targetWindowIsIframeElement;
5588
+
5589
+ function getIframeOrigin(iframe) {
5590
+ return iframe.src.match(/(.*?\/\/.*?)\//)[1];
5591
+ }
5592
+
5593
+ function post(type, content) {
5594
+ var message;
5595
+ // Message object can be constructed from 'type' and 'content' arguments or it can be passed
5596
+ // as the first argument.
5597
+ if (arguments.length === 1 && typeof type === 'object' && typeof type.type === 'string') {
5598
+ message = type;
5599
+ } else {
5600
+ message = {
5601
+ type: type,
5602
+ content: content
5603
+ };
5604
+ }
5605
+ if (connected) {
5606
+ var tWindow = getTargetWindow();
5607
+ // if we are laready connected ... send the message
5608
+ // See http://dev.opera.com/articles/view/window-postmessage-messagechannel/#crossdoc
5609
+ // https://github.com/Modernizr/Modernizr/issues/388
5610
+ // http://jsfiddle.net/ryanseddon/uZTgD/2/
5611
+ if (structuredClone.supported()) {
5612
+ tWindow.postMessage(message, targetOrigin);
5613
+ } else {
5614
+ tWindow.postMessage(JSON.stringify(message), targetOrigin);
5615
+ }
5616
+ } else {
5617
+ // else queue up the messages to send after connection complete.
5618
+ postMessageQueue.push(message);
5619
+ }
5620
+ }
5621
+
5622
+ function addListener(messageName, func) {
5623
+ handlers[messageName] = func;
5624
+ }
5625
+
5626
+ function removeListener(messageName) {
5627
+ delete handlers[messageName];
5628
+ }
5629
+
5630
+ function removeAllListeners() {
5631
+ handlers = {};
5632
+ }
5633
+
5634
+ // Note that this function can't be used when IFrame element hasn't been added to DOM yet
5635
+ // (.contentWindow would be null). At the moment risk is purely theoretical, as the parent endpoint
5636
+ // only listens for an incoming 'hello' message and the first time we call this function
5637
+ // is in #receiveMessage handler (so iframe had to be initialized before, as it could send 'hello').
5638
+ // It would become important when we decide to refactor the way how communication is initialized.
5639
+ function getTargetWindow() {
5640
+ if (targetWindowIsIframeElement) {
5641
+ var tWindow = targetWindowOrIframeEl.contentWindow;
5642
+ if (!tWindow) {
5643
+ throw "IFrame element needs to be added to DOM before communication " +
5644
+ "can be started (.contentWindow is not available)";
5645
+ }
5646
+ return tWindow;
5647
+ }
5648
+ return targetWindowOrIframeEl;
5649
+ }
5650
+
5651
+ function receiveMessage(message) {
5652
+ var messageData;
5653
+ if (message.source === getTargetWindow() && (targetOrigin === '*' || message.origin === targetOrigin)) {
5654
+ messageData = message.data;
5655
+ if (typeof messageData === 'string') {
5656
+ messageData = JSON.parse(messageData);
5657
+ }
5658
+ if (handlers[messageData.type]) {
5659
+ handlers[messageData.type](messageData.content);
5660
+ } else {
5661
+ console.log("cant handle type: " + messageData.type);
5662
+ }
5663
+ }
5664
+ }
5665
+
5666
+ function disconnect() {
5667
+ connected = false;
5668
+ removeAllListeners();
5669
+ window.removeEventListener('message', receiveMessage);
5670
+ }
5671
+
5672
+ // handle the case that targetWindowOrIframeEl is actually an <iframe> rather than a Window(Proxy) object
5673
+ // Note that if it *is* a WindowProxy, this probe will throw a SecurityException, but in that case
5674
+ // we also don't need to do anything
5675
+ try {
5676
+ targetWindowIsIframeElement = targetWindowOrIframeEl.constructor === HTMLIFrameElement;
5677
+ } catch (e) {
5678
+ targetWindowIsIframeElement = false;
5679
+ }
5627
5680
 
5628
- /***/ "./src/interactive-api-client/in-frame.ts":
5629
- /*!************************************************!*\
5630
- !*** ./src/interactive-api-client/in-frame.ts ***!
5631
- \************************************************/
5632
- /*! no static exports found */
5633
- /***/ (function(module, exports, __webpack_require__) {
5681
+ if (targetWindowIsIframeElement) {
5682
+ // Infer the origin ONLY if the user did not supply an explicit origin, i.e., if the second
5683
+ // argument is empty or is actually a callback (meaning it is supposed to be the
5684
+ // afterConnectionCallback)
5685
+ if (!targetOrigin || targetOrigin.constructor === Function) {
5686
+ afterConnectedCallback = targetOrigin;
5687
+ targetOrigin = getIframeOrigin(targetWindowOrIframeEl);
5688
+ }
5689
+ }
5634
5690
 
5635
- "use strict";
5691
+ // Handle pages served through file:// protocol. Behaviour varies in different browsers. Safari sets origin
5692
+ // to 'file://' and everything works fine, but Chrome and Safari set message.origin to null.
5693
+ // Also, https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage says:
5694
+ // > Lastly, posting a message to a page at a file: URL currently requires that the targetOrigin argument be "*".
5695
+ // > file:// cannot be used as a security restriction; this restriction may be modified in the future.
5696
+ // So, using '*' seems like the only possible solution.
5697
+ if (targetOrigin === 'file://') {
5698
+ targetOrigin = '*';
5699
+ }
5636
5700
 
5637
- Object.defineProperty(exports, "__esModule", { value: true });
5638
- exports.inIframe = void 0;
5639
- var _inIframe = (function () {
5640
- try {
5641
- return window.self !== window.top;
5642
- }
5643
- catch (e) {
5644
- return true;
5645
- }
5646
- })();
5647
- var inIframe = function () { return _inIframe; };
5648
- exports.inIframe = inIframe;
5701
+ // when we receive 'hello':
5702
+ addListener('hello', function () {
5703
+ connected = true;
5649
5704
 
5705
+ // send hello response
5706
+ post({
5707
+ type: 'hello',
5708
+ // `origin` property isn't used by IframeEndpoint anymore (>= 1.2.0), but it's being sent to be
5709
+ // backward compatible with old IframeEndpoint versions (< v1.2.0).
5710
+ origin: window.location.href.match(/(.*?\/\/.*?)\//)[1]
5711
+ });
5650
5712
 
5651
- /***/ }),
5713
+ // give the user a chance to do things now that we are connected
5714
+ // note that is will happen before any queued messages
5715
+ if (afterConnectedCallback && typeof afterConnectedCallback === "function") {
5716
+ afterConnectedCallback();
5717
+ }
5652
5718
 
5653
- /***/ "./src/interactive-api-client/index.ts":
5654
- /*!*********************************************!*\
5655
- !*** ./src/interactive-api-client/index.ts ***!
5656
- \*********************************************/
5657
- /*! no static exports found */
5658
- /***/ (function(module, exports, __webpack_require__) {
5719
+ // Now send any messages that have been queued up ...
5720
+ while (postMessageQueue.length > 0) {
5721
+ post(postMessageQueue.shift());
5722
+ }
5723
+ });
5659
5724
 
5660
- "use strict";
5725
+ window.addEventListener('message', receiveMessage, false);
5661
5726
 
5662
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
5663
- if (k2 === undefined) k2 = k;
5664
- Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
5665
- }) : (function(o, m, k, k2) {
5666
- if (k2 === undefined) k2 = k;
5667
- o[k2] = m[k];
5668
- }));
5669
- var __exportStar = (this && this.__exportStar) || function(m, exports) {
5670
- for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
5727
+ // Public API.
5728
+ return {
5729
+ post: post,
5730
+ addListener: addListener,
5731
+ removeListener: removeListener,
5732
+ removeAllListeners: removeAllListeners,
5733
+ disconnect: disconnect,
5734
+ getTargetWindow: getTargetWindow,
5735
+ targetOrigin: targetOrigin
5736
+ };
5671
5737
  };
5672
- Object.defineProperty(exports, "__esModule", { value: true });
5673
- __exportStar(__webpack_require__(/*! ./types */ "./src/interactive-api-client/types.ts"), exports);
5674
- __exportStar(__webpack_require__(/*! ./metadata-types */ "./src/interactive-api-client/metadata-types.ts"), exports);
5675
- __exportStar(__webpack_require__(/*! ./in-frame */ "./src/interactive-api-client/in-frame.ts"), exports);
5676
- __exportStar(__webpack_require__(/*! ./api */ "./src/interactive-api-client/api.ts"), exports);
5677
- __exportStar(__webpack_require__(/*! ./hooks */ "./src/interactive-api-client/hooks.ts"), exports);
5678
- __exportStar(__webpack_require__(/*! ./client */ "./src/interactive-api-client/client.ts"), exports);
5679
5738
 
5680
5739
 
5681
5740
  /***/ }),
5682
5741
 
5683
- /***/ "./src/interactive-api-client/managed-state.ts":
5684
- /*!*****************************************************!*\
5685
- !*** ./src/interactive-api-client/managed-state.ts ***!
5686
- \*****************************************************/
5742
+ /***/ "./src/interactive-api-client/node_modules/iframe-phone/lib/structured-clone.js":
5743
+ /*!**************************************************************************************!*\
5744
+ !*** ./src/interactive-api-client/node_modules/iframe-phone/lib/structured-clone.js ***!
5745
+ \**************************************************************************************/
5687
5746
  /*! no static exports found */
5688
- /***/ (function(module, exports, __webpack_require__) {
5747
+ /***/ (function(module, exports) {
5689
5748
 
5690
- "use strict";
5749
+ var featureSupported = {
5750
+ 'structuredClones': 0
5751
+ };
5691
5752
 
5692
- Object.defineProperty(exports, "__esModule", { value: true });
5693
- exports.ManagedState = void 0;
5694
- var eventemitter2_1 = __webpack_require__(/*! eventemitter2 */ "./node_modules/eventemitter2/lib/eventemitter2.js");
5695
- var deepFreeze = __webpack_require__(/*! deep-freeze */ "./node_modules/deep-freeze/index.js");
5696
- var ManagedState = /** @class */ (function () {
5697
- function ManagedState() {
5698
- this.interactiveStateDirty = false;
5699
- this._initMessage = null;
5700
- // State variables are kept separately from initMessage, as they might get updated. For client user convenience,
5701
- // this state is kept here and all the updates emit appropriate event.
5702
- this._interactiveState = null;
5703
- this._authoredState = null;
5704
- this._globalInteractiveState = null;
5705
- this.emitter = new eventemitter2_1.EventEmitter2({
5706
- maxListeners: Infinity
5707
- });
5753
+ (function () {
5754
+ var result = 0;
5755
+
5756
+ if (!!window.postMessage) {
5757
+ try {
5758
+ // Spec states you can't transmit DOM nodes and it will throw an error
5759
+ // postMessage implementations that support cloned data will throw.
5760
+ window.postMessage(document.createElement("a"), "*");
5761
+ } catch (e) {
5762
+ // BBOS6 throws but doesn't pass through the correct exception
5763
+ // so check error message
5764
+ result = (e.DATA_CLONE_ERR || e.message === "Cannot post cyclic structures.") ? 1 : 0;
5765
+ featureSupported = {
5766
+ 'structuredClones': result
5767
+ };
5708
5768
  }
5709
- Object.defineProperty(ManagedState.prototype, "initMessage", {
5710
- get: function () {
5711
- return this._initMessage;
5712
- },
5713
- set: function (value) {
5714
- // null is an object too.
5715
- if (value !== null && typeof value === "object") {
5716
- value = deepFreeze(value);
5717
- }
5718
- this._initMessage = value;
5719
- this.emit("initInteractive", value);
5720
- },
5721
- enumerable: false,
5722
- configurable: true
5723
- });
5724
- Object.defineProperty(ManagedState.prototype, "interactiveState", {
5725
- get: function () {
5726
- return this._interactiveState;
5727
- },
5728
- set: function (value) {
5729
- // null is an object too.
5730
- if (value !== null && typeof value === "object") {
5731
- value = deepFreeze(value);
5732
- }
5733
- this._interactiveState = value;
5734
- this.emit("interactiveStateUpdated", value);
5735
- this.interactiveStateDirty = true;
5736
- },
5737
- enumerable: false,
5738
- configurable: true
5739
- });
5740
- Object.defineProperty(ManagedState.prototype, "authoredState", {
5741
- get: function () {
5742
- return this._authoredState;
5743
- },
5744
- set: function (value) {
5745
- // null is an object too.
5746
- if (value !== null && typeof value === "object") {
5747
- value = deepFreeze(value);
5748
- }
5749
- this._authoredState = value;
5750
- this.emit("authoredStateUpdated", value);
5751
- },
5752
- enumerable: false,
5753
- configurable: true
5754
- });
5755
- Object.defineProperty(ManagedState.prototype, "globalInteractiveState", {
5756
- get: function () {
5757
- return this._globalInteractiveState;
5758
- },
5759
- set: function (value) {
5760
- // null is an object too.
5761
- if (value !== null && typeof value === "object") {
5762
- value = deepFreeze(value);
5763
- }
5764
- this._globalInteractiveState = value;
5765
- this.emit("globalInteractiveStateUpdated", value);
5766
- },
5767
- enumerable: false,
5768
- configurable: true
5769
- });
5770
- ManagedState.prototype.emit = function (event, content) {
5771
- this.emitter.emit(event, content);
5772
- };
5773
- ManagedState.prototype.on = function (event, handler) {
5774
- this.emitter.on(event, handler);
5775
- };
5776
- ManagedState.prototype.off = function (event, handler) {
5777
- this.emitter.off(event, handler);
5778
- };
5779
- ManagedState.prototype.once = function (event, handler) {
5780
- this.emitter.once(event, handler);
5781
- };
5782
- return ManagedState;
5769
+ }
5783
5770
  }());
5784
- exports.ManagedState = ManagedState;
5771
+
5772
+ exports.supported = function supported() {
5773
+ return featureSupported && featureSupported.structuredClones > 0;
5774
+ };
5785
5775
 
5786
5776
 
5787
5777
  /***/ }),
5788
5778
 
5789
- /***/ "./src/interactive-api-client/metadata-types.ts":
5790
- /*!******************************************************!*\
5791
- !*** ./src/interactive-api-client/metadata-types.ts ***!
5792
- \******************************************************/
5779
+ /***/ "./src/interactive-api-client/node_modules/iframe-phone/main.js":
5780
+ /*!**********************************************************************!*\
5781
+ !*** ./src/interactive-api-client/node_modules/iframe-phone/main.js ***!
5782
+ \**********************************************************************/
5793
5783
  /*! no static exports found */
5794
5784
  /***/ (function(module, exports, __webpack_require__) {
5795
5785
 
5796
- "use strict";
5786
+ module.exports = {
5787
+ /**
5788
+ * Allows to communicate with an iframe.
5789
+ */
5790
+ ParentEndpoint: __webpack_require__(/*! ./lib/parent-endpoint */ "./src/interactive-api-client/node_modules/iframe-phone/lib/parent-endpoint.js"),
5791
+ /**
5792
+ * Allows to communicate with a parent page.
5793
+ * IFrameEndpoint is a singleton, as iframe can't have multiple parents anyway.
5794
+ */
5795
+ getIFrameEndpoint: __webpack_require__(/*! ./lib/iframe-endpoint */ "./src/interactive-api-client/node_modules/iframe-phone/lib/iframe-endpoint.js"),
5796
+ structuredClone: __webpack_require__(/*! ./lib/structured-clone */ "./src/interactive-api-client/node_modules/iframe-phone/lib/structured-clone.js"),
5797
5797
 
5798
- // Each time these interfaces are updated, it might be necessary to also update base_interactive.rb
5799
- // and interactive_run_state.rb files that process this data passed from interactives and send
5800
- // to report service and portal.
5801
- Object.defineProperty(exports, "__esModule", { value: true });
5798
+ // TODO: May be misnamed
5799
+ IframePhoneRpcEndpoint: __webpack_require__(/*! ./lib/iframe-phone-rpc-endpoint */ "./src/interactive-api-client/node_modules/iframe-phone/lib/iframe-phone-rpc-endpoint.js")
5800
+
5801
+ };
5802
5802
 
5803
5803
 
5804
5804
  /***/ }),