1
0
mirror of https://github.com/twirl/The-API-Book.git synced 2025-05-13 21:26:26 +02:00
2023-08-14 17:41:39 +03:00

197 lines
67 KiB
JavaScript

/*
* ATTENTION: The "eval" devtool has been used (maybe by default in mode: "development").
* This devtool is neither made for production nor for readable output files.
* It uses "eval()" calls to create a separate source file in the browser devtools.
* If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/)
* or disable the default devtool with "devtool: false".
* If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/).
*/
/******/ (() => { // webpackBootstrap
/******/ "use strict";
/******/ var __webpack_modules__ = ({
/***/ "./docs/examples/01. Decomposing UI Components/src/OfferListComponent.ts":
/*!*******************************************************************************!*\
!*** ./docs/examples/01. Decomposing UI Components/src/OfferListComponent.ts ***!
\*******************************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ OfferListComponent: () => (/* binding */ OfferListComponent)\n/* harmony export */ });\n/* harmony import */ var _util_html__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./util/html */ \"./docs/examples/01. Decomposing UI Components/src/util/html.ts\");\n/* harmony import */ var _util_EventEmitter__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./util/EventEmitter */ \"./docs/examples/01. Decomposing UI Components/src/util/EventEmitter.ts\");\n/**\n * @fileoverview\n * This file comprises a reference implementation\n * of the `IOfferListComponent` interface called simply `OfferListComponent`\n */\n\n\n/**\n * An `OfferListComponent` visualizes a list of short descriptions\n * of offers (“previews”) and allows for interacting with it.\n *\n * The responsibility of this class is:\n * * Rendering previews and react on the preview list change event\n * * Allowing user to select a preview and emit the corresponding event\n */\nclass OfferListComponent {\n constructor(context, container, offerList, options) {\n this.context = context;\n this.container = container;\n this.offerList = offerList;\n this.options = options;\n /**\n * An accessor to subscribe for events or emit them.\n */\n this.events = new _util_EventEmitter__WEBPACK_IMPORTED_MODULE_1__.EventEmitter();\n /**\n * An inner state of the component, whether it's now\n * rendered or not\n */\n this.shown = false;\n /**\n * Event listeners\n */\n this.listenerDisposers = [];\n /**\n * An event handler for the context state change\n * event. Exposed as a protected method to allow\n * for altering the default reaction in subclasses\n */\n this.onOfferListChange = ({ offerList }) => {\n if (this.shown) {\n this.hide();\n }\n this.offerList = offerList;\n if (offerList !== null) {\n this.show();\n }\n };\n /**\n * A listener to the DOM 'click' event. Exposed as a shortcut\n * to allow for enriching the UX in subclasses.\n * If we've taken long and 'proper' way, this should be\n * a spearate composer to route events and data flow between\n * the component and its representation.\n */\n this.onClickListener = (e) => {\n var _a;\n let target = e.target;\n while (target) {\n const offerId = (_a = target.dataset) === null || _a === void 0 ? void 0 : _a.offerId;\n if (offerId !== undefined) {\n this.onOfferClick(offerId);\n break;\n }\n target = target.parentNode;\n }\n };\n this.listenerDisposers.push(this.context.events.on('offerPreviewListChange', this.onOfferListChange));\n if (offerList !== null) {\n this.show();\n }\n }\n /* Provided for consistency for the developer\n to have access to the full state\n of the component */\n getOfferList() {\n return this.offerList;\n }\n /**\n * Destroys the component\n */\n destroy() {\n this.teardownListeners();\n this.hide();\n this.offerList = null;\n }\n /**\n * Allows for programmatically selecting an\n * offer in the list\n */\n selectOffer(offerId) {\n this.events.emit('offerSelect', {\n offerId\n });\n }\n /**\n * A helper method to generate the DOM structure for\n * displaying a preview. Exposed\n */\n generateOfferHtml(offer) {\n return (0,_util_html__WEBPACK_IMPORTED_MODULE_0__.html) `<li\n class=\"our-coffee-sdk-offer-list-offer\"\n data-offer-id=\"${(0,_util_html__WEBPACK_IMPORTED_MODULE_0__.attrValue)(offer.offerId)}\"\n >\n <aside>${offer.price.formattedValue} &gt;</aside>\n ${offer.imageUrl !== undefined\n ? (0,_util_html__WEBPACK_IMPORTED_MODULE_0__.html) `<img src=\"${(0,_util_html__WEBPACK_IMPORTED_MODULE_0__.attrValue)(offer.imageUrl)}\" />`\n : ''}\n <h3>${offer.title}</h3>\n <p>${offer.subtitle}</p>\n <p>${offer.bottomLine}</p>\n </li>`.toString();\n }\n /* A couple of helper methods to render the preview list\n or to dispose the corresponding DOM structure. Exposed to allow\n carrying out additional actions in subclasses if needed */\n show() {\n this.container.innerHTML = (0,_util_html__WEBPACK_IMPORTED_MODULE_0__.html) `<ul class=\"our-coffee-sdk-offer-list\">\n ${this.offerList === null\n ? ''\n : this.offerList.map((offer) => (0,_util_html__WEBPACK_IMPORTED_MODULE_0__.raw)(this.generateOfferHtml(offer)))}\n </ul>`.toString();\n this.setupDomListeners();\n this.shown = true;\n }\n hide() {\n this.teardownDomListeners();\n this.container.innerHTML = '';\n this.shown = false;\n }\n /* Various methods to work with events */\n onOfferClick(offerId) {\n this.selectOffer(offerId);\n }\n setupDomListeners() {\n this.container.addEventListener('click', this.onClickListener, false);\n }\n teardownListeners() {\n for (const disposer of this.listenerDisposers) {\n disposer.off();\n }\n this.listenerDisposers = [];\n }\n teardownDomListeners() {\n this.container.removeEventListener('click', this.onClickListener, false);\n }\n}\n\n\n//# sourceURL=webpack://ourCoffeeSdk/./docs/examples/01._Decomposing_UI_Components/src/OfferListComponent.ts?");
/***/ }),
/***/ "./docs/examples/01. Decomposing UI Components/src/OfferPanelButton.ts":
/*!*****************************************************************************!*\
!*** ./docs/examples/01. Decomposing UI Components/src/OfferPanelButton.ts ***!
\*****************************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ CloseButton: () => (/* binding */ CloseButton),\n/* harmony export */ CreateOrderButton: () => (/* binding */ CreateOrderButton),\n/* harmony export */ OfferPanelButton: () => (/* binding */ OfferPanelButton)\n/* harmony export */ });\n/* harmony import */ var _util_EventEmitter__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./util/EventEmitter */ \"./docs/examples/01. Decomposing UI Components/src/util/EventEmitter.ts\");\n/* harmony import */ var _util_html__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./util/html */ \"./docs/examples/01. Decomposing UI Components/src/util/html.ts\");\n/**\n * @fileoverview\n * This file comprises a reference implementation\n * of the `IButton` interface adapted for using with\n * the `OfferPanelComponent` parent element\n */\n\n\n/**\n * Displays an UI element that represents a call to action\n * for a user.\n *\n * The responsibility of this class is:\n * * Rendering the corresponding UI\n * * Emitting 'press' events\n */\nclass OfferPanelButton {\n constructor(action, container, options) {\n this.action = action;\n this.container = container;\n this.options = options;\n this.events = new _util_EventEmitter__WEBPACK_IMPORTED_MODULE_0__.EventEmitter();\n this.onClickListener = () => {\n this.events.emit('press', { target: this });\n };\n this.container.innerHTML = (0,_util_html__WEBPACK_IMPORTED_MODULE_1__.html) `<button\n class=\"our-coffee-sdk-offer-panel-button\"\n >\n ${this.options.iconUrl\n ? (0,_util_html__WEBPACK_IMPORTED_MODULE_1__.html) `<img src=\"${(0,_util_html__WEBPACK_IMPORTED_MODULE_1__.attrValue)(this.options.iconUrl)}\" />`\n : ''}\n <span>${(0,_util_html__WEBPACK_IMPORTED_MODULE_1__.raw)(this.options.text)}</span>\n </button>`.toString();\n this.button = (0,_util_html__WEBPACK_IMPORTED_MODULE_1__.$)(this.container, '.our-coffee-sdk-offer-panel-button');\n this.button.addEventListener('click', this.onClickListener, false);\n }\n destroy() {\n this.button.removeEventListener('click', this.onClickListener, false);\n this.container.innerHTML = '';\n }\n}\nclass CreateOrderButton extends OfferPanelButton {\n constructor(container, options) {\n super('createOrder', container, Object.assign({ text: 'Place an Order' }, options));\n this.button.classList.add('our-coffee-sdk-offer-panel-create-order-button');\n }\n}\nclass CloseButton extends OfferPanelButton {\n constructor(container, options) {\n super('close', container, Object.assign({ text: 'Not Now' }, options));\n this.button.classList.add('our-coffee-sdk-offer-panel-close-button');\n }\n}\n\n\n//# sourceURL=webpack://ourCoffeeSdk/./docs/examples/01._Decomposing_UI_Components/src/OfferPanelButton.ts?");
/***/ }),
/***/ "./docs/examples/01. Decomposing UI Components/src/OfferPanelComponent.ts":
/*!********************************************************************************!*\
!*** ./docs/examples/01. Decomposing UI Components/src/OfferPanelComponent.ts ***!
\********************************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ OfferPanelComponent: () => (/* binding */ OfferPanelComponent)\n/* harmony export */ });\n/* harmony import */ var _test_util__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../test/util */ \"./docs/examples/01. Decomposing UI Components/test/util.ts\");\n/* harmony import */ var _OfferPanelButton__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./OfferPanelButton */ \"./docs/examples/01. Decomposing UI Components/src/OfferPanelButton.ts\");\n/* harmony import */ var _util_EventEmitter__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./util/EventEmitter */ \"./docs/examples/01. Decomposing UI Components/src/util/EventEmitter.ts\");\n/* harmony import */ var _util_html__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./util/html */ \"./docs/examples/01. Decomposing UI Components/src/util/html.ts\");\n/**\n * @fileoverview\n * This file comprises a reference implementation\n * of the `IOfferPanelComponent` interface called simply `OfferPanelComponent`\n */\n\n\n\n\n/**\n * A `OfferPanelComponent` represents a UI to display\n * the detailed information regarding an offer (a “full view”)\n * implying that user can act on the offer (for example,\n * to create an order).\n *\n * The responsibility of the component is:\n * * Displaying detailed information regarding an offer\n * and update it if the corresponding context state\n * change event happens\n * * Rendering “buttons,” i.e. the control elements\n * for user to express their intentions\n * * Emitting “actions” when the user interacts with the buttons\n * * Closing itself if needed\n */\nclass OfferPanelComponent {\n constructor(context, container, currentOffer, options) {\n this.context = context;\n this.container = container;\n this.currentOffer = currentOffer;\n this.options = options;\n /**\n * An accessor to subscribe for events or emit them.\n */\n this.events = new _util_EventEmitter__WEBPACK_IMPORTED_MODULE_2__.EventEmitter();\n /**\n * A DOM element container for buttons\n */\n this.buttonsContainer = null;\n /**\n * An array of currently displayed buttons\n */\n this.buttons = [];\n /**\n * Event listeners\n */\n this.listenerDisposers = [];\n /**\n * An inner state of the component, whether it's open\n * or closed\n */\n this.shown = false;\n /**\n * A listener for the parent context's state change.\n * Exposed as a protected method to allow for adding additional\n * functionality\n */\n this.onOfferFullViewToggle = ({ offer }) => {\n if (this.shown) {\n this.hide();\n }\n this.currentOffer = offer;\n if (offer) {\n this.show();\n }\n };\n /**\n * A listener for button pressing events. Exposed\n * as a protected method to allow for adding custom\n * reactions\n */\n this.onButtonPress = ({ target }) => {\n if (this.currentOffer !== null) {\n this.events.emit('action', {\n action: target.action,\n target,\n currentOfferId: this.currentOffer.offerId\n });\n }\n };\n this.listenerDisposers.push(this.context.events.on('offerFullViewToggle', this.onOfferFullViewToggle));\n if (currentOffer !== null) {\n this.show();\n }\n }\n /* Exposed for consistency */\n getOffer() {\n return this.currentOffer;\n }\n /**\n * Destroys the panel and its buttons\n */\n destroy() {\n this.currentOffer = null;\n for (const disposer of this.listenerDisposers) {\n disposer.off();\n }\n if (this.shown) {\n this.hide();\n }\n }\n /* A pair of helper methods to show and hide the panel */\n show() {\n this.container.innerHTML = (0,_util_html__WEBPACK_IMPORTED_MODULE_3__.html) `<div class=\"our-coffee-sdk-offer-panel\">\n <h1>${this.currentOffer.title}</h1>\n ${this.currentOffer.description.map((description) => (0,_util_html__WEBPACK_IMPORTED_MODULE_3__.html) `<p>${description}</p>`)}\n <ul class=\"our-coffee-sdk-offer-panel-buttons\"></ul>\n </div>`.toString();\n this.buttonsContainer = (0,_util_html__WEBPACK_IMPORTED_MODULE_3__.$)(this.container, '.our-coffee-sdk-offer-panel-buttons');\n if (!this.options.transparent) {\n this.container.classList.add('our-coffee-sdk-cover-blur');\n }\n this.setupButtons();\n this.shown = true;\n }\n hide() {\n this.destroyButtons();\n this.buttonsContainer = null;\n this.container.innerHTML = '';\n this.container.classList.remove('our-coffee-sdk-cover-blur');\n this.shown = false;\n }\n /**\n * Instantiates all buttons when a new offer is to be\n * displayed. Exposed as a protected method to allow for\n * an additional UX functionality in subclasses\n */\n setupButtons() {\n var _a;\n const buttonBuilders = (_a = this.options.buttonBuilders) !== null && _a !== void 0 ? _a : [\n OfferPanelComponent.buildCreateOrderButton,\n OfferPanelComponent.buildCloseButton\n ];\n for (const buttonBuilder of buttonBuilders) {\n const container = document.createElement('li');\n this.buttonsContainer.appendChild(container);\n const button = buttonBuilder(this.currentOffer, container, this.options);\n const listenerDisposer = button.events.on('press', this.onButtonPress);\n this.buttons.push({ button, listenerDisposer, container });\n }\n }\n /**\n * Destroys all buttons once the panel is hidden\n */\n destroyButtons() {\n for (const { button, listenerDisposer, container } of this.buttons) {\n listenerDisposer.off();\n button.destroy();\n container.parentNode.removeChild(container);\n }\n this.buttons = [];\n }\n}\n/**\n * A static helper function to build a specific button\n * for creating orders\n */\nOfferPanelComponent.buildCreateOrderButton = (offer, container, options) => new _OfferPanelButton__WEBPACK_IMPORTED_MODULE_1__.CreateOrderButton(container, (0,_test_util__WEBPACK_IMPORTED_MODULE_0__.omitUndefined)({\n iconUrl: options.createOrderButtonUrl,\n text: options.createOrderButtonText\n}));\n/**\n * A static helper function to build a specific button\n * for closing the panel\n */\nOfferPanelComponent.buildCloseButton = (offer, container, options) => new _OfferPanelButton__WEBPACK_IMPORTED_MODULE_1__.CloseButton(container, (0,_test_util__WEBPACK_IMPORTED_MODULE_0__.omitUndefined)({\n iconUrl: options.closeButtonUrl,\n text: options.closeButtonText\n}));\n\n\n//# sourceURL=webpack://ourCoffeeSdk/./docs/examples/01._Decomposing_UI_Components/src/OfferPanelComponent.ts?");
/***/ }),
/***/ "./docs/examples/01. Decomposing UI Components/src/SearchBox.ts":
/*!**********************************************************************!*\
!*** ./docs/examples/01. Decomposing UI Components/src/SearchBox.ts ***!
\**********************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ SearchBox: () => (/* binding */ SearchBox)\n/* harmony export */ });\n/* harmony import */ var _util_EventEmitter__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./util/EventEmitter */ \"./docs/examples/01. Decomposing UI Components/src/util/EventEmitter.ts\");\n/* harmony import */ var _SearchBoxComposer__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./SearchBoxComposer */ \"./docs/examples/01. Decomposing UI Components/src/SearchBoxComposer.ts\");\n/* harmony import */ var _util_html__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./util/html */ \"./docs/examples/01. Decomposing UI Components/src/util/html.ts\");\n/**\n * @fileoverview\n * This file comprises a reference implementation\n * of the `ISearchBox` interface called simply `SearchBox`\n */\nvar __awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\n return new (P || (P = Promise))(function (resolve, reject) {\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\n step((generator = generator.apply(thisArg, _arguments || [])).next());\n });\n};\n\n\n\n/**\n * A `SearchBox` represents a UI component\n * that allows an end user to enter search queries,\n * work with the received results and place orders.\n * The user input which will be propagated\n * to the underlying `ourCoffeeApi` functionality.\n *\n * The responsibility of this class is:\n * * Handling user input consistently\n * * Instantiating the `ISearchBoxComposer` subcomponent\n * that takes care of the offer list UI & UX, and creating\n * orders if a `composers` requests to.\n * * Emitting events when current displayed search results\n * (offers) are changed\n * * Providing methods to programmatically initialize\n * searching a given query and make orders\n */\nclass SearchBox {\n /**\n * A `SearchBox` synchoronously initializes itself\n * in the given HTML element context and will use\n * the given instance of the `ICoffeeApi` interface\n * to run search queries and create orders.\n */\n constructor(container, coffeeApi, options) {\n this.container = container;\n this.coffeeApi = coffeeApi;\n /**\n * An accessor to subscribe for events or emit them.\n */\n this.events = new _util_EventEmitter__WEBPACK_IMPORTED_MODULE_0__.EventEmitter();\n /**\n * The current list of search results (offers) to\n * present to the user. Might be `null`.\n */\n this.offerList = null;\n /**\n * A current asynchronous request to the search API (if any).\n * Needed to manage a possible race if the user or\n * the developer fires several search queries in a row.\n */\n this.currentRequest = null;\n /**\n * Event listeners to get disposed upon desructing the `SearchBox`\n */\n this.listenerDisposers = [];\n /**\n * Handling a 'Search' button press event. Provided as\n * a protected method to allow custom validations\n * or alternative inputs\n */\n this.onSearchButtonClickListener = () => {\n const query = this.input.value.trim();\n if (query) {\n this.search(query);\n }\n };\n this.options =\n options !== undefined\n ? Object.assign(Object.assign({}, SearchBox.DEFAULT_OPTIONS), options) : Object.assign({}, SearchBox.DEFAULT_OPTIONS);\n this.render();\n this.composer = this.buildComposer(this, this.layoutContainer, this.options);\n this.setupListeners();\n }\n /* These three methods are provided for consistency\n for the developer to have access to the full state\n of the `SearchBox` entity */\n getOptions() {\n return this.options;\n }\n getContainer() {\n return this.container;\n }\n getOfferList() {\n return this.offerList;\n }\n /**\n * Performs searching of offers and reflects this\n * operation in the UI\n * @param {string} rawQuery Raw unsanitized input\n */\n search(rawQuery) {\n return __awaiter(this, void 0, void 0, function* () {\n // Shall empty queries be allowed?\n // As it's an API method, it might make sense\n // for a developer to send empty strings to\n // the API method, so we keep this possibility\n const query = rawQuery.trim();\n this.input.value = query;\n const request = (this.currentRequest = this.coffeeApi.search(query));\n this.setOfferList(null);\n yield request.then((result) => {\n if (request === this.currentRequest) {\n this.setOfferList(result);\n this.currentRequest = null;\n }\n });\n });\n }\n /**\n * Creates an order based on the offer.\n */\n createOrder(parameters) {\n return this.coffeeApi.createOrder(parameters);\n }\n /**\n * Destroys the `SearchBox` and all its subcomponents\n */\n destroy() {\n this.teardownListeners();\n this.composer.destroy();\n this.container.innerHTML = '';\n this.currentRequest = this.offerList = null;\n }\n /**\n * Factory method to create a composer.\n * Exposed as a protected method to allow\n * instantiating custom composers.\n * @param {ISearchBox} context Parent search box\n * @param {HTMLElement} container An HTML Element\n * container prepared for rendering the UI\n * @param {ISearchBoxOptions} options Parent options\n * @returns\n */\n buildComposer(context, container, options) {\n return new _SearchBoxComposer__WEBPACK_IMPORTED_MODULE_1__.SearchBoxComposer(context, container, options);\n }\n /**\n * The internal implementation of setting a new\n * offer list after a search is performed.\n * Provided as a protected method to allow for custom\n * search result list modifications in a subclass.\n */\n setOfferList(offerList) {\n if (this.offerList !== offerList) {\n this.offerList = offerList;\n this.events.emit('offerListChange', { offerList });\n }\n }\n /**\n * Rendering HTML markup of the composer\n */\n render() {\n this.container.innerHTML = (0,_util_html__WEBPACK_IMPORTED_MODULE_2__.html) `<div class=\"our-coffee-sdk-search-box\">\n <div class=\"our-coffee-sdk-search-box-head\">\n <input type=\"text\" class=\"our-coffee-sdk-search-box-input\" />\n <button class=\"our-coffee-sdk-search-box-search-button\">\n ${this.options.searchButtonText}\n </button>\n </div>\n <div class=\"our-coffee-sdk-layout-container\"></div>\n </div>`.toString();\n this.input = (0,_util_html__WEBPACK_IMPORTED_MODULE_2__.$)(this.container, '.our-coffee-sdk-search-box-input');\n this.searchButton = (0,_util_html__WEBPACK_IMPORTED_MODULE_2__.$)(this.container, '.our-coffee-sdk-search-box-search-button');\n this.layoutContainer = (0,_util_html__WEBPACK_IMPORTED_MODULE_2__.$)(this.container, '.our-coffee-sdk-layout-container');\n }\n /**\n * Working with various events\n */\n setupListeners() {\n this.searchButton.addEventListener('click', this.onSearchButtonClickListener, false);\n this.listenerDisposers.push(this.composer.events.on('createOrder', ({ offer: { offerId } }) => this.createOrder({ offerId })));\n }\n teardownListeners() {\n for (const disposer of this.listenerDisposers) {\n disposer.off();\n }\n this.listenerDisposers = [];\n this.searchButton.removeEventListener('click', this.onSearchButtonClickListener, false);\n }\n}\n/**\n * Default options of the `SearchBox` component\n */\nSearchBox.DEFAULT_OPTIONS = {\n searchButtonText: 'Search'\n};\n\n\n//# sourceURL=webpack://ourCoffeeSdk/./docs/examples/01._Decomposing_UI_Components/src/SearchBox.ts?");
/***/ }),
/***/ "./docs/examples/01. Decomposing UI Components/src/SearchBoxComposer.ts":
/*!******************************************************************************!*\
!*** ./docs/examples/01. Decomposing UI Components/src/SearchBoxComposer.ts ***!
\******************************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ SearchBoxComposer: () => (/* binding */ SearchBoxComposer)\n/* harmony export */ });\n/* harmony import */ var _OfferListComponent__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./OfferListComponent */ \"./docs/examples/01. Decomposing UI Components/src/OfferListComponent.ts\");\n/* harmony import */ var _OfferPanelComponent__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./OfferPanelComponent */ \"./docs/examples/01. Decomposing UI Components/src/OfferPanelComponent.ts\");\n/* harmony import */ var _util_EventEmitter__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./util/EventEmitter */ \"./docs/examples/01. Decomposing UI Components/src/util/EventEmitter.ts\");\n/**\n * @fileoverview\n * This file comprises a reference implementation\n * of the `ISearchBoxComposer` interface called simply `SearchBoxComposer`\n */\n\n\n\n/**\n * A `SearchBoxComposer` stands for an entity which\n * controls the data flow between an abstract `ISearchBox`\n * and a specific UI concept.\n *\n * This reference implementation assumes that each offer\n * might be represented as a list item (a 'preview') and\n * as a detailed representation (a `full view`).\n *\n * The responsibility of the composer is:\n * * Instantiating and destroying nested components\n * that handles previews (`IOfferListComponent`) and\n * a full view (`IOfferPanelComponent`)\n * * Handling an internal state (a list of offers and\n * a currently selected offer) and emitting events when\n * it changes\n * * Generating previews, full views, and UI options when\n * needed\n * * Notifying parent `ISearchBox` about the user's intention\n * to place an order\n */\nclass SearchBoxComposer {\n /**\n * A `SearchBoxComposer` synchoronously initializes itself\n * in the context of the given `SearchBox` with provided\n * options and HTML container element.\n */\n constructor(context, container, contextOptions) {\n this.context = context;\n this.container = container;\n this.contextOptions = contextOptions;\n /**\n * An accessor to subscribe for events or emit them.\n */\n this.events = new _util_EventEmitter__WEBPACK_IMPORTED_MODULE_2__.EventEmitter();\n /**\n * Instances of subcomponents and HTML element containers\n * to host them\n */\n this.offerListContainer = null;\n this.offerListComponent = null;\n this.offerPanelContainer = null;\n this.offerPanelComponent = null;\n /**\n * A current state of the composer itself\n */\n this.offerList = null;\n this.currentOffer = null;\n /**\n * Event listeners\n */\n this.onOfferPanelAction = (event) => {\n this.performAction(event);\n };\n this.onOfferListOfferSelect = ({ offerId }) => this.selectOffer(offerId);\n /**\n * The event subscriber for the parent context `offerListChange`\n * event. Transforms the high-level event into a couple of lover-level\n * ones and maintaints the composer's internal state.\n * Exposed as a protected method to allow custom reactions\n * to parent context state change in subclasses.\n */\n this.onContextOfferListChange = ({ offerList }) => {\n if (this.currentOffer !== null) {\n this.currentOffer = null;\n this.events.emit('offerFullViewToggle', { offer: null });\n }\n this.offerList = offerList;\n this.events.emit('offerPreviewListChange', {\n offerList: this.generateOfferPreviews(this.offerList, this.contextOptions)\n });\n };\n this.offerListContainer = document.createElement('div');\n container.appendChild(this.offerListContainer);\n this.offerListComponent = this.buildOfferListComponent(this, this.offerListContainer, this.offerList, this.contextOptions);\n this.offerPanelContainer = document.createElement('div');\n container.appendChild(this.offerPanelContainer);\n this.offerPanelComponent = this.buildOfferPanelComponent(this, this.offerPanelContainer, this.currentOffer, this.contextOptions);\n this.listenerDisposers = [\n context.events.on('offerListChange', this.onContextOfferListChange),\n this.offerListComponent.events.on('offerSelect', this.onOfferListOfferSelect),\n this.offerPanelComponent.events.on('action', this.onOfferPanelAction)\n ];\n }\n /**\n * Allows for searching for a displayed offer\n */\n findOfferById(offerIdToFind) {\n var _a, _b;\n // Theoretically, we could have built a `Map`\n // for quickly searching offers by their id\n // Practically, as all responses in an API must be\n // paginated, it makes little sense to optimize this prematurely.\n return ((_b = (_a = this.offerList) === null || _a === void 0 ? void 0 : _a.find(({ offerId }) => offerId === offerIdToFind)) !== null && _b !== void 0 ? _b : null);\n }\n /**\n * Exposed publicly to allow developers to programmatically\n * select an offer (which typically implies opening an offer panel)\n */\n selectOffer(offerId) {\n const offer = this.findOfferById(offerId);\n // Offer may be missing for a variety of reasons,\n // most notably of `OfferListComponent` renders\n // offers asynchronously\n if (offer !== null) {\n this.currentOffer = offer;\n this.events.emit('offerFullViewToggle', {\n offer: this.generateCurrentOfferFullView(this.currentOffer, this.contextOptions)\n });\n }\n else {\n // TDB\n }\n }\n /**\n * Exposed publicly to allow programmatically\n * performing actions the composer is capable of,\n * i.e., creating an order or closing the offer panel,\n * or to add new actions in subclasses\n */\n performAction({ action, currentOfferId: offerId }) {\n switch (action) {\n case 'createOrder':\n this.createOrder(offerId);\n break;\n case 'close':\n if (this.currentOffer !== null) {\n this.currentOffer = null;\n this.events.emit('offerFullViewToggle', { offer: null });\n }\n break;\n }\n }\n /**\n * Exposed publicly as a helper function\n */\n createOrder(offerId) {\n const offer = this.findOfferById(offerId);\n // Offer may be missing if `OfferPanelComponent`\n // renders offers asynchronously\n if (offer !== null) {\n this.events.emit('createOrder', { offer });\n }\n }\n /**\n * Destroys the composer and all its subcomponents\n */\n destroy() {\n for (const disposer of this.listenerDisposers) {\n disposer.off();\n }\n this.listenerDisposers = [];\n this.offerListComponent.destroy();\n this.offerPanelComponent.destroy();\n this.offerListContainer.parentNode.removeChild(this.offerListContainer);\n this.offerPanelContainer.parentNode.removeChild(this.offerPanelContainer);\n }\n /**\n * A factory method to build an instance of an offer list\n * sub-component. Exposed as a protected method to allow\n * custom implementations of an offer list in subclasses\n */\n buildOfferListComponent(context, container, offerList, contextOptions) {\n return new _OfferListComponent__WEBPACK_IMPORTED_MODULE_0__.OfferListComponent(context, container, this.generateOfferPreviews(offerList, contextOptions), this.generateOfferListComponentOptions(contextOptions));\n }\n /**\n * A helper to generate “preview” data for the offer list component.\n * Exposed as a protected method to allow enriching preview data\n * with custom fields in subclasses.\n */\n generateOfferPreviews(offerList, contextOptions) {\n return offerList === null\n ? null\n : offerList.map((offer) => ({\n offerId: offer.offerId,\n title: offer.place.title,\n subtitle: offer.recipe.shortDescription,\n price: offer.price,\n bottomLine: SearchBoxComposer.generateOfferBottomLine(offer)\n }));\n }\n /**\n * A helper to translate context options (i.e., the options of the\n * parent `ISearchBox`) into the options of the offer list subcomponent.\n * Exposed as a protected method to allow for an additional logic of\n * generating options or passing extra options in subclasses\n */\n generateOfferListComponentOptions(options) {\n return {};\n }\n /**\n * A factory method to build an instance of an offer panel\n * sub-component. Exposed as a protected method to allow\n * custom implementations of an offer panel in subclasses\n */\n buildOfferPanelComponent(context, container, currentOffer, contextOptions) {\n return new _OfferPanelComponent__WEBPACK_IMPORTED_MODULE_1__.OfferPanelComponent(context, container, this.generateCurrentOfferFullView(currentOffer, contextOptions), this.generateOfferPanelComponentOptions(contextOptions));\n }\n /**\n * A helper to generate “full view” data for the offer panel component.\n * Exposed as a protected method to allow enriching full view data\n * with custom fields in subclasses.\n */\n generateCurrentOfferFullView(offer, contextOptions) {\n return offer === null\n ? null\n : {\n offerId: offer.offerId,\n title: offer.place.title,\n description: [\n offer.recipe.mediumDescription,\n SearchBoxComposer.generateOfferBottomLine(offer)\n ],\n price: offer.price\n };\n }\n /**\n * A helper to translate context options (i.e., the options of the\n * parent `ISearchBox`) into the options of the offer panel subcomponent.\n * Exposed as a protected method to allow for an additional logic of\n * generating options or passing extra options in subclasses\n */\n generateOfferPanelComponentOptions(options) {\n var _a;\n return (_a = options.offerPanel) !== null && _a !== void 0 ? _a : {};\n }\n /**\n * A small helper method to generate “bottomlines” for offers\n */\n static generateOfferBottomLine(offer) {\n return offer.place.walkingDistance.numericValueMeters >= 100\n ? `${offer.place.walkTime.formattedValue} · ${offer.place.walkingDistance.formattedValue}`\n : 'Just around the corner';\n }\n}\n\n\n//# sourceURL=webpack://ourCoffeeSdk/./docs/examples/01._Decomposing_UI_Components/src/SearchBoxComposer.ts?");
/***/ }),
/***/ "./docs/examples/01. Decomposing UI Components/src/index.ts":
/*!******************************************************************!*\
!*** ./docs/examples/01. Decomposing UI Components/src/index.ts ***!
\******************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ CAFEE_CHAMOMILE_LUNGO_OFFER: () => (/* reexport safe */ _test_fixtures_dummyCoffeeApi__WEBPACK_IMPORTED_MODULE_6__.CAFEE_CHAMOMILE_LUNGO_OFFER),\n/* harmony export */ CAFEE_CHAMOMILE_LUNGO_OFFER_FULL_VIEW: () => (/* reexport safe */ _test_fixtures_dummyCoffeeApi__WEBPACK_IMPORTED_MODULE_6__.CAFEE_CHAMOMILE_LUNGO_OFFER_FULL_VIEW),\n/* harmony export */ CAFEE_CHAMOMILE_LUNGO_OFFER_PREVIEW: () => (/* reexport safe */ _test_fixtures_dummyCoffeeApi__WEBPACK_IMPORTED_MODULE_6__.CAFEE_CHAMOMILE_LUNGO_OFFER_PREVIEW),\n/* harmony export */ CloseButton: () => (/* reexport safe */ _OfferPanelButton__WEBPACK_IMPORTED_MODULE_4__.CloseButton),\n/* harmony export */ CreateOrderButton: () => (/* reexport safe */ _OfferPanelButton__WEBPACK_IMPORTED_MODULE_4__.CreateOrderButton),\n/* harmony export */ DUMMY_ORDER: () => (/* reexport safe */ _test_fixtures_dummyCoffeeApi__WEBPACK_IMPORTED_MODULE_6__.DUMMY_ORDER),\n/* harmony export */ DUMMY_PREVIEWS: () => (/* reexport safe */ _test_fixtures_dummyCoffeeApi__WEBPACK_IMPORTED_MODULE_6__.DUMMY_PREVIEWS),\n/* harmony export */ DUMMY_RESPONSE: () => (/* reexport safe */ _test_fixtures_dummyCoffeeApi__WEBPACK_IMPORTED_MODULE_6__.DUMMY_RESPONSE),\n/* harmony export */ DummyMapApi: () => (/* reexport safe */ _test_fixtures_dummyMapApi__WEBPACK_IMPORTED_MODULE_7__.DummyMapApi),\n/* harmony export */ OfferListComponent: () => (/* reexport safe */ _OfferListComponent__WEBPACK_IMPORTED_MODULE_2__.OfferListComponent),\n/* harmony export */ OfferPanelButton: () => (/* reexport safe */ _OfferPanelButton__WEBPACK_IMPORTED_MODULE_4__.OfferPanelButton),\n/* harmony export */ OfferPanelComponent: () => (/* reexport safe */ _OfferPanelComponent__WEBPACK_IMPORTED_MODULE_3__.OfferPanelComponent),\n/* harmony export */ SearchBox: () => (/* reexport safe */ _SearchBox__WEBPACK_IMPORTED_MODULE_0__.SearchBox),\n/* harmony export */ SearchBoxComposer: () => (/* reexport safe */ _SearchBoxComposer__WEBPACK_IMPORTED_MODULE_1__.SearchBoxComposer),\n/* harmony export */ dummyCoffeeApi: () => (/* reexport safe */ _test_fixtures_dummyCoffeeApi__WEBPACK_IMPORTED_MODULE_6__.dummyCoffeeApi),\n/* harmony export */ util: () => (/* reexport module object */ _util_index__WEBPACK_IMPORTED_MODULE_5__)\n/* harmony export */ });\n/* harmony import */ var _SearchBox__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./SearchBox */ \"./docs/examples/01. Decomposing UI Components/src/SearchBox.ts\");\n/* harmony import */ var _SearchBoxComposer__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./SearchBoxComposer */ \"./docs/examples/01. Decomposing UI Components/src/SearchBoxComposer.ts\");\n/* harmony import */ var _OfferListComponent__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./OfferListComponent */ \"./docs/examples/01. Decomposing UI Components/src/OfferListComponent.ts\");\n/* harmony import */ var _OfferPanelComponent__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./OfferPanelComponent */ \"./docs/examples/01. Decomposing UI Components/src/OfferPanelComponent.ts\");\n/* harmony import */ var _OfferPanelButton__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./OfferPanelButton */ \"./docs/examples/01. Decomposing UI Components/src/OfferPanelButton.ts\");\n/* harmony import */ var _util_index__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./util/index */ \"./docs/examples/01. Decomposing UI Components/src/util/index.ts\");\n/* harmony import */ var _test_fixtures_dummyCoffeeApi__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../test/fixtures/dummyCoffeeApi */ \"./docs/examples/01. Decomposing UI Components/test/fixtures/dummyCoffeeApi.ts\");\n/* harmony import */ var _test_fixtures_dummyMapApi__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../test/fixtures/dummyMapApi */ \"./docs/examples/01. Decomposing UI Components/test/fixtures/dummyMapApi.ts\");\n\n\n\n\n\n\n\n\n\n\n\n//# sourceURL=webpack://ourCoffeeSdk/./docs/examples/01._Decomposing_UI_Components/src/index.ts?");
/***/ }),
/***/ "./docs/examples/01. Decomposing UI Components/src/util/EventEmitter.ts":
/*!******************************************************************************!*\
!*** ./docs/examples/01. Decomposing UI Components/src/util/EventEmitter.ts ***!
\******************************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ Disposer: () => (/* binding */ Disposer),\n/* harmony export */ EventEmitter: () => (/* binding */ EventEmitter)\n/* harmony export */ });\n/**\n * A helper class to subscribe for events and emit them\n */\nclass EventEmitter {\n constructor() {\n this.listenersByType = new Map();\n this.disposeCallback = (type, disposer) => {\n const listeners = this.listenersByType.get(type);\n if (listeners !== undefined) {\n const callback = listeners.get(disposer);\n if (callback !== undefined) {\n listeners.delete(disposer);\n if (listeners.size === 0) {\n this.listenersByType.delete(type);\n }\n }\n }\n };\n }\n /**\n * Subscribes for an event\n * @returns a `Disposer` which allows to unsubscribe\n */\n on(type, callback) {\n const disposer = new Disposer(type, this.disposeCallback);\n const listeners = this.listenersByType.get(type);\n if (listeners === undefined) {\n this.listenersByType.set(type, new Map([[disposer, callback]]));\n }\n else {\n listeners.set(disposer, callback);\n }\n return disposer;\n }\n /**\n * Emits an event, i.e., call all the subscribers for the\n * specified event type\n */\n emit(type, event) {\n const listeners = this.listenersByType.get(type);\n if (listeners !== undefined) {\n for (const callback of listeners.values()) {\n callback(event);\n }\n }\n }\n}\nclass Disposer {\n constructor(type, callback) {\n this.type = type;\n this.callback = callback;\n this.active = true;\n }\n off() {\n if (this.active) {\n this.callback(this.type, this);\n this.active = false;\n }\n }\n}\n\n\n//# sourceURL=webpack://ourCoffeeSdk/./docs/examples/01._Decomposing_UI_Components/src/util/EventEmitter.ts?");
/***/ }),
/***/ "./docs/examples/01. Decomposing UI Components/src/util/html.ts":
/*!**********************************************************************!*\
!*** ./docs/examples/01. Decomposing UI Components/src/util/html.ts ***!
\**********************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ $: () => (/* binding */ $),\n/* harmony export */ HtmlSerializable: () => (/* binding */ HtmlSerializable),\n/* harmony export */ attr: () => (/* binding */ attr),\n/* harmony export */ attrEscape: () => (/* binding */ attrEscape),\n/* harmony export */ attrValue: () => (/* binding */ attrValue),\n/* harmony export */ findDataField: () => (/* binding */ findDataField),\n/* harmony export */ getSubstituteValue: () => (/* binding */ getSubstituteValue),\n/* harmony export */ href: () => (/* binding */ href),\n/* harmony export */ hrefEscapeBuilder: () => (/* binding */ hrefEscapeBuilder),\n/* harmony export */ hrefValue: () => (/* binding */ hrefValue),\n/* harmony export */ html: () => (/* binding */ html),\n/* harmony export */ htmlEscape: () => (/* binding */ htmlEscape),\n/* harmony export */ httpHrefEscape: () => (/* binding */ httpHrefEscape),\n/* harmony export */ makeTemplate: () => (/* binding */ makeTemplate),\n/* harmony export */ raw: () => (/* binding */ raw)\n/* harmony export */ });\n/**\n * Helper function to find a single HTML element\n * matching a selector or fail\n */\nfunction $(...args) {\n const [node, selector] = args.length === 2 ? args : [document, args[0]];\n const result = node.querySelector(selector);\n if (!result) {\n throw new Error(`Cannot select a node with \"${selector}\" selector`);\n }\n return result;\n}\nfunction makeTemplate(e) {\n return (texts, ...substitutes) => {\n const parts = [];\n for (let i = 0; i < texts.length; i++) {\n parts.push(texts[i]);\n if (substitutes[i]) {\n parts.push(getSubstituteValue(substitutes[i], e));\n }\n }\n return new HtmlSerializable(parts.join(''));\n };\n}\nclass HtmlSerializable {\n constructor(__html) {\n this.__html = __html;\n this.__isHtmlSerializable = true;\n }\n toString() {\n return this.__html;\n }\n}\nfunction getSubstituteValue(value, escapeFunction) {\n if (typeof value == 'string') {\n return escapeFunction(value);\n }\n else if (value.__isHtmlSerializable) {\n return value.toString();\n }\n else {\n return value\n .map((v) => getSubstituteValue(v, escapeFunction))\n .join('');\n }\n}\nfunction htmlEscape(str) {\n return str\n .replace(/\\&/g, '&amp;')\n .replace(/\\</g, '&lt;')\n .replace(/\\>/g, '&gt;');\n}\nfunction attrEscape(str) {\n return htmlEscape(str).replace(/\\'/g, '&#39;').replace(/\\\"/g, '&quot;');\n}\nfunction hrefEscapeBuilder(allowedProtocols = ['http:', 'https:', null]) {\n return (raw) => {\n var _a;\n const str = raw.trim();\n const protocol = (_a = str.match(/$[a-z0-9\\+\\-\\.]+\\:/i)[0]) !== null && _a !== void 0 ? _a : null;\n if (allowedProtocols.includes(protocol)) {\n return attrEscape(str);\n }\n else {\n return '';\n }\n };\n}\nconst httpHrefEscape = hrefEscapeBuilder();\n/**\n * Template function to safely render HTML templates\n * and automatically escape substituted value\n */\nconst html = makeTemplate(htmlEscape);\nconst raw = (str) => new HtmlSerializable(str);\nconst attr = makeTemplate(attrEscape);\nconst attrValue = (str) => new HtmlSerializable(attrEscape(str));\nconst href = makeTemplate(httpHrefEscape);\nconst hrefValue = (str, allowedProtocols) => new HtmlSerializable(allowedProtocols === undefined\n ? httpHrefEscape(str)\n : hrefEscapeBuilder(allowedProtocols)(str));\nconst findDataField = (target, fieldName) => {\n let node = target;\n while (node) {\n if (node.dataset && node.dataset[fieldName] !== undefined) {\n return {\n target: node,\n value: node.dataset[fieldName]\n };\n }\n node = node.parentElement;\n }\n return {\n target: null,\n value: null\n };\n};\n\n\n//# sourceURL=webpack://ourCoffeeSdk/./docs/examples/01._Decomposing_UI_Components/src/util/html.ts?");
/***/ }),
/***/ "./docs/examples/01. Decomposing UI Components/src/util/index.ts":
/*!***********************************************************************!*\
!*** ./docs/examples/01. Decomposing UI Components/src/util/index.ts ***!
\***********************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ $: () => (/* reexport safe */ _html__WEBPACK_IMPORTED_MODULE_1__.$),\n/* harmony export */ Disposer: () => (/* reexport safe */ _EventEmitter__WEBPACK_IMPORTED_MODULE_0__.Disposer),\n/* harmony export */ EventEmitter: () => (/* reexport safe */ _EventEmitter__WEBPACK_IMPORTED_MODULE_0__.EventEmitter),\n/* harmony export */ HtmlSerializable: () => (/* reexport safe */ _html__WEBPACK_IMPORTED_MODULE_1__.HtmlSerializable),\n/* harmony export */ attr: () => (/* reexport safe */ _html__WEBPACK_IMPORTED_MODULE_1__.attr),\n/* harmony export */ attrEscape: () => (/* reexport safe */ _html__WEBPACK_IMPORTED_MODULE_1__.attrEscape),\n/* harmony export */ attrValue: () => (/* reexport safe */ _html__WEBPACK_IMPORTED_MODULE_1__.attrValue),\n/* harmony export */ findDataField: () => (/* reexport safe */ _html__WEBPACK_IMPORTED_MODULE_1__.findDataField),\n/* harmony export */ getSubstituteValue: () => (/* reexport safe */ _html__WEBPACK_IMPORTED_MODULE_1__.getSubstituteValue),\n/* harmony export */ href: () => (/* reexport safe */ _html__WEBPACK_IMPORTED_MODULE_1__.href),\n/* harmony export */ hrefEscapeBuilder: () => (/* reexport safe */ _html__WEBPACK_IMPORTED_MODULE_1__.hrefEscapeBuilder),\n/* harmony export */ hrefValue: () => (/* reexport safe */ _html__WEBPACK_IMPORTED_MODULE_1__.hrefValue),\n/* harmony export */ html: () => (/* reexport safe */ _html__WEBPACK_IMPORTED_MODULE_1__.html),\n/* harmony export */ htmlEscape: () => (/* reexport safe */ _html__WEBPACK_IMPORTED_MODULE_1__.htmlEscape),\n/* harmony export */ httpHrefEscape: () => (/* reexport safe */ _html__WEBPACK_IMPORTED_MODULE_1__.httpHrefEscape),\n/* harmony export */ makeTemplate: () => (/* reexport safe */ _html__WEBPACK_IMPORTED_MODULE_1__.makeTemplate),\n/* harmony export */ raw: () => (/* reexport safe */ _html__WEBPACK_IMPORTED_MODULE_1__.raw)\n/* harmony export */ });\n/* harmony import */ var _EventEmitter__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./EventEmitter */ \"./docs/examples/01. Decomposing UI Components/src/util/EventEmitter.ts\");\n/* harmony import */ var _html__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./html */ \"./docs/examples/01. Decomposing UI Components/src/util/html.ts\");\n\n\n\n\n//# sourceURL=webpack://ourCoffeeSdk/./docs/examples/01._Decomposing_UI_Components/src/util/index.ts?");
/***/ }),
/***/ "./docs/examples/01. Decomposing UI Components/test/fixtures/dummyCoffeeApi.ts":
/*!*************************************************************************************!*\
!*** ./docs/examples/01. Decomposing UI Components/test/fixtures/dummyCoffeeApi.ts ***!
\*************************************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ CAFEE_CHAMOMILE_LUNGO_OFFER: () => (/* binding */ CAFEE_CHAMOMILE_LUNGO_OFFER),\n/* harmony export */ CAFEE_CHAMOMILE_LUNGO_OFFER_FULL_VIEW: () => (/* binding */ CAFEE_CHAMOMILE_LUNGO_OFFER_FULL_VIEW),\n/* harmony export */ CAFEE_CHAMOMILE_LUNGO_OFFER_PREVIEW: () => (/* binding */ CAFEE_CHAMOMILE_LUNGO_OFFER_PREVIEW),\n/* harmony export */ DUMMY_ORDER: () => (/* binding */ DUMMY_ORDER),\n/* harmony export */ DUMMY_PREVIEWS: () => (/* binding */ DUMMY_PREVIEWS),\n/* harmony export */ DUMMY_RESPONSE: () => (/* binding */ DUMMY_RESPONSE),\n/* harmony export */ dummyCoffeeApi: () => (/* binding */ dummyCoffeeApi)\n/* harmony export */ });\n/**\n * @fileoverview\n * A dummy implementation of the coffee API. Always emits\n * the predefined array of results\n */\nvar __awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\n return new (P || (P = Promise))(function (resolve, reject) {\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\n step((generator = generator.apply(thisArg, _arguments || [])).next());\n });\n};\nconst CAFEE_CHAMOMILE_LUNGO_OFFER = {\n offerId: '1',\n recipe: {\n title: 'Lungo',\n shortDescription: 'Best Lungo in the town!',\n mediumDescription: `It's our best lungo. Smart SDK developers always choose Cafe “Chamomile” Lungo!`\n },\n place: {\n title: 'Cafe “Chamomile”',\n walkingDistance: {\n numericValueMeters: 200,\n formattedValue: '200m'\n },\n location: {\n longitude: 16.361645,\n latitude: 48.211515\n },\n walkTime: {\n intervalValueSeconds: 120,\n formattedValue: '2 min'\n },\n icon: '../../assets/coffee.png',\n phone: '12484345508'\n },\n price: {\n decimalValue: '37.00',\n formattedValue: '$37',\n currencyCode: 'USD'\n }\n};\nconst CAFEE_CHAMOMILE_LUNGO_OFFER_PREVIEW = {\n offerId: '1',\n title: 'Cafe “Chamomile”',\n subtitle: 'Best Lungo in the town!',\n bottomLine: '200m · 2 min',\n imageUrl: '/assets/coffee.png',\n price: {\n decimalValue: '37.00',\n formattedValue: '$37',\n currencyCode: 'USD'\n }\n};\nconst CAFEE_CHAMOMILE_LUNGO_OFFER_FULL_VIEW = {\n offerId: '1',\n title: 'Cafe “Chamomile”',\n description: [\n 'This is our best lungo. Smart SDK developers always choose Cafe “Chamomile” Lungo!',\n '200m · 2 min'\n ],\n price: {\n decimalValue: '37.00',\n formattedValue: '$37',\n currencyCode: 'USD'\n }\n};\nconst DUMMY_RESPONSE = [\n CAFEE_CHAMOMILE_LUNGO_OFFER,\n {\n offerId: '2',\n recipe: {\n title: 'Lungo',\n shortDescription: 'Best Lungo in the world!',\n mediumDescription: `It's our best lungo. Smart SDK developers always choose Peripheral Perk© Lungo!`\n },\n place: {\n title: 'Peripheral Perk',\n walkingDistance: {\n numericValueMeters: 400,\n formattedValue: '400m'\n },\n location: {\n longitude: 16.365423,\n latitude: 48.210377\n },\n walkTime: {\n intervalValueSeconds: 600,\n formattedValue: '5 min'\n }\n },\n price: {\n decimalValue: '39.00',\n formattedValue: '$39',\n currencyCode: 'USD'\n }\n },\n {\n offerId: '3',\n recipe: {\n title: 'Lungo',\n shortDescription: 'Best Lungo in this app!',\n mediumDescription: `It's our best lungo. Smart SDK developers always choose Top Top Cafe Lungo!`\n },\n place: {\n title: 'Top Top Cafe',\n walkingDistance: {\n numericValueMeters: 50,\n formattedValue: '50m'\n },\n location: {\n longitude: 16.367205,\n latitude: 48.208574\n },\n walkTime: {\n intervalValueSeconds: 50,\n formattedValue: 'less than a minute'\n }\n },\n price: {\n decimalValue: '41.00',\n formattedValue: '$41',\n currencyCode: 'USD'\n }\n }\n];\nconst DUMMY_PREVIEWS = [CAFEE_CHAMOMILE_LUNGO_OFFER_PREVIEW];\nconst DUMMY_ORDER = {\n orderId: '321'\n};\nconst dummyCoffeeApi = {\n search: () => __awaiter(void 0, void 0, void 0, function* () { return timeouted([...DUMMY_RESPONSE], 300); }),\n createOrder: () => __awaiter(void 0, void 0, void 0, function* () { return timeouted(DUMMY_ORDER, 300); })\n};\nfunction timeouted(result, timeoutMs) {\n return new Promise((resolve) => {\n setTimeout(() => {\n resolve(result);\n }, timeoutMs);\n });\n}\n\n\n//# sourceURL=webpack://ourCoffeeSdk/./docs/examples/01._Decomposing_UI_Components/test/fixtures/dummyCoffeeApi.ts?");
/***/ }),
/***/ "./docs/examples/01. Decomposing UI Components/test/fixtures/dummyMapApi.ts":
/*!**********************************************************************************!*\
!*** ./docs/examples/01. Decomposing UI Components/test/fixtures/dummyMapApi.ts ***!
\**********************************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ DummyMapApi: () => (/* binding */ DummyMapApi)\n/* harmony export */ });\nclass DummyMapApi {\n constructor(container, bounds) {\n this.container = container;\n this.bounds = bounds;\n this.listenerDisposers = [];\n this.container.style.cssText = [\n 'background-image: url(../../assets/map.jpg)',\n 'background-position: center',\n 'background-repeat: no-repeat',\n 'background-size: cover',\n 'position: relative',\n 'width: 100%',\n 'height: 100%',\n 'overflow: hidden'\n ].join(';');\n }\n addMarker(markerId, location, onClick) {\n const rect = this.container.getBoundingClientRect();\n const x = Math.floor((rect.width * (location.longitude - this.bounds[0][0])) /\n (this.bounds[1][0] - this.bounds[0][0])) - 15;\n const y = Math.floor((rect.height * (this.bounds[1][1] - location.latitude)) /\n (this.bounds[1][1] - this.bounds[0][1])) - 30;\n const marker = document.createElement('div');\n marker.dataset.markerId = markerId;\n marker.style.cssText = [\n 'position: absolute',\n 'width: 30px',\n 'height: 30px',\n `left: ${x}px`,\n `top: ${y}px`,\n 'align: center',\n 'line-height: 30px',\n 'font-size: 30px',\n 'cursor: pointer',\n 'mix-blend-mode: luminosity'\n ].join(';');\n marker.innerHTML =\n '<a href=\"javascript:void(0)\" style=\"text-decoration: none;\">📍</a>';\n const listener = () => onClick(markerId);\n this.listenerDisposers.push(() => {\n marker.removeEventListener('click', listener, false);\n });\n marker.addEventListener('click', listener, false);\n this.container.appendChild(marker);\n }\n selectSingleMarker(markerId) {\n var _a;\n for (const marker of this.container.childNodes) {\n const element = marker;\n if (((_a = element.dataset) === null || _a === void 0 ? void 0 : _a.markerId) === markerId) {\n element.style.mixBlendMode = 'unset';\n }\n else {\n element.style.mixBlendMode = 'luminosity';\n }\n }\n }\n destroy() {\n for (const dispose of this.listenerDisposers) {\n dispose();\n }\n this.listenerDisposers = [];\n this.container.innerHTML = '';\n this.container.style.cssText = '';\n }\n}\n\n\n//# sourceURL=webpack://ourCoffeeSdk/./docs/examples/01._Decomposing_UI_Components/test/fixtures/dummyMapApi.ts?");
/***/ }),
/***/ "./docs/examples/01. Decomposing UI Components/test/util.ts":
/*!******************************************************************!*\
!*** ./docs/examples/01. Decomposing UI Components/test/util.ts ***!
\******************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ defer: () => (/* binding */ defer),\n/* harmony export */ omitUndefined: () => (/* binding */ omitUndefined),\n/* harmony export */ waitForEvents: () => (/* binding */ waitForEvents)\n/* harmony export */ });\n/**\n * @fileoverview\n * Various helpers for testing the components\n */\nvar __awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\n return new (P || (P = Promise))(function (resolve, reject) {\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\n step((generator = generator.apply(thisArg, _arguments || [])).next());\n });\n};\nfunction waitForEvents(emitter, type, callback, n = 1) {\n return __awaiter(this, void 0, void 0, function* () {\n let counter = 0;\n const result = [];\n const disposers = [];\n return new Promise((resolve) => {\n const disposer = emitter.on(type, (event) => {\n result.push(event);\n if (++counter >= n) {\n setTimeout(() => {\n for (const disposer of disposers) {\n disposer.off();\n }\n resolve(result);\n }, 0);\n }\n });\n disposers.push(disposer);\n callback();\n });\n });\n}\nfunction defer() {\n let resolve;\n let reject;\n const promise = new Promise((nestedResolve, nestedReject) => {\n resolve = nestedResolve;\n });\n return {\n resolve,\n reject,\n promise\n };\n}\nfunction omitUndefined(obj) {\n const result = {};\n for (const [k, v] of Object.entries(obj)) {\n if (v !== undefined) {\n result[k] = v;\n }\n }\n return result;\n}\n\n\n//# sourceURL=webpack://ourCoffeeSdk/./docs/examples/01._Decomposing_UI_Components/test/util.ts?");
/***/ })
/******/ });
/************************************************************************/
/******/ // The module cache
/******/ var __webpack_module_cache__ = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/ // Check if module is in cache
/******/ var cachedModule = __webpack_module_cache__[moduleId];
/******/ if (cachedModule !== undefined) {
/******/ return cachedModule.exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = __webpack_module_cache__[moduleId] = {
/******/ // no module.id needed
/******/ // no module.loaded needed
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/************************************************************************/
/******/ /* webpack/runtime/define property getters */
/******/ (() => {
/******/ // define getter functions for harmony exports
/******/ __webpack_require__.d = (exports, definition) => {
/******/ for(var key in definition) {
/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
/******/ }
/******/ }
/******/ };
/******/ })();
/******/
/******/ /* webpack/runtime/hasOwnProperty shorthand */
/******/ (() => {
/******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
/******/ })();
/******/
/******/ /* webpack/runtime/make namespace object */
/******/ (() => {
/******/ // define __esModule on exports
/******/ __webpack_require__.r = (exports) => {
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/******/ }
/******/ Object.defineProperty(exports, '__esModule', { value: true });
/******/ };
/******/ })();
/******/
/************************************************************************/
/******/
/******/ // startup
/******/ // Load entry module and return exports
/******/ // This entry module can't be inlined because the eval devtool is used.
/******/ var __webpack_exports__ = __webpack_require__("./docs/examples/01. Decomposing UI Components/src/index.ts");
/******/ window.ourCoffeeSdk = __webpack_exports__;
/******/
/******/ })()
;