-60\n })}\n />\n
-40\n })}\n />\n
-20\n })}\n />\n \n
\n \n \n );\n }\n}\n\nPeripheralTile.propTypes = {\n connectionSmallIconURL: PropTypes.string,\n name: PropTypes.string,\n onConnecting: PropTypes.func,\n peripheralId: PropTypes.string,\n rssi: PropTypes.number\n};\n\nexport default PeripheralTile;\n","import {FormattedMessage} from 'react-intl';\nimport PropTypes from 'prop-types';\nimport React from 'react';\nimport classNames from 'classnames';\n\nimport BalancedFormattedMessage from '../../containers/balanced-formatted-message.jsx';\nimport Box from '../box/box.jsx';\nimport PeripheralTile from './peripheral-tile.jsx';\nimport Dots from './dots.jsx';\n\nimport enterUpdateIcon from './icons/enter-update.svg';\nimport radarIcon from './icons/searching.png';\nimport refreshIcon from './icons/refresh.svg';\nimport warningIcon from './icons/warning.svg';\n\nimport styles from './connection-modal.css';\n\nconst ScanningStep = props => {\n const showUpdate = !!(props.onUpdatePeripheral && !props.scanning);\n return (
\n \n {props.scanning ? (\n props.peripheralList.length === 0 ? (\n \n
\n
\n
\n
\n
\n ) : (\n \n {props.peripheralList.map(peripheral =>\n (
)\n )}\n
\n )\n ) : (\n \n \n \n \n )}\n \n \n \n {(props.scanning || props.peripheralList.length > 0) && (\n // Show this message if we're still scanning OR if we've found devices\n \n )}\n {showUpdate && (\n // Show this message if we're done scanning AND we can update\n // Note that it's possible the list includes devices but does not include the desired device,\n // so don't limit this message to the (props.peripheralList.length === 0) case\n \n )}\n \n \n \n \n {showUpdate && (\n \n )}\n \n \n );\n};\n\nScanningStep.propTypes = {\n connectionSmallIconURL: PropTypes.string,\n onConnecting: PropTypes.func,\n onRefresh: PropTypes.func,\n onUpdatePeripheral: PropTypes.func,\n peripheralList: PropTypes.arrayOf(PropTypes.shape({\n name: PropTypes.string,\n rssi: PropTypes.number,\n peripheralId: PropTypes.string\n })),\n scanning: PropTypes.bool.isRequired\n};\n\nScanningStep.defaultProps = {\n peripheralList: [],\n scanning: true\n};\n\nexport default ScanningStep;\n","import {FormattedMessage} from 'react-intl';\nimport PropTypes from 'prop-types';\nimport classNames from 'classnames';\nimport React from 'react';\n\nimport Box from '../box/box.jsx';\nimport Dots from './dots.jsx';\nimport helpIcon from './icons/help.svg';\nimport backIcon from './icons/back.svg';\nimport bluetoothIcon from './icons/bluetooth.svg';\nimport scratchLinkIcon from './icons/scratchlink.svg';\n\nimport styles from './connection-modal.css';\n\nconst UnavailableStep = props => (\n
\n \n \n
\n
\n {'1'}\n
\n
\n
\n
\n
\n \n
\n
\n
\n
\n {'2'}\n
\n
\n
\n
\n
\n \n
\n
\n
\n \n \n \n \n \n \n \n \n \n);\n\nUnavailableStep.propTypes = {\n onHelp: PropTypes.func,\n onScanning: PropTypes.func\n};\n\nexport default UnavailableStep;\n","import 'regenerator-runtime/runtime';\nimport {FormattedMessage} from 'react-intl';\nimport PropTypes from 'prop-types';\nimport classNames from 'classnames';\nimport React from 'react';\nimport bindAll from 'lodash.bindall';\nimport keyMirror from 'keymirror';\n\nimport BalancedFormattedMessage from '../../containers/balanced-formatted-message.jsx';\nimport Box from '../box/box.jsx';\nimport ProgressRingComponent from '../progress-ring/progress-ring.jsx';\n\nimport backIcon from './icons/back.svg';\nimport sendUpdateIcon from './icons/send-update.svg';\nimport sendUpdateGlyph from './icons/send-update-white.svg';\n\nimport styles from './connection-modal.css';\n\n/** @enum{string} UPDATE_ACTIVITY */\nconst UPDATE_ACTIVITY = keyMirror({\n getReady: null,\n sendUpdate: null,\n results: null\n});\n\nconst microBitFirmwareUrl = 'https://microbit.org/get-started/user-guide/firmware/';\n\nclass UpdatePeripheralStep extends React.Component {\n constructor (props) {\n super(props);\n bindAll(this, [\n 'handleSendUpdate'\n ]);\n this.state = {\n /** @type {UPDATE_ACTIVITY} */\n activity: UPDATE_ACTIVITY.getReady,\n\n /** @type {number} */\n progressPercentage: 0,\n\n /** @type {Error?} */\n err: null,\n\n /** @type {any} */\n res: null\n };\n }\n\n async handleSendUpdate () {\n this.setState({\n activity: UPDATE_ACTIVITY.sendUpdate,\n progress: 0,\n err: null,\n res: null\n });\n try {\n const res = await this.props.onSendPeripheralUpdate(progress => {\n // On my computer, I get a progress update every 0.005% or so.\n // Rendering the progress ring is a little expensive, so filtering updates here reduces the CPU load.\n // Updating every 1% doesn't look very smooth, but 0.5% (1/200) looks good to me.\n this.setState({progressPercentage: Math.floor(progress * 200) / 2});\n });\n this.setState({\n activity: UPDATE_ACTIVITY.results,\n res\n });\n } catch (err) {\n this.setState({\n activity: UPDATE_ACTIVITY.results,\n err\n });\n }\n }\n\n renderGetReady () {\n return (
\n \n \n \n {'1'}\n \n \n {\n // The instructions for getting the peripheral ready for the update process will vary\n // depending on the peripheral. Should we get this from the extension somehow?\n }\n \n \n \n \n {'2'}\n \n \n \n \n \n );\n }\n\n renderSendUpdate () {\n return (
\n \n \n );\n }\n\n renderResults () {\n let resultsContent;\n if (this.state.err === null) {\n resultsContent = (
);\n } else if (this.state.err.message === 'No valid interfaces found.') {\n // this is a special case where the micro:bit's communication firmware is too old to support WebUSB\n resultsContent = (
\n {microBitFirmwareUrl}\n \n }}\n />);\n } else {\n resultsContent = (\n \n \n \n \n );\n }\n return (\n {resultsContent}\n );\n }\n\n render () {\n const showGetReady = this.state.activity === UPDATE_ACTIVITY.getReady;\n const showSendUpdate = this.state.activity === UPDATE_ACTIVITY.sendUpdate;\n const showResults = this.state.activity === UPDATE_ACTIVITY.results;\n const showBadResults = showResults && !!this.state.err;\n return (\n \n {showGetReady && this.renderGetReady()}\n {showSendUpdate && this.renderSendUpdate()}\n {showResults && this.renderResults()}\n \n {!showResults &&\n \n }\n {!showSendUpdate &&\n \n \n {(showGetReady || showBadResults) &&\n \n }\n \n }\n \n \n );\n }\n}\n\nUpdatePeripheralStep.propTypes = {\n connectionSmallIconURL: PropTypes.string,\n name: PropTypes.string.isRequired,\n onScanning: PropTypes.func.isRequired,\n onSendPeripheralUpdate: PropTypes.func.isRequired\n};\n\nexport default UpdatePeripheralStep;\n","\nvar content = require(\"!!../../../node_modules/css-loader/index.js??ref--5-1!../../../node_modules/postcss-loader/src/index.js??postcss!./context-menu.css\");\n\nif(typeof content === 'string') content = [[module.id, content, '']];\n\nvar transform;\nvar insertInto;\n\n\n\nvar options = {\"hmr\":true}\n\noptions.transform = transform\noptions.insertInto = undefined;\n\nvar update = require(\"!../../../node_modules/style-loader/lib/addStyles.js\")(content, options);\n\nif(content.locals) module.exports = content.locals;\n\nif(module.hot) {\n\tmodule.hot.accept(\"!!../../../node_modules/css-loader/index.js??ref--5-1!../../../node_modules/postcss-loader/src/index.js??postcss!./context-menu.css\", function() {\n\t\tvar newContent = require(\"!!../../../node_modules/css-loader/index.js??ref--5-1!../../../node_modules/postcss-loader/src/index.js??postcss!./context-menu.css\");\n\n\t\tif(typeof newContent === 'string') newContent = [[module.id, newContent, '']];\n\n\t\tvar locals = (function(a, b) {\n\t\t\tvar key, idx = 0;\n\n\t\t\tfor(key in a) {\n\t\t\t\tif(!b || a[key] !== b[key]) return false;\n\t\t\t\tidx++;\n\t\t\t}\n\n\t\t\tfor(key in b) idx--;\n\n\t\t\treturn idx === 0;\n\t\t}(content.locals, newContent.locals));\n\n\t\tif(!locals) throw new Error('Aborting CSS HMR due to changed css-modules locals.');\n\n\t\tupdate(newContent);\n\t});\n\n\tmodule.hot.dispose(function() { update(); });\n}","import React from 'react';\nimport {ContextMenu, MenuItem} from 'react-contextmenu';\nimport classNames from 'classnames';\n\nimport styles from './context-menu.css';\n\nconst StyledContextMenu = props => (\n \n);\n\nconst StyledMenuItem = props => (\n \n);\n\nconst BorderedMenuItem = props => (\n \n);\n\nconst DangerousMenuItem = props => (\n \n);\n\n\nexport {\n BorderedMenuItem,\n DangerousMenuItem,\n StyledContextMenu as ContextMenu,\n StyledMenuItem as MenuItem\n};\n","\nvar content = require(\"!!../../../node_modules/css-loader/index.js??ref--5-1!../../../node_modules/postcss-loader/src/index.js??postcss!./controls.css\");\n\nif(typeof content === 'string') content = [[module.id, content, '']];\n\nvar transform;\nvar insertInto;\n\n\n\nvar options = {\"hmr\":true}\n\noptions.transform = transform\noptions.insertInto = undefined;\n\nvar update = require(\"!../../../node_modules/style-loader/lib/addStyles.js\")(content, options);\n\nif(content.locals) module.exports = content.locals;\n\nif(module.hot) {\n\tmodule.hot.accept(\"!!../../../node_modules/css-loader/index.js??ref--5-1!../../../node_modules/postcss-loader/src/index.js??postcss!./controls.css\", function() {\n\t\tvar newContent = require(\"!!../../../node_modules/css-loader/index.js??ref--5-1!../../../node_modules/postcss-loader/src/index.js??postcss!./controls.css\");\n\n\t\tif(typeof newContent === 'string') newContent = [[module.id, newContent, '']];\n\n\t\tvar locals = (function(a, b) {\n\t\t\tvar key, idx = 0;\n\n\t\t\tfor(key in a) {\n\t\t\t\tif(!b || a[key] !== b[key]) return false;\n\t\t\t\tidx++;\n\t\t\t}\n\n\t\t\tfor(key in b) idx--;\n\n\t\t\treturn idx === 0;\n\t\t}(content.locals, newContent.locals));\n\n\t\tif(!locals) throw new Error('Aborting CSS HMR due to changed css-modules locals.');\n\n\t\tupdate(newContent);\n\t});\n\n\tmodule.hot.dispose(function() { update(); });\n}","import classNames from 'classnames';\nimport PropTypes from 'prop-types';\nimport React from 'react';\nimport {defineMessages, injectIntl, intlShape} from 'react-intl';\n\nimport GreenFlag from '../green-flag/green-flag.jsx';\nimport StopAll from '../stop-all/stop-all.jsx';\nimport TurboMode from '../turbo-mode/turbo-mode.jsx';\nimport FramerateIndicator from '../tw-framerate-indicator/framerate-indicator.jsx';\n\nimport styles from './controls.css';\n\nconst messages = defineMessages({\n goTitle: {\n id: 'gui.controls.go',\n defaultMessage: 'Go',\n description: 'Green flag button title'\n },\n stopTitle: {\n id: 'gui.controls.stop',\n defaultMessage: 'Stop',\n description: 'Stop button title'\n }\n});\n\nconst Controls = function (props) {\n const {\n active,\n className,\n intl,\n onGreenFlagClick,\n onStopAllClick,\n turbo,\n framerate,\n interpolation,\n isSmall,\n ...componentProps\n } = props;\n return (\n \n \n \n {turbo ? (\n \n ) : null}\n {!isSmall && (\n \n )}\n
\n );\n};\n\nControls.propTypes = {\n active: PropTypes.bool,\n className: PropTypes.string,\n intl: intlShape.isRequired,\n onGreenFlagClick: PropTypes.func.isRequired,\n onStopAllClick: PropTypes.func.isRequired,\n framerate: PropTypes.number,\n interpolation: PropTypes.bool,\n isSmall: PropTypes.bool,\n turbo: PropTypes.bool\n};\n\nControls.defaultProps = {\n active: false,\n turbo: false,\n isSmall: false\n};\n\nexport default injectIntl(Controls);\n","\nvar content = require(\"!!../../../node_modules/css-loader/index.js??ref--5-1!../../../node_modules/postcss-loader/src/index.js??postcss!./crash-message.css\");\n\nif(typeof content === 'string') content = [[module.id, content, '']];\n\nvar transform;\nvar insertInto;\n\n\n\nvar options = {\"hmr\":true}\n\noptions.transform = transform\noptions.insertInto = undefined;\n\nvar update = require(\"!../../../node_modules/style-loader/lib/addStyles.js\")(content, options);\n\nif(content.locals) module.exports = content.locals;\n\nif(module.hot) {\n\tmodule.hot.accept(\"!!../../../node_modules/css-loader/index.js??ref--5-1!../../../node_modules/postcss-loader/src/index.js??postcss!./crash-message.css\", function() {\n\t\tvar newContent = require(\"!!../../../node_modules/css-loader/index.js??ref--5-1!../../../node_modules/postcss-loader/src/index.js??postcss!./crash-message.css\");\n\n\t\tif(typeof newContent === 'string') newContent = [[module.id, newContent, '']];\n\n\t\tvar locals = (function(a, b) {\n\t\t\tvar key, idx = 0;\n\n\t\t\tfor(key in a) {\n\t\t\t\tif(!b || a[key] !== b[key]) return false;\n\t\t\t\tidx++;\n\t\t\t}\n\n\t\t\tfor(key in b) idx--;\n\n\t\t\treturn idx === 0;\n\t\t}(content.locals, newContent.locals));\n\n\t\tif(!locals) throw new Error('Aborting CSS HMR due to changed css-modules locals.');\n\n\t\tupdate(newContent);\n\t});\n\n\tmodule.hot.dispose(function() { update(); });\n}","import PropTypes from 'prop-types';\nimport React from 'react';\nimport Box from '../box/box.jsx';\nimport {FormattedMessage} from 'react-intl';\n\nimport styles from './crash-message.css';\nimport reloadIcon from './reload.svg';\n\nconst CrashMessage = props => (\n \n
\n \n \n \n
\n \n \n
\n {props.errorMessage && (\n \n {props.errorMessage}\n
\n )}\n {props.eventId && (\n \n \n
\n )}\n \n \n
\n);\n\nCrashMessage.propTypes = {\n eventId: PropTypes.string,\n errorMessage: PropTypes.string,\n onReload: PropTypes.func.isRequired\n};\n\nexport default CrashMessage;\n","module.exports = \"data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyB3aWR0aD0iNDBweCIgaGVpZ2h0PSI0N3B4IiB2aWV3Qm94PSIwIDAgNDAgNDciIHZlcnNpb249IjEuMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayI+CiAgICA8IS0tIEdlbmVyYXRvcjogU2tldGNoIDQ4LjIgKDQ3MzI3KSAtIGh0dHA6Ly93d3cuYm9oZW1pYW5jb2RpbmcuY29tL3NrZXRjaCAtLT4KICAgIDx0aXRsZT5SZWxvYWQ8L3RpdGxlPgogICAgPGRlc2M+Q3JlYXRlZCB3aXRoIFNrZXRjaC48L2Rlc2M+CiAgICA8ZGVmcz48L2RlZnM+CiAgICA8ZyBpZD0iVjItLS1HZW5lcmFsLU9vcHMiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIxIiBmaWxsPSJub25lIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC02MjEuMDAwMDAwLCAtMjI0LjAwMDAwMCkiPgogICAgICAgIDxnIGlkPSJ2MS1XZWxjb21lLU1vZGFsLSIgZmlsbD0iI0ZGRkZGRiI+CiAgICAgICAgICAgIDxnIGlkPSJVbnN1cHBvcnRlZCIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoNDI4LjAwMDAwMCwgMjE5LjAwMDAwMCkiPgogICAgICAgICAgICAgICAgPHBhdGggZD0iTTIzMywzMS44OTY0NjgxIEMyMzMsNDIuOTM2ODgzOSAyMjQuMDM4NjI0LDUxLjg5ODI2MDMgMjEzLjAwMTc5Miw1MS44OTgyNjAzIEMyMDEuOTk3MjIyLDUxLjg5ODI2MDMgMTkzLDQyLjkzNjg4MzkgMTkzLDMxLjg5NjQ2ODEgQzE5MywyMS40Mjk1ODA0IDIwMS4xMzMzNDUsMTIuODI2NjU4OSAyMTEuMzg4NzQ1LDEyLjAwMjIxMjMgTDIxMS4zODg3NDUsNy40ODU2Nzg1NyBDMjExLjM4ODc0NSw1LjUxNDE3NTc1IDIxMy41MzU4OSw0LjMzMTI3NDA1IDIxNS4yMjA2MjksNS40MDY2MzkyMyBMMjI2Ljk3Nzk1NSwxMi45NzAwNDEgQzIyOC41MTkzMTIsMTMuOTM3ODY5NiAyMjguNTE5MzEyLDE2LjE2MDI5MSAyMjYuOTc3OTU1LDE3LjE2Mzk2NTIgTDIxNS4yMjA2MjksMjQuNjkxNTIxNCBDMjEzLjUzNTg5LDI1Ljc2Njg4NjYgMjExLjM4ODc0NSwyNC41ODM5ODQ5IDIxMS4zODg3NDUsMjIuNjEyNDgyIEwyMTEuMzg4NzQ1LDE4LjMxMTAyMTMgQzIwNC41NzQ1MTQsMTkuMDk5NjIyNSAxOTkuMjcyOTY0LDI0Ljg3MDc0ODkgMTk5LjI3Mjk2NCwzMS44OTY0NjgxIEMxOTkuMjcyOTY0LDM5LjQ5NTcxNTMgMjA1LjQzODM5MSw0NS42MjUyOTY4IDIxMy4wMDE3OTIsNDUuNjI1Mjk2OCBDMjIwLjU2MTYwOSw0NS42MjUyOTY4IDIyNi43MjcwMzYsMzkuNDk1NzE1MyAyMjYuNzI3MDM2LDMxLjg5NjQ2ODEgQzIyNi43MjcwMzYsMzAuMTc5NDY4MyAyMjguMTI4NTk2LDI4Ljc3NzkwOTEgMjI5Ljg4MTQ0MSwyOC43Nzc5MDkxIEMyMzEuNjAyMDI1LDI4Ljc3NzkwOTEgMjMzLDMwLjE3OTQ2ODMgMjMzLDMxLjg5NjQ2ODEiIGlkPSJSZWxvYWQiPjwvcGF0aD4KICAgICAgICAgICAgPC9nPgogICAgICAgIDwvZz4KICAgIDwvZz4KPC9zdmc+\"","\nvar content = require(\"!!../../../node_modules/css-loader/index.js??ref--5-1!../../../node_modules/postcss-loader/src/index.js??postcss!./custom-procedures.css\");\n\nif(typeof content === 'string') content = [[module.id, content, '']];\n\nvar transform;\nvar insertInto;\n\n\n\nvar options = {\"hmr\":true}\n\noptions.transform = transform\noptions.insertInto = undefined;\n\nvar update = require(\"!../../../node_modules/style-loader/lib/addStyles.js\")(content, options);\n\nif(content.locals) module.exports = content.locals;\n\nif(module.hot) {\n\tmodule.hot.accept(\"!!../../../node_modules/css-loader/index.js??ref--5-1!../../../node_modules/postcss-loader/src/index.js??postcss!./custom-procedures.css\", function() {\n\t\tvar newContent = require(\"!!../../../node_modules/css-loader/index.js??ref--5-1!../../../node_modules/postcss-loader/src/index.js??postcss!./custom-procedures.css\");\n\n\t\tif(typeof newContent === 'string') newContent = [[module.id, newContent, '']];\n\n\t\tvar locals = (function(a, b) {\n\t\t\tvar key, idx = 0;\n\n\t\t\tfor(key in a) {\n\t\t\t\tif(!b || a[key] !== b[key]) return false;\n\t\t\t\tidx++;\n\t\t\t}\n\n\t\t\tfor(key in b) idx--;\n\n\t\t\treturn idx === 0;\n\t\t}(content.locals, newContent.locals));\n\n\t\tif(!locals) throw new Error('Aborting CSS HMR due to changed css-modules locals.');\n\n\t\tupdate(newContent);\n\t});\n\n\tmodule.hot.dispose(function() { update(); });\n}","import PropTypes from 'prop-types';\nimport React from 'react';\nimport Modal from '../../containers/modal.jsx';\nimport Box from '../box/box.jsx';\nimport {defineMessages, injectIntl, intlShape, FormattedMessage} from 'react-intl';\n\nimport booleanInputIcon from './icon--boolean-input.svg';\nimport textInputIcon from './icon--text-input.svg';\nimport labelIcon from './icon--label.svg';\n\nimport styles from './custom-procedures.css';\n\nconst messages = defineMessages({\n myblockModalTitle: {\n defaultMessage: 'Make a Block',\n description: 'Title for the modal where you create a custom block.',\n id: 'gui.customProcedures.myblockModalTitle'\n }\n});\n\nconst CustomProcedures = props => (\n \n \n \n \n
\n
\n
\n \n
\n
\n \n
\n
\n
\n
\n
\n \n
\n
\n \n
\n
\n
\n
\n
\n \n
\n
\n
\n \n \n
\n \n \n \n \n \n \n);\n\nCustomProcedures.propTypes = {\n componentRef: PropTypes.func.isRequired,\n intl: intlShape,\n onAddBoolean: PropTypes.func.isRequired,\n onAddLabel: PropTypes.func.isRequired,\n onAddTextNumber: PropTypes.func.isRequired,\n onCancel: PropTypes.func.isRequired,\n onOk: PropTypes.func.isRequired,\n onToggleWarp: PropTypes.func.isRequired,\n warp: PropTypes.bool.isRequired\n};\n\nexport default injectIntl(CustomProcedures);\n","module.exports = \"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA1NyA0OSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtvcGFjaXR5OjAuMzt9LmNscy0ye29wYWNpdHk6MC4xO30uY2xzLTN7ZmlsbDojZmY2NjgwO3N0cm9rZS1taXRlcmxpbWl0OjEwO30uY2xzLTMsLmNscy00e3N0cm9rZTojZjM1O30uY2xzLTR7ZmlsbDojZmY0ZDZhO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZDt9PC9zdHlsZT48L2RlZnM+PHRpdGxlPlIxXyBDLlByb2NlZHVyZSBFZGl0YmxlIElucHV0czwvdGl0bGU+PGcgaWQ9ImJvb2xlYW5fYm9vbGVhbl9pbnB1dHMiIGRhdGEtbmFtZT0iYm9vbGVhbiArIGJvb2xlYW4gaW5wdXRzIj48cmVjdCBjbGFzcz0iY2xzLTMiIHg9IjAuNSIgeT0iMC41IiB3aWR0aD0iNTYiIGhlaWdodD0iNDgiIHJ4PSI0IiByeT0iNCIvPjxwYXRoIGNsYXNzPSJjbHMtNCIgZD0iTTMyLjUsNDAuNWgtOGwtMTYtMTZoMGwxNi0xNmg4bDE2LDE2aDBaIi8+PC9nPjwvc3ZnPg==\"","module.exports = \"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA1NyA0OSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtvcGFjaXR5OjAuMzt9LmNscy0ye29wYWNpdHk6MC4xO30uY2xzLTN7ZmlsbDojZmY2NjgwO3N0cm9rZTojZjM1O3N0cm9rZS1taXRlcmxpbWl0OjEwO30uY2xzLTR7Zm9udC1zaXplOjEycHg7ZmlsbDojZmZmO2ZvbnQtZmFtaWx5OkhlbHZldGljYU5ldWUtQm9sZCwgSGVsdmV0aWNhIE5ldWUsIHNhbnMtc2VyaWY7Zm9udC13ZWlnaHQ6NzAwO2xldHRlci1zcGFjaW5nOjBlbTt9PC9zdHlsZT48L2RlZnM+PHRpdGxlPlIxXyBDLlByb2NlZHVyZSBFZGl0YmxlIElucHV0czwvdGl0bGU+PGcgaWQ9ImJvb2xlYW5fYm9vbGVhbl9pbnB1dHMiIGRhdGEtbmFtZT0iYm9vbGVhbiArIGJvb2xlYW4gaW5wdXRzIj48cmVjdCBjbGFzcz0iY2xzLTMiIHg9IjAuNSIgeT0iMC41IiB3aWR0aD0iNTYiIGhlaWdodD0iNDgiIHJ4PSI0IiByeT0iNCIvPjx0ZXh0IGNsYXNzPSJjbHMtNCIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMTcuNTcgMjcuNSkiPnRleHQ8L3RleHQ+PC9nPjwvc3ZnPgo=\"","module.exports = \"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA1NyA0OSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtvcGFjaXR5OjAuMzt9LmNscy0ye29wYWNpdHk6MC4xO30uY2xzLTN7ZmlsbDojZmY2NjgwO3N0cm9rZS1taXRlcmxpbWl0OjEwO30uY2xzLTMsLmNscy00e3N0cm9rZTojZjM1O30uY2xzLTR7ZmlsbDojZmY0ZDZhO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZDt9PC9zdHlsZT48L2RlZnM+PHRpdGxlPlIxXyBDLlByb2NlZHVyZSBFZGl0YmxlIElucHV0czwvdGl0bGU+PGcgaWQ9ImJvb2xlYW5fYm9vbGVhbl9pbnB1dHMiIGRhdGEtbmFtZT0iYm9vbGVhbiArIGJvb2xlYW4gaW5wdXRzIj48cmVjdCBjbGFzcz0iY2xzLTMiIHg9IjAuNSIgeT0iMC41IiB3aWR0aD0iNTYiIGhlaWdodD0iNDgiIHJ4PSI0IiByeT0iNCIvPjxyZWN0IGNsYXNzPSJjbHMtNCIgeD0iOC41IiB5PSI4LjUiIHdpZHRoPSI0MCIgaGVpZ2h0PSIzMiIgcng9IjE2IiByeT0iMTYiLz48L2c+PC9zdmc+\"","\nvar content = require(\"!!../../../node_modules/css-loader/index.js??ref--5-1!../../../node_modules/postcss-loader/src/index.js??postcss!./delete-button.css\");\n\nif(typeof content === 'string') content = [[module.id, content, '']];\n\nvar transform;\nvar insertInto;\n\n\n\nvar options = {\"hmr\":true}\n\noptions.transform = transform\noptions.insertInto = undefined;\n\nvar update = require(\"!../../../node_modules/style-loader/lib/addStyles.js\")(content, options);\n\nif(content.locals) module.exports = content.locals;\n\nif(module.hot) {\n\tmodule.hot.accept(\"!!../../../node_modules/css-loader/index.js??ref--5-1!../../../node_modules/postcss-loader/src/index.js??postcss!./delete-button.css\", function() {\n\t\tvar newContent = require(\"!!../../../node_modules/css-loader/index.js??ref--5-1!../../../node_modules/postcss-loader/src/index.js??postcss!./delete-button.css\");\n\n\t\tif(typeof newContent === 'string') newContent = [[module.id, newContent, '']];\n\n\t\tvar locals = (function(a, b) {\n\t\t\tvar key, idx = 0;\n\n\t\t\tfor(key in a) {\n\t\t\t\tif(!b || a[key] !== b[key]) return false;\n\t\t\t\tidx++;\n\t\t\t}\n\n\t\t\tfor(key in b) idx--;\n\n\t\t\treturn idx === 0;\n\t\t}(content.locals, newContent.locals));\n\n\t\tif(!locals) throw new Error('Aborting CSS HMR due to changed css-modules locals.');\n\n\t\tupdate(newContent);\n\t});\n\n\tmodule.hot.dispose(function() { update(); });\n}","import PropTypes from 'prop-types';\nimport React from 'react';\nimport classNames from 'classnames';\n\nimport styles from './delete-button.css';\nimport deleteIcon from './icon--delete.svg';\n\nconst DeleteButton = props => (\n \n
\n
\n
\n
\n\n);\n\nDeleteButton.propTypes = {\n className: PropTypes.string,\n onClick: PropTypes.func.isRequired,\n tabIndex: PropTypes.number\n};\n\nDeleteButton.defaultProps = {\n tabIndex: 0\n};\n\nexport default DeleteButton;\n","module.exports = __webpack_public_path__ + \"static/assets/bc0fbf502b38884f440135ddae40016d.svg\";","\nvar content = require(\"!!../../../node_modules/css-loader/index.js??ref--5-1!../../../node_modules/postcss-loader/src/index.js??postcss!./dial.css\");\n\nif(typeof content === 'string') content = [[module.id, content, '']];\n\nvar transform;\nvar insertInto;\n\n\n\nvar options = {\"hmr\":true}\n\noptions.transform = transform\noptions.insertInto = undefined;\n\nvar update = require(\"!../../../node_modules/style-loader/lib/addStyles.js\")(content, options);\n\nif(content.locals) module.exports = content.locals;\n\nif(module.hot) {\n\tmodule.hot.accept(\"!!../../../node_modules/css-loader/index.js??ref--5-1!../../../node_modules/postcss-loader/src/index.js??postcss!./dial.css\", function() {\n\t\tvar newContent = require(\"!!../../../node_modules/css-loader/index.js??ref--5-1!../../../node_modules/postcss-loader/src/index.js??postcss!./dial.css\");\n\n\t\tif(typeof newContent === 'string') newContent = [[module.id, newContent, '']];\n\n\t\tvar locals = (function(a, b) {\n\t\t\tvar key, idx = 0;\n\n\t\t\tfor(key in a) {\n\t\t\t\tif(!b || a[key] !== b[key]) return false;\n\t\t\t\tidx++;\n\t\t\t}\n\n\t\t\tfor(key in b) idx--;\n\n\t\t\treturn idx === 0;\n\t\t}(content.locals, newContent.locals));\n\n\t\tif(!locals) throw new Error('Aborting CSS HMR due to changed css-modules locals.');\n\n\t\tupdate(newContent);\n\t});\n\n\tmodule.hot.dispose(function() { update(); });\n}","import PropTypes from 'prop-types';\nimport bindAll from 'lodash.bindall';\nimport React from 'react';\nimport {getEventXY} from '../../lib/touch-utils';\n\nimport styles from './dial.css';\n\nimport dialFace from '!../../lib/tw-recolor/build!./icon--dial.svg';\nimport dialHandle from '!../../lib/tw-recolor/build!./icon--handle.svg';\n\nclass Dial extends React.Component {\n constructor (props) {\n super(props);\n bindAll(this, [\n 'handleMouseDown',\n 'handleMouseMove',\n 'containerRef',\n 'handleRef',\n 'unbindMouseEvents'\n ]);\n }\n\n componentDidMount () {\n // Manually add touch/mouse handlers so that preventDefault can be used\n // to prevent scrolling on touch.\n // Tracked as a react issue https://github.com/facebook/react/issues/6436\n this.handleElement.addEventListener('mousedown', this.handleMouseDown);\n this.handleElement.addEventListener('touchstart', this.handleMouseDown);\n }\n\n componentWillUnmount () {\n this.unbindMouseEvents();\n this.handleElement.removeEventListener('mousedown', this.handleMouseDown);\n this.handleElement.removeEventListener('touchstart', this.handleMouseDown);\n }\n\n /**\n * Get direction from dial center to mouse move event.\n * @param {Event} e - Mouse move event.\n * @returns {number} Direction in degrees, clockwise, 90=horizontal.\n */\n directionToMouseEvent (e) {\n const {x: mx, y: my} = getEventXY(e);\n const bbox = this.containerElement.getBoundingClientRect();\n const cy = bbox.top + (bbox.height / 2);\n const cx = bbox.left + (bbox.width / 2);\n const angle = Math.atan2(my - cy, mx - cx);\n const degrees = angle * (180 / Math.PI);\n return degrees + 90; // To correspond with scratch coordinate system\n }\n\n /**\n * Create SVG path data string for the dial \"gauge\", the overlaid arc slice.\n * @param {number} radius - The radius of the dial.\n * @param {number} direction - Direction in degrees, clockwise, 90=horizontal.\n * @returns {string} Path data string for the gauge.\n */\n gaugePath (radius, direction) {\n const rads = (direction) * (Math.PI / 180);\n const path = [];\n path.push(`M ${radius} 0`);\n path.push(`L ${radius} ${radius}`);\n path.push(`L ${radius + (radius * Math.sin(rads))} ${radius - (radius * Math.cos(rads))}`);\n path.push(`A ${radius} ${radius} 0 0 ${direction < 0 ? 1 : 0} ${radius} 0`);\n path.push(`Z`);\n return path.join(' ');\n }\n\n handleMouseMove (e) {\n this.props.onChange(this.directionToMouseEvent(e) + this.directionOffset);\n e.preventDefault();\n }\n\n unbindMouseEvents () {\n window.removeEventListener('mousemove', this.handleMouseMove);\n window.removeEventListener('mouseup', this.unbindMouseEvents);\n window.removeEventListener('touchmove', this.handleMouseMove);\n window.removeEventListener('touchend', this.unbindMouseEvents);\n }\n\n handleMouseDown (e) {\n // Because the drag handle is not a single point, there is some initial\n // difference between the current sprite direction and the direction to the mouse\n // Store this offset to prevent jumping when the mouse is moved.\n this.directionOffset = this.props.direction - this.directionToMouseEvent(e);\n window.addEventListener('mousemove', this.handleMouseMove);\n window.addEventListener('mouseup', this.unbindMouseEvents);\n window.addEventListener('touchmove', this.handleMouseMove);\n window.addEventListener('touchend', this.unbindMouseEvents);\n e.preventDefault();\n }\n\n containerRef (el) {\n this.containerElement = el;\n }\n\n handleRef (el) {\n this.handleElement = el;\n }\n\n render () {\n const {direction, radius} = this.props;\n return (\n \n
\n
\n
\n
\n
\n
\n );\n }\n}\n\nDial.propTypes = {\n direction: PropTypes.number,\n onChange: PropTypes.func.isRequired,\n radius: PropTypes.number\n};\n\nDial.defaultProps = {\n direction: 90, // degrees\n radius: 56 // px\n};\n\nexport default Dial;\n","\nvar content = require(\"!!../../../node_modules/css-loader/index.js??ref--5-1!../../../node_modules/postcss-loader/src/index.js??postcss!./direction-picker.css\");\n\nif(typeof content === 'string') content = [[module.id, content, '']];\n\nvar transform;\nvar insertInto;\n\n\n\nvar options = {\"hmr\":true}\n\noptions.transform = transform\noptions.insertInto = undefined;\n\nvar update = require(\"!../../../node_modules/style-loader/lib/addStyles.js\")(content, options);\n\nif(content.locals) module.exports = content.locals;\n\nif(module.hot) {\n\tmodule.hot.accept(\"!!../../../node_modules/css-loader/index.js??ref--5-1!../../../node_modules/postcss-loader/src/index.js??postcss!./direction-picker.css\", function() {\n\t\tvar newContent = require(\"!!../../../node_modules/css-loader/index.js??ref--5-1!../../../node_modules/postcss-loader/src/index.js??postcss!./direction-picker.css\");\n\n\t\tif(typeof newContent === 'string') newContent = [[module.id, newContent, '']];\n\n\t\tvar locals = (function(a, b) {\n\t\t\tvar key, idx = 0;\n\n\t\t\tfor(key in a) {\n\t\t\t\tif(!b || a[key] !== b[key]) return false;\n\t\t\t\tidx++;\n\t\t\t}\n\n\t\t\tfor(key in b) idx--;\n\n\t\t\treturn idx === 0;\n\t\t}(content.locals, newContent.locals));\n\n\t\tif(!locals) throw new Error('Aborting CSS HMR due to changed css-modules locals.');\n\n\t\tupdate(newContent);\n\t});\n\n\tmodule.hot.dispose(function() { update(); });\n}","import React from 'react';\nimport PropTypes from 'prop-types';\nimport Popover from 'react-popover';\nimport {injectIntl, intlShape, defineMessages, FormattedMessage} from 'react-intl';\n\nimport Label from '../forms/label.jsx';\nimport Input from '../forms/input.jsx';\nimport BufferedInputHOC from '../forms/buffered-input-hoc.jsx';\nimport ToggleButtons from '../toggle-buttons/toggle-buttons.jsx';\nimport Dial from './dial.jsx';\n\nimport styles from './direction-picker.css';\n\nimport allAroundIcon from '!../../lib/tw-recolor/build!./icon--all-around.svg';\nimport leftRightIcon from '!../../lib/tw-recolor/build!./icon--left-right.svg';\nimport dontRotateIcon from '!../../lib/tw-recolor/build!./icon--dont-rotate.svg';\n\nconst BufferedInput = BufferedInputHOC(Input);\n\nconst directionLabel = (\n \n);\n\nconst RotationStyles = {\n ALL_AROUND: 'all around',\n LEFT_RIGHT: 'left-right',\n DONT_ROTATE: \"don't rotate\"\n};\n\nconst messages = defineMessages({\n allAround: {\n id: 'gui.directionPicker.rotationStyles.allAround',\n description: 'Button to change to the all around rotation style',\n defaultMessage: 'All Around'\n },\n leftRight: {\n id: 'gui.directionPicker.rotationStyles.leftRight',\n description: 'Button to change to the left-right rotation style',\n defaultMessage: 'Left/Right'\n },\n dontRotate: {\n id: 'gui.directionPicker.rotationStyles.dontRotate',\n description: 'Button to change to the dont rotate rotation style',\n defaultMessage: 'Do not rotate'\n }\n});\n\nconst DirectionPicker = props => (\n \n }\n isOpen={props.popoverOpen}\n preferPlace=\"above\"\n onOuterAction={props.onClosePopover}\n >\n
\n \n \n\n);\n\nDirectionPicker.propTypes = {\n direction: PropTypes.number,\n disabled: PropTypes.bool.isRequired,\n intl: intlShape,\n labelAbove: PropTypes.bool,\n onChangeDirection: PropTypes.func.isRequired,\n onClickAllAround: PropTypes.func.isRequired,\n onClickDontRotate: PropTypes.func.isRequired,\n onClickLeftRight: PropTypes.func.isRequired,\n onClosePopover: PropTypes.func.isRequired,\n onOpenPopover: PropTypes.func.isRequired,\n popoverOpen: PropTypes.bool.isRequired,\n rotationStyle: PropTypes.string\n};\n\nDirectionPicker.defaultProps = {\n labelAbove: false\n};\n\nconst WrappedDirectionPicker = injectIntl(DirectionPicker);\n\nexport {\n WrappedDirectionPicker as default,\n RotationStyles\n};\n","\nvar content = require(\"!!../../../node_modules/css-loader/index.js??ref--5-1!../../../node_modules/postcss-loader/src/index.js??postcss!./divider.css\");\n\nif(typeof content === 'string') content = [[module.id, content, '']];\n\nvar transform;\nvar insertInto;\n\n\n\nvar options = {\"hmr\":true}\n\noptions.transform = transform\noptions.insertInto = undefined;\n\nvar update = require(\"!../../../node_modules/style-loader/lib/addStyles.js\")(content, options);\n\nif(content.locals) module.exports = content.locals;\n\nif(module.hot) {\n\tmodule.hot.accept(\"!!../../../node_modules/css-loader/index.js??ref--5-1!../../../node_modules/postcss-loader/src/index.js??postcss!./divider.css\", function() {\n\t\tvar newContent = require(\"!!../../../node_modules/css-loader/index.js??ref--5-1!../../../node_modules/postcss-loader/src/index.js??postcss!./divider.css\");\n\n\t\tif(typeof newContent === 'string') newContent = [[module.id, newContent, '']];\n\n\t\tvar locals = (function(a, b) {\n\t\t\tvar key, idx = 0;\n\n\t\t\tfor(key in a) {\n\t\t\t\tif(!b || a[key] !== b[key]) return false;\n\t\t\t\tidx++;\n\t\t\t}\n\n\t\t\tfor(key in b) idx--;\n\n\t\t\treturn idx === 0;\n\t\t}(content.locals, newContent.locals));\n\n\t\tif(!locals) throw new Error('Aborting CSS HMR due to changed css-modules locals.');\n\n\t\tupdate(newContent);\n\t});\n\n\tmodule.hot.dispose(function() { update(); });\n}","import classNames from 'classnames';\nimport PropTypes from 'prop-types';\nimport React from 'react';\n\nimport styles from './divider.css';\n\nconst Divider = ({className}) => (\n
\n);\n\nDivider.propTypes = {\n className: PropTypes.string\n};\n\nexport default Divider;\n","\nvar content = require(\"!!../../../node_modules/css-loader/index.js??ref--5-1!../../../node_modules/postcss-loader/src/index.js??postcss!./drag-layer.css\");\n\nif(typeof content === 'string') content = [[module.id, content, '']];\n\nvar transform;\nvar insertInto;\n\n\n\nvar options = {\"hmr\":true}\n\noptions.transform = transform\noptions.insertInto = undefined;\n\nvar update = require(\"!../../../node_modules/style-loader/lib/addStyles.js\")(content, options);\n\nif(content.locals) module.exports = content.locals;\n\nif(module.hot) {\n\tmodule.hot.accept(\"!!../../../node_modules/css-loader/index.js??ref--5-1!../../../node_modules/postcss-loader/src/index.js??postcss!./drag-layer.css\", function() {\n\t\tvar newContent = require(\"!!../../../node_modules/css-loader/index.js??ref--5-1!../../../node_modules/postcss-loader/src/index.js??postcss!./drag-layer.css\");\n\n\t\tif(typeof newContent === 'string') newContent = [[module.id, newContent, '']];\n\n\t\tvar locals = (function(a, b) {\n\t\t\tvar key, idx = 0;\n\n\t\t\tfor(key in a) {\n\t\t\t\tif(!b || a[key] !== b[key]) return false;\n\t\t\t\tidx++;\n\t\t\t}\n\n\t\t\tfor(key in b) idx--;\n\n\t\t\treturn idx === 0;\n\t\t}(content.locals, newContent.locals));\n\n\t\tif(!locals) throw new Error('Aborting CSS HMR due to changed css-modules locals.');\n\n\t\tupdate(newContent);\n\t});\n\n\tmodule.hot.dispose(function() { update(); });\n}","import React from 'react';\nimport PropTypes from 'prop-types';\nimport styles from './drag-layer.css';\n\n/* eslint no-confusing-arrow: [\"error\", {\"allowParens\": true}] */\nconst DragLayer = ({dragging, img, currentOffset}) => (dragging ? (\n
\n
\n
\n
\n
\n) : null);\n\nDragLayer.propTypes = {\n currentOffset: PropTypes.shape({\n x: PropTypes.number.isRequired,\n y: PropTypes.number.isRequired\n }),\n dragging: PropTypes.bool.isRequired,\n img: PropTypes.string\n};\n\nexport default DragLayer;\n","\nvar content = require(\"!!../../../node_modules/css-loader/index.js??ref--5-1!../../../node_modules/postcss-loader/src/index.js??postcss!./filter.css\");\n\nif(typeof content === 'string') content = [[module.id, content, '']];\n\nvar transform;\nvar insertInto;\n\n\n\nvar options = {\"hmr\":true}\n\noptions.transform = transform\noptions.insertInto = undefined;\n\nvar update = require(\"!../../../node_modules/style-loader/lib/addStyles.js\")(content, options);\n\nif(content.locals) module.exports = content.locals;\n\nif(module.hot) {\n\tmodule.hot.accept(\"!!../../../node_modules/css-loader/index.js??ref--5-1!../../../node_modules/postcss-loader/src/index.js??postcss!./filter.css\", function() {\n\t\tvar newContent = require(\"!!../../../node_modules/css-loader/index.js??ref--5-1!../../../node_modules/postcss-loader/src/index.js??postcss!./filter.css\");\n\n\t\tif(typeof newContent === 'string') newContent = [[module.id, newContent, '']];\n\n\t\tvar locals = (function(a, b) {\n\t\t\tvar key, idx = 0;\n\n\t\t\tfor(key in a) {\n\t\t\t\tif(!b || a[key] !== b[key]) return false;\n\t\t\t\tidx++;\n\t\t\t}\n\n\t\t\tfor(key in b) idx--;\n\n\t\t\treturn idx === 0;\n\t\t}(content.locals, newContent.locals));\n\n\t\tif(!locals) throw new Error('Aborting CSS HMR due to changed css-modules locals.');\n\n\t\tupdate(newContent);\n\t});\n\n\tmodule.hot.dispose(function() { update(); });\n}","import classNames from 'classnames';\nimport PropTypes from 'prop-types';\nimport React from 'react';\n\nimport TWRenderRecoloredImage from '../../lib/tw-recolor/render.jsx';\nimport filterIcon from '!../../lib/tw-recolor/build!./icon--filter.svg';\nimport xIcon from '!../../lib/tw-recolor/build!./icon--x.svg';\nimport styles from './filter.css';\n\nconst FilterComponent = props => {\n const {\n className,\n onChange,\n onClear,\n placeholderText,\n filterQuery,\n inputClassName\n } = props;\n return (\n
0\n })}\n >\n
\n
\n
\n \n
\n
\n );\n};\n\nFilterComponent.propTypes = {\n className: PropTypes.string,\n filterQuery: PropTypes.string,\n inputClassName: PropTypes.string,\n onChange: PropTypes.func,\n onClear: PropTypes.func,\n placeholderText: PropTypes.string\n};\nFilterComponent.defaultProps = {\n placeholderText: 'Search'\n};\nexport default FilterComponent;\n","import bindAll from 'lodash.bindall';\nimport PropTypes from 'prop-types';\nimport React from 'react';\n\n/**\n * Higher Order Component to manage inputs that submit on blur and
\n * @param {React.Component} Input text input that consumes onChange, onBlur, onKeyPress\n * @returns {React.Component} Buffered input that calls onSubmit on blur and \n */\nexport default function (Input) {\n class BufferedInput extends React.Component {\n constructor (props) {\n super(props);\n bindAll(this, [\n 'handleChange',\n 'handleKeyPress',\n 'handleFlush'\n ]);\n this.state = {\n value: null\n };\n }\n handleKeyPress (e) {\n if (e.key === 'Enter') {\n this.handleFlush();\n e.target.blur();\n }\n }\n handleFlush () {\n const isNumeric = typeof this.props.value === 'number';\n const validatesNumeric = isNumeric ? !isNaN(this.state.value) : true;\n if (this.state.value !== null && validatesNumeric) {\n this.props.onSubmit(isNumeric ? Number(this.state.value) : this.state.value);\n }\n this.setState({value: null});\n }\n handleChange (e) {\n this.setState({value: e.target.value});\n }\n render () {\n const bufferedValue = this.state.value === null ? this.props.value : this.state.value;\n return (\n \n );\n }\n }\n\n BufferedInput.propTypes = {\n onSubmit: PropTypes.func.isRequired,\n value: PropTypes.oneOfType([PropTypes.string, PropTypes.number])\n };\n\n return BufferedInput;\n}\n","\nvar content = require(\"!!../../../node_modules/css-loader/index.js??ref--5-1!../../../node_modules/postcss-loader/src/index.js??postcss!./input.css\");\n\nif(typeof content === 'string') content = [[module.id, content, '']];\n\nvar transform;\nvar insertInto;\n\n\n\nvar options = {\"hmr\":true}\n\noptions.transform = transform\noptions.insertInto = undefined;\n\nvar update = require(\"!../../../node_modules/style-loader/lib/addStyles.js\")(content, options);\n\nif(content.locals) module.exports = content.locals;\n\nif(module.hot) {\n\tmodule.hot.accept(\"!!../../../node_modules/css-loader/index.js??ref--5-1!../../../node_modules/postcss-loader/src/index.js??postcss!./input.css\", function() {\n\t\tvar newContent = require(\"!!../../../node_modules/css-loader/index.js??ref--5-1!../../../node_modules/postcss-loader/src/index.js??postcss!./input.css\");\n\n\t\tif(typeof newContent === 'string') newContent = [[module.id, newContent, '']];\n\n\t\tvar locals = (function(a, b) {\n\t\t\tvar key, idx = 0;\n\n\t\t\tfor(key in a) {\n\t\t\t\tif(!b || a[key] !== b[key]) return false;\n\t\t\t\tidx++;\n\t\t\t}\n\n\t\t\tfor(key in b) idx--;\n\n\t\t\treturn idx === 0;\n\t\t}(content.locals, newContent.locals));\n\n\t\tif(!locals) throw new Error('Aborting CSS HMR due to changed css-modules locals.');\n\n\t\tupdate(newContent);\n\t});\n\n\tmodule.hot.dispose(function() { update(); });\n}","import PropTypes from 'prop-types';\nimport React from 'react';\nimport classNames from 'classnames';\n\nimport styles from './input.css';\n\nconst Input = props => {\n const {small, ...componentProps} = props;\n return (\n \n );\n};\n\nInput.propTypes = {\n className: PropTypes.string,\n small: PropTypes.bool\n};\n\nInput.defaultProps = {\n small: false\n};\n\nexport default Input;\n","\nvar content = require(\"!!../../../node_modules/css-loader/index.js??ref--5-1!../../../node_modules/postcss-loader/src/index.js??postcss!./label.css\");\n\nif(typeof content === 'string') content = [[module.id, content, '']];\n\nvar transform;\nvar insertInto;\n\n\n\nvar options = {\"hmr\":true}\n\noptions.transform = transform\noptions.insertInto = undefined;\n\nvar update = require(\"!../../../node_modules/style-loader/lib/addStyles.js\")(content, options);\n\nif(content.locals) module.exports = content.locals;\n\nif(module.hot) {\n\tmodule.hot.accept(\"!!../../../node_modules/css-loader/index.js??ref--5-1!../../../node_modules/postcss-loader/src/index.js??postcss!./label.css\", function() {\n\t\tvar newContent = require(\"!!../../../node_modules/css-loader/index.js??ref--5-1!../../../node_modules/postcss-loader/src/index.js??postcss!./label.css\");\n\n\t\tif(typeof newContent === 'string') newContent = [[module.id, newContent, '']];\n\n\t\tvar locals = (function(a, b) {\n\t\t\tvar key, idx = 0;\n\n\t\t\tfor(key in a) {\n\t\t\t\tif(!b || a[key] !== b[key]) return false;\n\t\t\t\tidx++;\n\t\t\t}\n\n\t\t\tfor(key in b) idx--;\n\n\t\t\treturn idx === 0;\n\t\t}(content.locals, newContent.locals));\n\n\t\tif(!locals) throw new Error('Aborting CSS HMR due to changed css-modules locals.');\n\n\t\tupdate(newContent);\n\t});\n\n\tmodule.hot.dispose(function() { update(); });\n}","import PropTypes from 'prop-types';\nimport React from 'react';\n\nimport styles from './label.css';\n\nconst Label = props => (\n \n);\n\nLabel.propTypes = {\n above: PropTypes.bool,\n children: PropTypes.node,\n secondary: PropTypes.bool,\n text: PropTypes.oneOfType([PropTypes.string, PropTypes.node]).isRequired\n};\n\nLabel.defaultProps = {\n above: false,\n secondary: false\n};\n\nexport default Label;\n","module.exports = \"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxMjgiIGhlaWdodD0iMTI4IiB2aWV3Qm94PSIwIDAgMTYgMTYiPjxwYXRoIGZpbGw9IiMwNTk2NjkiIGQ9Ik00IDEwaDlhLjUuNSAwIDAgMCAuNDA3LS43OUwxMS4xMTQgNmwyLjI5My0zLjIxQS41LjUgMCAwIDAgMTMgMkgzLjVhLjUuNSAwIDAgMC0uNS41djExYS41LjUgMCAwIDAgMSAweiIvPjwvc3ZnPg==\"","\nvar content = require(\"!!../../../node_modules/css-loader/index.js??ref--5-1!../../../node_modules/postcss-loader/src/index.js??postcss!./green-flag.css\");\n\nif(typeof content === 'string') content = [[module.id, content, '']];\n\nvar transform;\nvar insertInto;\n\n\n\nvar options = {\"hmr\":true}\n\noptions.transform = transform\noptions.insertInto = undefined;\n\nvar update = require(\"!../../../node_modules/style-loader/lib/addStyles.js\")(content, options);\n\nif(content.locals) module.exports = content.locals;\n\nif(module.hot) {\n\tmodule.hot.accept(\"!!../../../node_modules/css-loader/index.js??ref--5-1!../../../node_modules/postcss-loader/src/index.js??postcss!./green-flag.css\", function() {\n\t\tvar newContent = require(\"!!../../../node_modules/css-loader/index.js??ref--5-1!../../../node_modules/postcss-loader/src/index.js??postcss!./green-flag.css\");\n\n\t\tif(typeof newContent === 'string') newContent = [[module.id, newContent, '']];\n\n\t\tvar locals = (function(a, b) {\n\t\t\tvar key, idx = 0;\n\n\t\t\tfor(key in a) {\n\t\t\t\tif(!b || a[key] !== b[key]) return false;\n\t\t\t\tidx++;\n\t\t\t}\n\n\t\t\tfor(key in b) idx--;\n\n\t\t\treturn idx === 0;\n\t\t}(content.locals, newContent.locals));\n\n\t\tif(!locals) throw new Error('Aborting CSS HMR due to changed css-modules locals.');\n\n\t\tupdate(newContent);\n\t});\n\n\tmodule.hot.dispose(function() { update(); });\n}","import classNames from 'classnames';\nimport PropTypes from 'prop-types';\nimport React from 'react';\n\nimport greenFlagIcon from './FluentFlag16Filled.svg';\nimport styles from './green-flag.css';\n\nconst GreenFlagComponent = function (props) {\n const {\n active,\n className,\n onClick,\n title,\n ...componentProps\n } = props;\n return (\n \n );\n};\nGreenFlagComponent.propTypes = {\n active: PropTypes.bool,\n className: PropTypes.string,\n onClick: PropTypes.func.isRequired,\n title: PropTypes.string\n};\nGreenFlagComponent.defaultProps = {\n active: false,\n title: 'Go'\n};\nexport default GreenFlagComponent;\n","module.exports = \"data:image/svg+xml;base64,PHN2ZyBpZD0iTGF5ZXJfMSIgZGF0YS1uYW1lPSJMYXllciAxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNi42MyAxNy41Ij48ZGVmcz48c3R5bGU+LmNscy0xLC5jbHMtMntmaWxsOiM0Y2JmNTY7c3Ryb2tlOiM0NTk5M2Q7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kO30uY2xzLTJ7c3Ryb2tlLXdpZHRoOjEuNXB4O308L3N0eWxlPjwvZGVmcz48dGl0bGU+aWNvbi0tZ3JlZW4tZmxhZzwvdGl0bGU+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNLjc1LDJBNi40NCw2LjQ0LDAsMCwxLDguNDQsMmgwYTYuNDQsNi40NCwwLDAsMCw3LjY5LDBWMTIuNGE2LjQ0LDYuNDQsMCwwLDEtNy42OSwwaDBhNi40NCw2LjQ0LDAsMCwwLTcuNjksMCIvPjxsaW5lIGNsYXNzPSJjbHMtMiIgeDE9IjAuNzUiIHkxPSIxNi43NSIgeDI9IjAuNzUiIHkyPSIwLjc1Ii8+PC9zdmc+\"","\nvar content = require(\"!!../../../node_modules/css-loader/index.js??ref--5-1!../../../node_modules/postcss-loader/src/index.js??postcss!./gui.css\");\n\nif(typeof content === 'string') content = [[module.id, content, '']];\n\nvar transform;\nvar insertInto;\n\n\n\nvar options = {\"hmr\":true}\n\noptions.transform = transform\noptions.insertInto = undefined;\n\nvar update = require(\"!../../../node_modules/style-loader/lib/addStyles.js\")(content, options);\n\nif(content.locals) module.exports = content.locals;\n\nif(module.hot) {\n\tmodule.hot.accept(\"!!../../../node_modules/css-loader/index.js??ref--5-1!../../../node_modules/postcss-loader/src/index.js??postcss!./gui.css\", function() {\n\t\tvar newContent = require(\"!!../../../node_modules/css-loader/index.js??ref--5-1!../../../node_modules/postcss-loader/src/index.js??postcss!./gui.css\");\n\n\t\tif(typeof newContent === 'string') newContent = [[module.id, newContent, '']];\n\n\t\tvar locals = (function(a, b) {\n\t\t\tvar key, idx = 0;\n\n\t\t\tfor(key in a) {\n\t\t\t\tif(!b || a[key] !== b[key]) return false;\n\t\t\t\tidx++;\n\t\t\t}\n\n\t\t\tfor(key in b) idx--;\n\n\t\t\treturn idx === 0;\n\t\t}(content.locals, newContent.locals));\n\n\t\tif(!locals) throw new Error('Aborting CSS HMR due to changed css-modules locals.');\n\n\t\tupdate(newContent);\n\t});\n\n\tmodule.hot.dispose(function() { update(); });\n}","import classNames from 'classnames';\nimport omit from 'lodash.omit';\nimport PropTypes from 'prop-types';\nimport React from 'react';\nimport {defineMessages, FormattedMessage, injectIntl, intlShape} from 'react-intl';\nimport {connect} from 'react-redux';\nimport MediaQuery from 'react-responsive';\nimport {Tab, Tabs, TabList, TabPanel} from 'react-tabs';\nimport tabStyles from 'react-tabs/style/react-tabs.css';\nimport VM from 'scratch-vm';\n\nimport Blocks from '../../containers/blocks.jsx';\nimport CostumeTab from '../../containers/costume-tab.jsx';\nimport TargetPane from '../../containers/target-pane.jsx';\nimport SoundTab from '../../containers/sound-tab.jsx';\nimport StageWrapper from '../../containers/stage-wrapper.jsx';\nimport Loader from '../loader/loader.jsx';\nimport Box from '../box/box.jsx';\nimport MenuBar from '../menu-bar/menu-bar.jsx';\nimport CostumeLibrary from '../../containers/costume-library.jsx';\nimport BackdropLibrary from '../../containers/backdrop-library.jsx';\nimport Watermark from '../../containers/watermark.jsx';\n\nimport Backpack from '../../containers/backpack.jsx';\nimport BrowserModal from '../browser-modal/browser-modal.jsx';\nimport TipsLibrary from '../../containers/tips-library.jsx';\nimport Cards from '../../containers/cards.jsx';\nimport Alerts from '../../containers/alerts.jsx';\nimport DragLayer from '../../containers/drag-layer.jsx';\nimport ConnectionModal from '../../containers/connection-modal.jsx';\nimport TelemetryModal from '../telemetry-modal/telemetry-modal.jsx';\nimport TWUsernameModal from '../../containers/tw-username-modal.jsx';\nimport TWSettingsModal from '../../containers/tw-settings-modal.jsx';\nimport TWSecurityManager from '../../containers/tw-security-manager.jsx';\nimport TWCustomExtensionModal from '../../containers/tw-custom-extension-modal.jsx';\nimport TWRestorePointManager from '../../containers/tw-restore-point-manager.jsx';\nimport TWFontsModal from '../../containers/tw-fonts-modal.jsx';\n\nimport {STAGE_SIZE_MODES, FIXED_WIDTH, UNCONSTRAINED_NON_STAGE_WIDTH} from '../../lib/layout-constants';\nimport {resolveStageSize} from '../../lib/screen-utils';\nimport {Theme} from '../../lib/themes';\n\nimport {isRendererSupported, isBrowserSupported} from '../../lib/tw-environment-support-prober';\n\nimport styles from './gui.css';\nimport addExtensionIcon from './icon--extensions.svg';\nimport codeIcon from '!../../lib/tw-recolor/build!./icon--code.svg';\nimport costumesIcon from '!../../lib/tw-recolor/build!./icon--costumes.svg';\nimport soundsIcon from '!../../lib/tw-recolor/build!./icon--sounds.svg';\n\nconst messages = defineMessages({\n addExtension: {\n id: 'gui.gui.addExtension',\n description: 'Button to add an extension in the target pane',\n defaultMessage: 'Add Extension'\n }\n});\n\nconst getFullscreenBackgroundColor = () => {\n const params = new URLSearchParams(location.search);\n if (params.has('fullscreen-background')) {\n return params.get('fullscreen-background');\n }\n if (window.matchMedia('(prefers-color-scheme: dark)').matches) {\n return '#111';\n }\n return 'white';\n};\n\nconst fullscreenBackgroundColor = getFullscreenBackgroundColor();\n\nconst GUIComponent = props => {\n const {\n accountNavOpen,\n activeTabIndex,\n alertsVisible,\n authorId,\n authorThumbnailUrl,\n authorUsername,\n basePath,\n backdropLibraryVisible,\n backpackHost,\n backpackVisible,\n blocksId,\n blocksTabVisible,\n cardsVisible,\n canChangeLanguage,\n canChangeTheme,\n canCreateNew,\n canEditTitle,\n canManageFiles,\n canRemix,\n canSave,\n canCreateCopy,\n canShare,\n canUseCloud,\n children,\n connectionModalVisible,\n costumeLibraryVisible,\n costumesTabVisible,\n customStageSize,\n enableCommunity,\n intl,\n isCreating,\n isEmbedded,\n isFullScreen,\n isPlayerOnly,\n isRtl,\n isShared,\n isWindowFullScreen,\n isTelemetryEnabled,\n isTotallyNormal,\n loading,\n logo,\n renderLogin,\n onClickAbout,\n onClickAccountNav,\n onCloseAccountNav,\n onClickAddonSettings,\n onClickNewWindow,\n onClickPackager,\n onLogOut,\n onOpenRegistration,\n onToggleLoginOpen,\n onActivateCostumesTab,\n onActivateSoundsTab,\n onActivateTab,\n onClickLogo,\n onExtensionButtonClick,\n onOpenCustomExtensionModal,\n onProjectTelemetryEvent,\n onRequestCloseBackdropLibrary,\n onRequestCloseCostumeLibrary,\n onRequestCloseTelemetryModal,\n onSeeCommunity,\n onShare,\n onShowPrivacyPolicy,\n onStartSelectingFileUpload,\n onTelemetryModalCancel,\n onTelemetryModalOptIn,\n onTelemetryModalOptOut,\n securityManager,\n showComingSoon,\n soundsTabVisible,\n stageSizeMode,\n targetIsStage,\n telemetryModalVisible,\n theme,\n tipsLibraryVisible,\n usernameModalVisible,\n settingsModalVisible,\n customExtensionModalVisible,\n fontsModalVisible,\n vm,\n ...componentProps\n } = omit(props, 'dispatch');\n if (children) {\n return {children};\n }\n\n const tabClassNames = {\n tabs: styles.tabs,\n tab: classNames(tabStyles.reactTabsTab, styles.tab),\n tabList: classNames(tabStyles.reactTabsTabList, styles.tabList),\n tabPanel: classNames(tabStyles.reactTabsTabPanel, styles.tabPanel),\n tabPanelSelected: classNames(tabStyles.reactTabsTabPanelSelected, styles.isSelected),\n tabSelected: classNames(tabStyles.reactTabsTabSelected, styles.isSelected)\n };\n\n const unconstrainedWidth = (\n UNCONSTRAINED_NON_STAGE_WIDTH +\n FIXED_WIDTH +\n Math.max(0, customStageSize.width - FIXED_WIDTH)\n );\n return ({isUnconstrained => {\n const stageSize = resolveStageSize(stageSizeMode, isUnconstrained);\n\n const alwaysEnabledModals = (\n \n \n \n {usernameModalVisible && }\n {settingsModalVisible && }\n {customExtensionModalVisible && }\n {fontsModalVisible && }\n \n );\n\n return isPlayerOnly ? (\n \n {/* TW: When the window is fullscreen, use an element to display the background color */}\n {/* The default color for transparency is inconsistent between browsers and there isn't an existing */}\n {/* element for us to style that fills the entire screen. */}\n {isWindowFullScreen ? (\n \n ) : null}\n \n {alertsVisible ? (\n \n ) : null}\n \n {alwaysEnabledModals}\n \n ) : (\n \n {alwaysEnabledModals}\n {telemetryModalVisible ? (\n \n ) : null}\n {loading ? (\n \n ) : null}\n {isCreating ? (\n \n ) : null}\n {isBrowserSupported() ? null : (\n \n )}\n {tipsLibraryVisible ? (\n \n ) : null}\n {cardsVisible ? (\n \n ) : null}\n {alertsVisible ? (\n \n ) : null}\n {connectionModalVisible ? (\n \n ) : null}\n {costumeLibraryVisible ? (\n \n ) : null}\n {backdropLibraryVisible ? (\n \n ) : null}\n \n \n \n \n \n \n \n \n \n \n \n \n {targetIsStage ? (\n \n ) : (\n \n )}\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n {costumesTabVisible ? : null}\n \n \n {soundsTabVisible ? : null}\n \n \n {backpackVisible ? (\n \n ) : null}\n \n\n \n \n \n \n \n \n \n \n \n \n );\n }});\n};\n\nGUIComponent.propTypes = {\n accountNavOpen: PropTypes.bool,\n activeTabIndex: PropTypes.number,\n authorId: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]), // can be false\n authorThumbnailUrl: PropTypes.string,\n authorUsername: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]), // can be false\n backdropLibraryVisible: PropTypes.bool,\n backpackHost: PropTypes.string,\n backpackVisible: PropTypes.bool,\n basePath: PropTypes.string,\n blocksTabVisible: PropTypes.bool,\n blocksId: PropTypes.string,\n canChangeLanguage: PropTypes.bool,\n canChangeTheme: PropTypes.bool,\n canCreateCopy: PropTypes.bool,\n canCreateNew: PropTypes.bool,\n canEditTitle: PropTypes.bool,\n canManageFiles: PropTypes.bool,\n canRemix: PropTypes.bool,\n canSave: PropTypes.bool,\n canShare: PropTypes.bool,\n canUseCloud: PropTypes.bool,\n cardsVisible: PropTypes.bool,\n children: PropTypes.node,\n costumeLibraryVisible: PropTypes.bool,\n costumesTabVisible: PropTypes.bool,\n customStageSize: PropTypes.shape({\n width: PropTypes.number,\n height: PropTypes.number\n }),\n enableCommunity: PropTypes.bool,\n intl: intlShape.isRequired,\n isCreating: PropTypes.bool,\n isEmbedded: PropTypes.bool,\n isFullScreen: PropTypes.bool,\n isPlayerOnly: PropTypes.bool,\n isRtl: PropTypes.bool,\n isShared: PropTypes.bool,\n isWindowFullScreen: PropTypes.bool,\n isTotallyNormal: PropTypes.bool,\n loading: PropTypes.bool,\n logo: PropTypes.string,\n onActivateCostumesTab: PropTypes.func,\n onActivateSoundsTab: PropTypes.func,\n onActivateTab: PropTypes.func,\n onClickAccountNav: PropTypes.func,\n onClickAddonSettings: PropTypes.func,\n onClickNewWindow: PropTypes.func,\n onClickPackager: PropTypes.func,\n onClickLogo: PropTypes.func,\n onCloseAccountNav: PropTypes.func,\n onExtensionButtonClick: PropTypes.func,\n onOpenCustomExtensionModal: PropTypes.func,\n onLogOut: PropTypes.func,\n onOpenRegistration: PropTypes.func,\n onRequestCloseBackdropLibrary: PropTypes.func,\n onRequestCloseCostumeLibrary: PropTypes.func,\n onRequestCloseTelemetryModal: PropTypes.func,\n onSeeCommunity: PropTypes.func,\n onShare: PropTypes.func,\n onShowPrivacyPolicy: PropTypes.func,\n onStartSelectingFileUpload: PropTypes.func,\n onTabSelect: PropTypes.func,\n onTelemetryModalCancel: PropTypes.func,\n onTelemetryModalOptIn: PropTypes.func,\n onTelemetryModalOptOut: PropTypes.func,\n onToggleLoginOpen: PropTypes.func,\n renderLogin: PropTypes.func,\n securityManager: PropTypes.shape({}),\n showComingSoon: PropTypes.bool,\n soundsTabVisible: PropTypes.bool,\n stageSizeMode: PropTypes.oneOf(Object.keys(STAGE_SIZE_MODES)),\n targetIsStage: PropTypes.bool,\n telemetryModalVisible: PropTypes.bool,\n theme: PropTypes.instanceOf(Theme),\n tipsLibraryVisible: PropTypes.bool,\n usernameModalVisible: PropTypes.bool,\n settingsModalVisible: PropTypes.bool,\n customExtensionModalVisible: PropTypes.bool,\n fontsModalVisible: PropTypes.bool,\n vm: PropTypes.instanceOf(VM).isRequired\n};\nGUIComponent.defaultProps = {\n backpackHost: null,\n backpackVisible: false,\n basePath: './',\n blocksId: 'original',\n canChangeLanguage: true,\n canChangeTheme: true,\n canCreateNew: false,\n canEditTitle: false,\n canManageFiles: true,\n canRemix: false,\n canSave: false,\n canCreateCopy: false,\n canShare: false,\n canUseCloud: false,\n enableCommunity: false,\n isCreating: false,\n isShared: false,\n isTotallyNormal: false,\n loading: false,\n showComingSoon: false,\n stageSizeMode: STAGE_SIZE_MODES.large\n};\n\nconst mapStateToProps = state => ({\n customStageSize: state.scratchGui.customStageSize,\n isWindowFullScreen: state.scratchGui.tw.isWindowFullScreen,\n // This is the button's mode, as opposed to the actual current state\n blocksId: state.scratchGui.timeTravel.year.toString(),\n stageSizeMode: state.scratchGui.stageSize.stageSize,\n theme: state.scratchGui.theme.theme\n});\n\nexport default injectIntl(connect(\n mapStateToProps\n)(GUIComponent));\n","module.exports = __webpack_public_path__ + \"static/assets/d259fcbecaa9d2a22d19848daff9d4c6.svg\";","\nvar content = require(\"!!../../../node_modules/css-loader/index.js??ref--5-1!../../../node_modules/postcss-loader/src/index.js??postcss!./icon-button.css\");\n\nif(typeof content === 'string') content = [[module.id, content, '']];\n\nvar transform;\nvar insertInto;\n\n\n\nvar options = {\"hmr\":true}\n\noptions.transform = transform\noptions.insertInto = undefined;\n\nvar update = require(\"!../../../node_modules/style-loader/lib/addStyles.js\")(content, options);\n\nif(content.locals) module.exports = content.locals;\n\nif(module.hot) {\n\tmodule.hot.accept(\"!!../../../node_modules/css-loader/index.js??ref--5-1!../../../node_modules/postcss-loader/src/index.js??postcss!./icon-button.css\", function() {\n\t\tvar newContent = require(\"!!../../../node_modules/css-loader/index.js??ref--5-1!../../../node_modules/postcss-loader/src/index.js??postcss!./icon-button.css\");\n\n\t\tif(typeof newContent === 'string') newContent = [[module.id, newContent, '']];\n\n\t\tvar locals = (function(a, b) {\n\t\t\tvar key, idx = 0;\n\n\t\t\tfor(key in a) {\n\t\t\t\tif(!b || a[key] !== b[key]) return false;\n\t\t\t\tidx++;\n\t\t\t}\n\n\t\t\tfor(key in b) idx--;\n\n\t\t\treturn idx === 0;\n\t\t}(content.locals, newContent.locals));\n\n\t\tif(!locals) throw new Error('Aborting CSS HMR due to changed css-modules locals.');\n\n\t\tupdate(newContent);\n\t});\n\n\tmodule.hot.dispose(function() { update(); });\n}","import PropTypes from 'prop-types';\nimport React from 'react';\nimport classNames from 'classnames';\nimport TWRenderRecoloredImage from '../../lib/tw-recolor/render.jsx';\nimport styles from './icon-button.css';\n\nconst IconButton = ({\n img,\n disabled,\n className,\n title,\n onClick\n}) => (\n \n);\n\nIconButton.propTypes = {\n className: PropTypes.string,\n disabled: PropTypes.bool,\n img: PropTypes.oneOfType([PropTypes.func, PropTypes.string]),\n onClick: PropTypes.func.isRequired,\n title: PropTypes.node.isRequired\n};\n\nexport default IconButton;\n","module.exports = \"data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyB3aWR0aD0iMjBweCIgaGVpZ2h0PSIyMHB4IiB2aWV3Qm94PSIwIDAgMjAgMjAiIHZlcnNpb249IjEuMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayI+CiAgICA8IS0tIEdlbmVyYXRvcjogU2tldGNoIDQ4LjIgKDQ3MzI3KSAtIGh0dHA6Ly93d3cuYm9oZW1pYW5jb2RpbmcuY29tL3NrZXRjaCAtLT4KICAgIDx0aXRsZT5MYW5ndWFnZTwvdGl0bGU+CiAgICA8ZGVzYz5DcmVhdGVkIHdpdGggU2tldGNoLjwvZGVzYz4KICAgIDxkZWZzPjwvZGVmcz4KICAgIDxnIGlkPSJQYWdlLTEiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIxIiBmaWxsPSJub25lIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCI+CiAgICAgICAgPGcgaWQ9Ikxhbmd1YWdlIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMS4yNSI+CiAgICAgICAgICAgIDxnIGlkPSJsYW5ndWFnZSIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMi4wMDAwMDAsIDIuMDAwMDAwKSI+CiAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTUuNjM1Miw4LjExMjk0MTE4IEMxNS42MzUyLDEyLjI2ODIzNTMgMTIuMjY2NzI5NCwxNS42MzU3NjQ3IDguMTEyMzc2NDcsMTUuNjM1NzY0NyBDMy45NTcwODIzNSwxNS42MzU3NjQ3IDAuNTg4NjExNzY1LDEyLjI2ODIzNTMgMC41ODg2MTE3NjUsOC4xMTI5NDExOCBDMC41ODg2MTE3NjUsMy45NTc2NDcwNiAzLjk1NzA4MjM1LDAuNTg5MTc2NDcxIDguMTEyMzc2NDcsMC41ODkxNzY0NzEgQzEyLjI2NjcyOTQsMC41ODkxNzY0NzEgMTUuNjM1MiwzLjk1NzY0NzA2IDE1LjYzNTIsOC4xMTI5NDExOCBaIiBpZD0iU3Ryb2tlLTEiPjwvcGF0aD4KICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik0xMS45ODA4LDguMTE2NjExNzYgQzExLjk4MDgsOS43NDk1NTI5NCAxMS43MTUzODgyLDExLjI2MDE0MTIgMTEuMjU0MjExOCwxMi40OTIxNDEyIEMxMC41NTU4NTg4LDE0LjM5MzMxNzYgOS40MDc2MjM1MywxNS42MzQ3Mjk0IDguMTEwNjgyMzUsMTUuNjM0NzI5NCBDNi44MTM3NDExOCwxNS42MzQ3Mjk0IDUuNjY5MjcwNTksMTQuMzkzMzE3NiA0Ljk2NzE1Mjk0LDEyLjQ5MjE0MTIgQzQuNTEwNjgyMzUsMTEuMjYwMTQxMiA0LjI0NDMyOTQxLDkuNzQ5NTUyOTQgNC4yNDQzMjk0MSw4LjExNjYxMTc2IEM0LjI0NDMyOTQxLDYuNDgyNzI5NDEgNC41MTA2ODIzNSw0Ljk3MzA4MjM1IDQuOTY3MTUyOTQsMy43NDEwODIzNSBDNS42NjkyNzA1OSwxLjgyOTU1Mjk0IDYuODEzNzQxMTgsMC41ODgxNDExNzYgOC4xMTA2ODIzNSwwLjU4ODE0MTE3NiBDOS40MDc2MjM1MywwLjU4ODE0MTE3NiAxMC41NTU4NTg4LDEuODI5NTUyOTQgMTEuMjU0MjExOCwzLjc0MTA4MjM1IEMxMS43MTUzODgyLDQuOTczMDgyMzUgMTEuOTgwOCw2LjQ4MjcyOTQxIDExLjk4MDgsOC4xMTY2MTE3NiBaIiBpZD0iU3Ryb2tlLTMiPjwvcGF0aD4KICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik0wLjk1NTAxMTc2NSwxMC4yODExMjk0IEwxNS4yNjg0MjM1LDEwLjI4MTEyOTQiIGlkPSJTdHJva2UtNSI+PC9wYXRoPgogICAgICAgICAgICAgICAgPHBhdGggZD0iTTAuOTU1MDExNzY1LDUuOTQ2NjM1MjkgTDE1LjI2ODQyMzUsNS45NDY2MzUyOSIgaWQ9IlN0cm9rZS03Ij48L3BhdGg+CiAgICAgICAgICAgICAgICA8cGF0aCBkPSJNOC4xMTIxODgyNCwwLjU5MDAyMzUyOSBMOC4xMTIxODgyNCwxNS42Mzc1NTI5IiBpZD0iU3Ryb2tlLTkiPjwvcGF0aD4KICAgICAgICAgICAgPC9nPgogICAgICAgIDwvZz4KICAgIDwvZz4KPC9zdmc+\"","module.exports = __webpack_public_path__ + \"static/assets/79a644579518611a7b397f85a32cfb85.svg\";","module.exports = __webpack_public_path__ + \"static/assets/d1f6af6170e0178514f35fedc62e5eab.svg\";","module.exports = __webpack_public_path__ + \"static/assets/2501d1b87cf04e00cc3a623fa8b5d95c.svg\";","module.exports = __webpack_public_path__ + \"static/assets/e91530fe8f85b7fdc983b48ab3b9885d.svg\";","module.exports = __webpack_public_path__ + \"static/assets/c14c0c1e852949eff4e6c069772b0015.svg\";","module.exports = __webpack_public_path__ + \"static/assets/32d903cafc72328bd30afce14bfa4c79.svg\";","\nvar content = require(\"!!../../../node_modules/css-loader/index.js??ref--5-1!../../../node_modules/postcss-loader/src/index.js??postcss!./library-item.css\");\n\nif(typeof content === 'string') content = [[module.id, content, '']];\n\nvar transform;\nvar insertInto;\n\n\n\nvar options = {\"hmr\":true}\n\noptions.transform = transform\noptions.insertInto = undefined;\n\nvar update = require(\"!../../../node_modules/style-loader/lib/addStyles.js\")(content, options);\n\nif(content.locals) module.exports = content.locals;\n\nif(module.hot) {\n\tmodule.hot.accept(\"!!../../../node_modules/css-loader/index.js??ref--5-1!../../../node_modules/postcss-loader/src/index.js??postcss!./library-item.css\", function() {\n\t\tvar newContent = require(\"!!../../../node_modules/css-loader/index.js??ref--5-1!../../../node_modules/postcss-loader/src/index.js??postcss!./library-item.css\");\n\n\t\tif(typeof newContent === 'string') newContent = [[module.id, newContent, '']];\n\n\t\tvar locals = (function(a, b) {\n\t\t\tvar key, idx = 0;\n\n\t\t\tfor(key in a) {\n\t\t\t\tif(!b || a[key] !== b[key]) return false;\n\t\t\t\tidx++;\n\t\t\t}\n\n\t\t\tfor(key in b) idx--;\n\n\t\t\treturn idx === 0;\n\t\t}(content.locals, newContent.locals));\n\n\t\tif(!locals) throw new Error('Aborting CSS HMR due to changed css-modules locals.');\n\n\t\tupdate(newContent);\n\t});\n\n\tmodule.hot.dispose(function() { update(); });\n}","import {FormattedMessage, intlShape, defineMessages} from 'react-intl';\nimport PropTypes from 'prop-types';\nimport React from 'react';\n\nimport Box from '../box/box.jsx';\nimport PlayButton from '../../containers/play-button.jsx';\nimport styles from './library-item.css';\nimport classNames from 'classnames';\n\nimport bluetoothIconURL from './bluetooth.svg';\nimport internetConnectionIconURL from './internet-connection.svg';\nimport favoriteInactiveIcon from './favorite-inactive.svg';\nimport favoriteActiveIcon from './favorite-active.svg';\n\nconst messages = defineMessages({\n favorite: {\n defaultMessage: 'Favorite',\n description: 'Alt text of icon in costume, sound, and extension libraries to mark an item as favorite.',\n id: 'tw.favorite'\n },\n unfavorite: {\n defaultMessage: 'Unfavorite',\n description: 'Alt text of icon in costume, sound, and extension libraries to unmark an item as favorite.',\n id: 'tw.unfavorite'\n }\n});\n\n/* eslint-disable react/prefer-stateless-function */\nclass LibraryItemComponent extends React.PureComponent {\n render () {\n const favoriteMessage = this.props.intl.formatMessage(\n this.props.favorite ? messages.unfavorite : messages.favorite\n );\n const favorite = (\n \n );\n\n return this.props.featured ? (\n \n
\n {this.props.disabled ? (\n
\n \n
\n ) : null}\n
\n
\n {this.props.insetIconURL ? (\n
\n
\n
\n ) : null}\n
\n {this.props.name}\n
\n {this.props.description}\n
\n\n {(this.props.docsURI || this.props.samples) && (\n
\n {this.props.docsURI && (\n
\n \n \n )}\n\n {this.props.samples && (\n
\n \n \n )}\n
\n )}\n\n {this.props.credits && this.props.credits.length > 0 && (\n
\n
\n \n {' '}\n {this.props.credits.map((credit, index) => (\n \n {credit}\n {index !== this.props.credits.length - 1 && (\n ', '\n )}\n \n ))}\n
\n
\n )}\n\n {this.props.bluetoothRequired || this.props.internetConnectionRequired || this.props.collaborator ? (\n
\n
\n {this.props.bluetoothRequired || this.props.internetConnectionRequired ? (\n
\n
\n \n
\n
\n {this.props.bluetoothRequired ? (\n
\n ) : null}\n {this.props.internetConnectionRequired ? (\n
\n ) : null}\n
\n
\n ) : null}\n
\n
\n {this.props.collaborator ? (\n
\n
\n \n
\n
\n {this.props.collaborator}\n
\n
\n ) : null}\n
\n
\n ) : null}\n\n {favorite}\n
\n ) : (\n \n {/* Layers of wrapping is to prevent layout thrashing on animation */}\n \n \n \n \n \n {this.props.name}\n {this.props.showPlayButton ? (\n \n ) : null}\n\n {favorite}\n \n );\n }\n}\n/* eslint-enable react/prefer-stateless-function */\n\n\nLibraryItemComponent.propTypes = {\n intl: intlShape,\n bluetoothRequired: PropTypes.bool,\n collaborator: PropTypes.string,\n description: PropTypes.oneOfType([\n PropTypes.string,\n PropTypes.node\n ]),\n disabled: PropTypes.bool,\n extensionId: PropTypes.string,\n featured: PropTypes.bool,\n hidden: PropTypes.bool,\n iconURL: PropTypes.string,\n insetIconURL: PropTypes.string,\n internetConnectionRequired: PropTypes.bool,\n isPlaying: PropTypes.bool,\n name: PropTypes.oneOfType([\n PropTypes.string,\n PropTypes.node\n ]),\n credits: PropTypes.arrayOf(PropTypes.oneOfType([\n PropTypes.string,\n PropTypes.node\n ])),\n docsURI: PropTypes.string,\n samples: PropTypes.arrayOf(PropTypes.shape({\n href: PropTypes.string,\n text: PropTypes.string\n })),\n favorite: PropTypes.bool,\n onFavorite: PropTypes.func,\n onBlur: PropTypes.func.isRequired,\n onClick: PropTypes.func.isRequired,\n onFocus: PropTypes.func.isRequired,\n onKeyPress: PropTypes.func.isRequired,\n onMouseEnter: PropTypes.func.isRequired,\n onMouseLeave: PropTypes.func.isRequired,\n onPlay: PropTypes.func.isRequired,\n onStop: PropTypes.func.isRequired,\n showPlayButton: PropTypes.bool\n};\n\nLibraryItemComponent.defaultProps = {\n disabled: false,\n showPlayButton: false\n};\n\nexport default LibraryItemComponent;\n","\nvar content = require(\"!!../../../node_modules/css-loader/index.js??ref--5-1!../../../node_modules/postcss-loader/src/index.js??postcss!./library.css\");\n\nif(typeof content === 'string') content = [[module.id, content, '']];\n\nvar transform;\nvar insertInto;\n\n\n\nvar options = {\"hmr\":true}\n\noptions.transform = transform\noptions.insertInto = undefined;\n\nvar update = require(\"!../../../node_modules/style-loader/lib/addStyles.js\")(content, options);\n\nif(content.locals) module.exports = content.locals;\n\nif(module.hot) {\n\tmodule.hot.accept(\"!!../../../node_modules/css-loader/index.js??ref--5-1!../../../node_modules/postcss-loader/src/index.js??postcss!./library.css\", function() {\n\t\tvar newContent = require(\"!!../../../node_modules/css-loader/index.js??ref--5-1!../../../node_modules/postcss-loader/src/index.js??postcss!./library.css\");\n\n\t\tif(typeof newContent === 'string') newContent = [[module.id, newContent, '']];\n\n\t\tvar locals = (function(a, b) {\n\t\t\tvar key, idx = 0;\n\n\t\t\tfor(key in a) {\n\t\t\t\tif(!b || a[key] !== b[key]) return false;\n\t\t\t\tidx++;\n\t\t\t}\n\n\t\t\tfor(key in b) idx--;\n\n\t\t\treturn idx === 0;\n\t\t}(content.locals, newContent.locals));\n\n\t\tif(!locals) throw new Error('Aborting CSS HMR due to changed css-modules locals.');\n\n\t\tupdate(newContent);\n\t});\n\n\tmodule.hot.dispose(function() { update(); });\n}","import classNames from 'classnames';\nimport bindAll from 'lodash.bindall';\nimport PropTypes from 'prop-types';\nimport React from 'react';\nimport {defineMessages, injectIntl, intlShape} from 'react-intl';\n\nimport LibraryItem from '../../containers/library-item.jsx';\nimport Modal from '../../containers/modal.jsx';\nimport Divider from '../divider/divider.jsx';\nimport Filter from '../filter/filter.jsx';\nimport TagButton from '../../containers/tag-button.jsx';\nimport Spinner from '../spinner/spinner.jsx';\nimport Separator from '../tw-extension-separator/separator.jsx';\nimport {APP_NAME} from '../../lib/brand.js';\n\nimport styles from './library.css';\n\nconst messages = defineMessages({\n filterPlaceholder: {\n id: 'gui.library.filterPlaceholder',\n defaultMessage: 'Search',\n description: 'Placeholder text for library search field'\n },\n allTag: {\n id: 'gui.library.allTag',\n defaultMessage: 'All',\n description: 'Label for library tag to revert to all items after filtering by tag.'\n }\n});\n\nconst ALL_TAG = {tag: 'all', intlLabel: messages.allTag};\nconst tagListPrefix = [ALL_TAG];\n\nclass LibraryComponent extends React.Component {\n constructor (props) {\n super(props);\n bindAll(this, [\n 'handleClose',\n 'handleFilterChange',\n 'handleFilterClear',\n 'handleMouseEnter',\n 'handleMouseLeave',\n 'handlePlayingEnd',\n 'handleSelect',\n 'handleFavorite',\n 'handleTagClick',\n 'setFilteredDataRef'\n ]);\n const favorites = this.readFavoritesFromStorage();\n this.state = {\n playingItem: null,\n filterQuery: '',\n selectedTag: ALL_TAG.tag,\n canDisplay: false,\n favorites,\n initialFavorites: favorites\n };\n }\n componentDidMount () {\n // Rendering all the items in the library can take a bit, so we'll always\n // show one frame with a loading spinner.\n setTimeout(() => {\n this.setState({\n canDisplay: true\n });\n });\n if (this.props.setStopHandler) this.props.setStopHandler(this.handlePlayingEnd);\n }\n componentDidUpdate (prevProps, prevState) {\n if (prevState.filterQuery !== this.state.filterQuery ||\n prevState.selectedTag !== this.state.selectedTag) {\n this.scrollToTop();\n }\n\n if (this.state.favorites !== prevState.favorites) {\n try {\n localStorage.setItem(this.getFavoriteStorageKey(), JSON.stringify(this.state.favorites));\n } catch (error) {\n // ignore\n }\n }\n }\n handleSelect (id) {\n this.handleClose();\n this.props.onItemSelected(this.getFilteredData()[id]);\n }\n readFavoritesFromStorage () {\n let data;\n try {\n data = JSON.parse(localStorage.getItem(this.getFavoriteStorageKey()));\n } catch (error) {\n // ignore\n }\n if (!Array.isArray(data)) {\n data = [];\n }\n return data;\n }\n getFavoriteStorageKey () {\n return `tw:library-favorites:${this.props.id}`;\n }\n handleFavorite (id) {\n const data = this.getFilteredData()[id];\n const key = data[this.props.persistableKey];\n this.setState(oldState => ({\n favorites: oldState.favorites.includes(key) ? (\n oldState.favorites.filter(i => i !== key)\n ) : (\n [...oldState.favorites, key]\n )\n }));\n }\n handleClose () {\n this.props.onRequestClose();\n }\n handleTagClick (tag) {\n if (this.state.playingItem === null) {\n this.setState({\n filterQuery: '',\n selectedTag: tag.toLowerCase()\n });\n } else {\n this.props.onItemMouseLeave(this.getFilteredData()[[this.state.playingItem]]);\n this.setState({\n filterQuery: '',\n playingItem: null,\n selectedTag: tag.toLowerCase()\n });\n }\n }\n handleMouseEnter (id) {\n // don't restart if mouse over already playing item\n if (this.props.onItemMouseEnter && this.state.playingItem !== id) {\n this.props.onItemMouseEnter(this.getFilteredData()[id]);\n this.setState({\n playingItem: id\n });\n }\n }\n handleMouseLeave (id) {\n if (this.props.onItemMouseLeave) {\n this.props.onItemMouseLeave(this.getFilteredData()[id]);\n this.setState({\n playingItem: null\n });\n }\n }\n handlePlayingEnd () {\n if (this.state.playingItem !== null) {\n this.setState({\n playingItem: null\n });\n }\n }\n handleFilterChange (event) {\n if (this.state.playingItem === null) {\n this.setState({\n filterQuery: event.target.value,\n selectedTag: ALL_TAG.tag\n });\n } else {\n this.props.onItemMouseLeave(this.getFilteredData()[[this.state.playingItem]]);\n this.setState({\n filterQuery: event.target.value,\n playingItem: null,\n selectedTag: ALL_TAG.tag\n });\n }\n }\n handleFilterClear () {\n this.setState({filterQuery: ''});\n }\n getFilteredData () {\n // When no filtering, favorites get their own section\n if (this.state.selectedTag === 'all' && !this.state.filterQuery) {\n const favoriteItems = this.props.data\n .filter(dataItem => (\n this.state.initialFavorites.includes(dataItem[this.props.persistableKey])\n ))\n .map(dataItem => ({\n ...dataItem,\n key: `favorite-${dataItem[this.props.persistableKey]}`\n }));\n\n if (favoriteItems.length) {\n favoriteItems.push('---');\n }\n\n return [\n ...favoriteItems,\n ...this.props.data\n ];\n }\n\n // When filtering, favorites are just listed first, not in a separte section.\n const favoriteItems = [];\n const nonFavoriteItems = [];\n for (const dataItem of this.props.data) {\n if (dataItem === '---') {\n // ignore\n } else if (this.state.initialFavorites.includes(dataItem[this.props.persistableKey])) {\n favoriteItems.push(dataItem);\n } else {\n nonFavoriteItems.push(dataItem);\n }\n }\n\n let filteredItems = favoriteItems.concat(nonFavoriteItems);\n\n if (this.state.selectedTag !== 'all') {\n filteredItems = filteredItems.filter(dataItem => (\n dataItem.tags &&\n dataItem.tags.map(i => i.toLowerCase()).includes(this.state.selectedTag)\n ));\n }\n\n if (this.state.filterQuery) {\n filteredItems = filteredItems.filter(dataItem => {\n const search = [...dataItem.tags];\n if (dataItem.name) {\n // Use the name if it is a string, else use formatMessage to get the translated name\n if (typeof dataItem.name === 'string') {\n search.push(dataItem.name);\n } else {\n search.push(this.props.intl.formatMessage(dataItem.name.props, {APP_NAME}));\n }\n }\n if (dataItem.description) {\n search.push(dataItem.description);\n }\n return search\n .join('\\n')\n .toLowerCase()\n .includes(this.state.filterQuery.toLowerCase());\n });\n }\n\n return filteredItems;\n }\n scrollToTop () {\n this.filteredDataRef.scrollTop = 0;\n }\n setFilteredDataRef (ref) {\n this.filteredDataRef = ref;\n }\n render () {\n return (\n \n {(this.props.filterable || this.props.tags) && (\n \n {this.props.filterable && (\n
\n )}\n {this.props.filterable && this.props.tags && (\n
\n )}\n {this.props.tags &&\n
\n {tagListPrefix.concat(this.props.tags).map((tagProps, id) => (\n \n ))}\n
\n }\n
\n )}\n \n {(this.state.canDisplay && this.props.data) ? this.getFilteredData().map((dataItem, index) => (\n dataItem === '---' ? (\n
\n ) : (\n
\n )\n )) : (\n
\n \n
\n )}\n
\n \n );\n }\n}\n\nLibraryComponent.propTypes = {\n data: PropTypes.oneOfType([\n PropTypes.arrayOf(PropTypes.oneOfType([\n /* eslint-disable react/no-unused-prop-types, lines-around-comment */\n // An item in the library\n PropTypes.shape({\n // @todo remove md5/rawURL prop from library, refactor to use storage\n md5: PropTypes.string,\n name: PropTypes.oneOfType([\n PropTypes.string,\n PropTypes.node\n ]),\n rawURL: PropTypes.string\n }),\n PropTypes.string\n /* eslint-enable react/no-unused-prop-types, lines-around-comment */\n ])),\n PropTypes.instanceOf(Promise)\n ]),\n filterable: PropTypes.bool,\n id: PropTypes.string.isRequired,\n persistableKey: PropTypes.string,\n intl: intlShape.isRequired,\n onItemMouseEnter: PropTypes.func,\n onItemMouseLeave: PropTypes.func,\n onItemSelected: PropTypes.func,\n onRequestClose: PropTypes.func,\n setStopHandler: PropTypes.func,\n showPlayButton: PropTypes.bool,\n tags: PropTypes.arrayOf(PropTypes.shape(TagButton.propTypes)),\n title: PropTypes.string.isRequired\n};\n\nLibraryComponent.defaultProps = {\n filterable: true,\n persistableKey: 'name',\n showPlayButton: false\n};\n\nexport default injectIntl(LibraryComponent);\n","module.exports = __webpack_public_path__ + \"static/assets/7efe82fffae735cd083388badd51b3fa.svg\";","\nvar content = require(\"!!../../../node_modules/css-loader/index.js??ref--5-1!../../../node_modules/postcss-loader/src/index.js??postcss!./loader.css\");\n\nif(typeof content === 'string') content = [[module.id, content, '']];\n\nvar transform;\nvar insertInto;\n\n\n\nvar options = {\"hmr\":true}\n\noptions.transform = transform\noptions.insertInto = undefined;\n\nvar update = require(\"!../../../node_modules/style-loader/lib/addStyles.js\")(content, options);\n\nif(content.locals) module.exports = content.locals;\n\nif(module.hot) {\n\tmodule.hot.accept(\"!!../../../node_modules/css-loader/index.js??ref--5-1!../../../node_modules/postcss-loader/src/index.js??postcss!./loader.css\", function() {\n\t\tvar newContent = require(\"!!../../../node_modules/css-loader/index.js??ref--5-1!../../../node_modules/postcss-loader/src/index.js??postcss!./loader.css\");\n\n\t\tif(typeof newContent === 'string') newContent = [[module.id, newContent, '']];\n\n\t\tvar locals = (function(a, b) {\n\t\t\tvar key, idx = 0;\n\n\t\t\tfor(key in a) {\n\t\t\t\tif(!b || a[key] !== b[key]) return false;\n\t\t\t\tidx++;\n\t\t\t}\n\n\t\t\tfor(key in b) idx--;\n\n\t\t\treturn idx === 0;\n\t\t}(content.locals, newContent.locals));\n\n\t\tif(!locals) throw new Error('Aborting CSS HMR due to changed css-modules locals.');\n\n\t\tupdate(newContent);\n\t});\n\n\tmodule.hot.dispose(function() { update(); });\n}","import React from 'react';\nimport {FormattedMessage, injectIntl, intlShape, defineMessages} from 'react-intl';\nimport {connect} from 'react-redux';\nimport classNames from 'classnames';\nimport PropTypes from 'prop-types';\nimport bindAll from 'lodash.bindall';\nimport styles from './loader.css';\nimport {getIsLoadingWithId} from '../../reducers/project-state';\nimport topBlock from './top-block.svg';\nimport middleBlock from './middle-block.svg';\nimport bottomBlock from './bottom-block.svg';\n\nconst mainMessages = {\n 'gui.loader.headline': (\n \n ),\n 'gui.loader.creating': (\n \n )\n};\n\nconst messages = defineMessages({\n projectData: {\n defaultMessage: 'Loading project …',\n description: 'Appears when loading project data, but not assets yet',\n id: 'tw.loader.projectData'\n },\n downloadingAssets: {\n defaultMessage: 'Downloading assets ({complete}/{total}) …',\n description: 'Appears when loading project assets from a project on a remote website',\n id: 'tw.loader.downloadingAssets'\n },\n loadingAssets: {\n defaultMessage: 'Loading assets ({complete}/{total}) …',\n description: 'Appears when loading project assets from a project file on the user\\'s computer',\n id: 'tw.loader.loadingAssets'\n }\n});\n\n// Because progress events are fired so often during the very performance-critical loading\n// process and React updates are very slow, we bypass React for updating the progress bar.\n\nclass LoaderComponent extends React.Component {\n constructor (props) {\n super(props);\n bindAll(this, [\n 'handleAssetProgress',\n 'handleProjectLoaded',\n 'barInnerRef',\n 'messageRef'\n ]);\n this.barInnerEl = null;\n this.messageEl = null;\n this.ignoreProgress = false;\n }\n componentDidMount () {\n this.handleAssetProgress(\n this.props.vm.runtime.finishedAssetRequests,\n this.props.vm.runtime.totalAssetRequests\n );\n this.props.vm.on('ASSET_PROGRESS', this.handleAssetProgress);\n this.props.vm.runtime.on('PROJECT_LOADED', this.handleProjectLoaded);\n }\n componentWillUnmount () {\n this.props.vm.off('ASSET_PROGRESS', this.handleAssetProgress);\n this.props.vm.runtime.off('PROJECT_LOADED', this.handleProjectLoaded);\n }\n handleAssetProgress (finished, total) {\n if (this.ignoreProgress || !this.barInnerEl || !this.messageEl) {\n return;\n }\n\n if (total === 0) {\n // Started loading a new project.\n this.barInnerEl.style.width = '0';\n this.messageEl.textContent = this.props.intl.formatMessage(messages.projectData);\n } else {\n this.barInnerEl.style.width = `${finished / total * 100}%`;\n const message = this.props.isRemote ? messages.downloadingAssets : messages.loadingAssets\n this.messageEl.textContent = this.props.intl.formatMessage(message, {\n complete: finished,\n total\n });\n }\n }\n handleProjectLoaded () {\n if (this.ignoreProgress || !this.barInnerEl || !this.messageEl) {\n return;\n }\n\n this.ignoreProgress = true;\n this.props.vm.runtime.resetProgress();\n }\n barInnerRef (barInner) {\n this.barInnerEl = barInner;\n }\n messageRef (message) {\n this.messageEl = message;\n }\n render () {\n return (\n \n
\n
\n\n
\n {mainMessages[this.props.messageId]}\n
\n\n
\n\n
\n
\n
\n );\n }\n}\n\nLoaderComponent.propTypes = {\n intl: intlShape,\n isFullScreen: PropTypes.bool,\n isRemote: PropTypes.bool,\n messageId: PropTypes.string,\n vm: PropTypes.shape({\n on: PropTypes.func,\n off: PropTypes.func,\n runtime: PropTypes.shape({\n totalAssetRequests: PropTypes.number,\n finishedAssetRequests: PropTypes.number,\n resetProgress: PropTypes.func,\n on: PropTypes.func,\n off: PropTypes.func\n })\n })\n};\nLoaderComponent.defaultProps = {\n isFullScreen: false,\n messageId: 'gui.loader.headline'\n};\n\nconst mapStateToProps = state => ({\n isRemote: getIsLoadingWithId(state.scratchGui.projectState.loadingState),\n vm: state.scratchGui.vm\n});\n\nconst mapDispatchToProps = () => ({});\n\nexport default connect(\n mapStateToProps,\n mapDispatchToProps\n)(injectIntl(LoaderComponent));\n","module.exports = __webpack_public_path__ + \"static/assets/674db5c2e49df884273ac0f7d221865c.svg\";","module.exports = __webpack_public_path__ + \"static/assets/566d73a090e3d42d5bdfee3d92c79d25.svg\";","\nvar content = require(\"!!../../../node_modules/css-loader/index.js??ref--5-1!../../../node_modules/postcss-loader/src/index.js??postcss!./loupe.css\");\n\nif(typeof content === 'string') content = [[module.id, content, '']];\n\nvar transform;\nvar insertInto;\n\n\n\nvar options = {\"hmr\":true}\n\noptions.transform = transform\noptions.insertInto = undefined;\n\nvar update = require(\"!../../../node_modules/style-loader/lib/addStyles.js\")(content, options);\n\nif(content.locals) module.exports = content.locals;\n\nif(module.hot) {\n\tmodule.hot.accept(\"!!../../../node_modules/css-loader/index.js??ref--5-1!../../../node_modules/postcss-loader/src/index.js??postcss!./loupe.css\", function() {\n\t\tvar newContent = require(\"!!../../../node_modules/css-loader/index.js??ref--5-1!../../../node_modules/postcss-loader/src/index.js??postcss!./loupe.css\");\n\n\t\tif(typeof newContent === 'string') newContent = [[module.id, newContent, '']];\n\n\t\tvar locals = (function(a, b) {\n\t\t\tvar key, idx = 0;\n\n\t\t\tfor(key in a) {\n\t\t\t\tif(!b || a[key] !== b[key]) return false;\n\t\t\t\tidx++;\n\t\t\t}\n\n\t\t\tfor(key in b) idx--;\n\n\t\t\treturn idx === 0;\n\t\t}(content.locals, newContent.locals));\n\n\t\tif(!locals) throw new Error('Aborting CSS HMR due to changed css-modules locals.');\n\n\t\tupdate(newContent);\n\t});\n\n\tmodule.hot.dispose(function() { update(); });\n}","import PropTypes from 'prop-types';\nimport React from 'react';\nimport bindAll from 'lodash.bindall';\n\nimport Box from '../box/box.jsx';\nimport styles from './loupe.css';\n\nconst zoomScale = 3;\n\nclass LoupeComponent extends React.Component {\n constructor (props) {\n super(props);\n bindAll(this, [\n 'setCanvas'\n ]);\n }\n componentDidUpdate () {\n this.draw();\n }\n draw () {\n const boxSize = 6 / zoomScale;\n const boxLineWidth = 1 / zoomScale;\n const colorRingWidth = 15 / zoomScale;\n\n const ctx = this.canvas.getContext('2d');\n const {color, data, width, height} = this.props.colorInfo;\n this.canvas.width = zoomScale * width;\n this.canvas.height = zoomScale * height;\n\n // In order to scale the image data, must draw to a tmp canvas first\n const tmpCanvas = document.createElement('canvas');\n tmpCanvas.width = width;\n tmpCanvas.height = height;\n const tmpCtx = tmpCanvas.getContext('2d');\n const imageData = tmpCtx.createImageData(width, height);\n imageData.data.set(data);\n tmpCtx.putImageData(imageData, 0, 0);\n\n // Scale the loupe canvas and draw the zoomed image\n ctx.save();\n ctx.scale(zoomScale, zoomScale);\n ctx.drawImage(tmpCanvas, 0, 0, width, height);\n\n // Draw an outlined square at the cursor position (cursor is hidden)\n ctx.lineWidth = boxLineWidth;\n ctx.strokeStyle = 'black';\n ctx.fillStyle = `rgba(${color.r}, ${color.g}, ${color.b}, ${color.a})`;\n ctx.beginPath();\n ctx.rect((width / 2) - (boxSize / 2), (height / 2) - (boxSize / 2), boxSize, boxSize);\n ctx.fill();\n ctx.stroke();\n\n // Draw a thick ring around the loupe showing the current color\n ctx.strokeStyle = `rgba(${color.r}, ${color.g}, ${color.b}, ${color.a})`;\n ctx.lineWidth = colorRingWidth;\n ctx.beginPath();\n ctx.moveTo(width, height / 2);\n ctx.arc(width / 2, height / 2, width / 2, 0, 2 * Math.PI);\n ctx.stroke();\n ctx.restore();\n }\n setCanvas (element) {\n this.canvas = element;\n }\n render () {\n const {\n colorInfo,\n ...boxProps\n } = this.props;\n const x = colorInfo.x - ((zoomScale * colorInfo.width) / 2);\n const y = colorInfo.y - ((zoomScale * colorInfo.height) / 2);\n return (\n \n );\n }\n}\n\nLoupeComponent.propTypes = {\n colorInfo: PropTypes.shape({\n color: PropTypes.shape({\n r: PropTypes.number,\n g: PropTypes.number,\n b: PropTypes.number,\n a: PropTypes.number\n }),\n data: PropTypes.instanceOf(Uint8Array),\n width: PropTypes.number,\n height: PropTypes.number,\n x: PropTypes.number,\n y: PropTypes.number\n })\n};\n\nexport default LoupeComponent;\n","module.exports = \"data:image/svg+xml;base64,PCEtLSBodHRwczovL2ZvbnRzLmdvb2dsZS5jb20vaWNvbnM/c2VsZWN0ZWQ9TWF0ZXJpYWwrU3ltYm9scytPdXRsaW5lZDpleHRlbnNpb246RklMTEAxO3dnaHRANDAwO0dSQURAMDtvcHN6QDI0Jmljb24ucXVlcnk9ZXh0ZW5zaW9uIC0tPgo8c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgaGVpZ2h0PSIyMCIgdmlld0JveD0iMCAtOTYwIDk2MCA5NjAiIHdpZHRoPSIyMCI+PHBhdGggZmlsbD0iI2ZmZmZmZiIgZD0iTTM1Mi0xMjBIMjAwcS0zMyAwLTU2LjUtMjMuNVQxMjAtMjAwdi0xNTJxNDggMCA4NC0zMC41dDM2LTc3LjVxMC00Ny0zNi03Ny41VDEyMC01Njh2LTE1MnEwLTMzIDIzLjUtNTYuNVQyMDAtODAwaDE2MHEwLTQyIDI5LTcxdDcxLTI5cTQyIDAgNzEgMjl0MjkgNzFoMTYwcTMzIDAgNTYuNSAyMy41VDgwMC03MjB2MTYwcTQyIDAgNzEgMjl0MjkgNzFxMCA0Mi0yOSA3MXQtNzEgMjl2MTYwcTAgMzMtMjMuNSA1Ni41VDcyMC0xMjBINTY4cTAtNTAtMzEuNS04NVQ0NjAtMjQwcS00NSAwLTc2LjUgMzVUMzUyLTEyMFoiLz48L3N2Zz4=\"","\nvar content = require(\"!!../../../node_modules/css-loader/index.js??ref--5-1!../../../node_modules/postcss-loader/src/index.js??postcss!./author-info.css\");\n\nif(typeof content === 'string') content = [[module.id, content, '']];\n\nvar transform;\nvar insertInto;\n\n\n\nvar options = {\"hmr\":true}\n\noptions.transform = transform\noptions.insertInto = undefined;\n\nvar update = require(\"!../../../node_modules/style-loader/lib/addStyles.js\")(content, options);\n\nif(content.locals) module.exports = content.locals;\n\nif(module.hot) {\n\tmodule.hot.accept(\"!!../../../node_modules/css-loader/index.js??ref--5-1!../../../node_modules/postcss-loader/src/index.js??postcss!./author-info.css\", function() {\n\t\tvar newContent = require(\"!!../../../node_modules/css-loader/index.js??ref--5-1!../../../node_modules/postcss-loader/src/index.js??postcss!./author-info.css\");\n\n\t\tif(typeof newContent === 'string') newContent = [[module.id, newContent, '']];\n\n\t\tvar locals = (function(a, b) {\n\t\t\tvar key, idx = 0;\n\n\t\t\tfor(key in a) {\n\t\t\t\tif(!b || a[key] !== b[key]) return false;\n\t\t\t\tidx++;\n\t\t\t}\n\n\t\t\tfor(key in b) idx--;\n\n\t\t\treturn idx === 0;\n\t\t}(content.locals, newContent.locals));\n\n\t\tif(!locals) throw new Error('Aborting CSS HMR due to changed css-modules locals.');\n\n\t\tupdate(newContent);\n\t});\n\n\tmodule.hot.dispose(function() { update(); });\n}","import PropTypes from 'prop-types';\nimport React from 'react';\nimport classNames from 'classnames';\nimport {FormattedMessage} from 'react-intl';\nimport UserAvatar from './user-avatar.jsx';\n\nimport styles from './author-info.css';\n\nconst ActualAuthorInfo = ({\n className,\n imageUrl,\n projectTitle,\n // TODO: use userId to link to user's profile\n userId, // eslint-disable-line no-unused-vars\n username\n}) => (\n \n
\n
\n
\n {projectTitle}\n
\n
\n \n {username}\n }}\n />\n \n
\n
\n
\n);\n\nActualAuthorInfo.propTypes = {\n className: PropTypes.string,\n imageUrl: PropTypes.string,\n projectTitle: PropTypes.string,\n userId: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]),\n username: PropTypes.oneOfType([PropTypes.string, PropTypes.bool])\n};\n\nconst AuthorInfo = ({projectId, ...props}) => (\n projectId ? (\n \n \n \n ) : \n);\nAuthorInfo.propTypes = {\n projectId: PropTypes.string\n};\n\nexport default AuthorInfo;\n","module.exports = __webpack_public_path__ + \"static/assets/82072226e8cf716289165650c31eeda2.svg\";","module.exports = \"data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTUiIGhlaWdodD0iMTIiIHZpZXdCb3g9IjAgMCAxNSAxMiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik01LjE3MTUgMTEuNDAzQzQuNzQ1MzMgMTEuNDAzIDQuMzE5MTYgMTEuMjM5OCAzLjk5NDUzIDEwLjkxNTJMMC43OTgyNDIgNy43MTg5MkMwLjE0NzMzMSA3LjA2ODAxIDAuMTQ3MzMxIDYuMDE1ODkgMC43OTgyNDIgNS4zNjQ5OEMxLjQ0OTE1IDQuNzE0MDcgMi41MDEyNyA0LjcxNDA3IDMuMTUyMTggNS4zNjQ5OEw1LjE3MTUgNy4zODQzMUwxMS40NjkyIDEuMDg4MjhDMTIuMTE4NCAwLjQzNzM3IDEzLjE3MjIgMC40MzczNyAxMy44MjMxIDEuMDg4MjhDMTQuNDcyNCAxLjczNzUzIDE0LjQ3MjQgMi43OTEzIDEzLjgyMzEgMy40NDIyMkw2LjM0ODQ3IDEwLjkxNTJDNi4wMjM4NCAxMS4yMzk4IDUuNTk3NjcgMTEuNDAzIDUuMTcxNSAxMS40MDNaIiBmaWxsPSJ3aGl0ZSIvPgo8L3N2Zz4K\"","\nvar content = require(\"!!../../../node_modules/css-loader/index.js??ref--5-1!../../../node_modules/postcss-loader/src/index.js??postcss!./community-button.css\");\n\nif(typeof content === 'string') content = [[module.id, content, '']];\n\nvar transform;\nvar insertInto;\n\n\n\nvar options = {\"hmr\":true}\n\noptions.transform = transform\noptions.insertInto = undefined;\n\nvar update = require(\"!../../../node_modules/style-loader/lib/addStyles.js\")(content, options);\n\nif(content.locals) module.exports = content.locals;\n\nif(module.hot) {\n\tmodule.hot.accept(\"!!../../../node_modules/css-loader/index.js??ref--5-1!../../../node_modules/postcss-loader/src/index.js??postcss!./community-button.css\", function() {\n\t\tvar newContent = require(\"!!../../../node_modules/css-loader/index.js??ref--5-1!../../../node_modules/postcss-loader/src/index.js??postcss!./community-button.css\");\n\n\t\tif(typeof newContent === 'string') newContent = [[module.id, newContent, '']];\n\n\t\tvar locals = (function(a, b) {\n\t\t\tvar key, idx = 0;\n\n\t\t\tfor(key in a) {\n\t\t\t\tif(!b || a[key] !== b[key]) return false;\n\t\t\t\tidx++;\n\t\t\t}\n\n\t\t\tfor(key in b) idx--;\n\n\t\t\treturn idx === 0;\n\t\t}(content.locals, newContent.locals));\n\n\t\tif(!locals) throw new Error('Aborting CSS HMR due to changed css-modules locals.');\n\n\t\tupdate(newContent);\n\t});\n\n\tmodule.hot.dispose(function() { update(); });\n}","import classNames from 'classnames';\nimport {FormattedMessage} from 'react-intl';\nimport PropTypes from 'prop-types';\nimport React from 'react';\nimport Button from '../button/button.jsx';\n\nimport communityIcon from './icon--see-community.svg';\nimport styles from './community-button.css';\n\nconst CommunityButton = ({\n className,\n onClick\n}) => (\n \n);\n\nCommunityButton.propTypes = {\n className: PropTypes.string,\n onClick: PropTypes.func\n};\n\nCommunityButton.defaultProps = {\n onClick: () => {}\n};\n\nexport default CommunityButton;\n","module.exports = \"data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyB3aWR0aD0iOHB4IiBoZWlnaHQ9IjVweCIgdmlld0JveD0iMCAwIDggNSIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIj4KICAgIDwhLS0gR2VuZXJhdG9yOiBTa2V0Y2ggNDguMiAoNDczMjcpIC0gaHR0cDovL3d3dy5ib2hlbWlhbmNvZGluZy5jb20vc2tldGNoIC0tPgogICAgPHRpdGxlPmRyb3Bkb3duLWNhcmV0PC90aXRsZT4KICAgIDxkZXNjPkNyZWF0ZWQgd2l0aCBTa2V0Y2guPC9kZXNjPgogICAgPGRlZnM+PC9kZWZzPgogICAgPGcgaWQ9IlBhZ2UtMSIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjEiIGZpbGw9Im5vbmUiIGZpbGwtcnVsZT0iZXZlbm9kZCI+CiAgICAgICAgPGcgaWQ9ImRyb3Bkb3duLWNhcmV0IiBmaWxsPSIjRkZGRkZGIj4KICAgICAgICAgICAgPHBhdGggZD0iTTQsNSBDMy43MjUyMDcwOCw1IDMuNDUxNjMwMDYsNC44OTY5NTA0NSAzLjI0MTI3OTczLDQuNjg5NjUzMTEgTDAuMzE0NjEzNTcyLDEuODA2NjYyMjcgQy0wLjEwNDg3MTE5MSwxLjM5MzI2NTgzIC0wLjEwNDg3MTE5MSwwLjcyNDY0MjAyMyAwLjMxNDYxMzU3MiwwLjMxMDA0NzMzMSBDMC43MzI4ODI0MzgsLTAuMTAzMzQ5MTEgNy4yNjcxMTc1NiwtMC4xMDMzNDkxMSA3LjY4NTM4NjQzLDAuMzEwMDQ3MzMxIEM4LjEwNDg3MTE5LDAuNzIzNDQzNzcyIDguMTA0ODcxMTksMS4zOTMyNjU4MyA3LjY4NTM4NjQzLDEuODA2NjYyMjcgTDQuNzU5OTM2MTcsNC42ODk2NTMxMSBDNC41NDk1ODU4Myw0Ljg5Njk1MDQ1IDQuMjc2MDA4ODIsNSA0LDUiPjwvcGF0aD4KICAgICAgICA8L2c+CiAgICA8L2c+Cjwvc3ZnPg==\"","module.exports = \"data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayI+PGRlZnM+PHBhdGggZD0iTTEwIDJjNC40MTggMCA4IDMuNTgyIDggOHMtMy41ODIgOC04IDgtOC0zLjU4Mi04LTggMy41ODItOCA4LTh6bS0uMDcyIDEwLjQyYy0uMjU2IDAtLjQ3Mi4wNzYtLjY0OC4yMjctLjE3Ni4xNTEtLjI2NC4zMzgtLjI2NC41NiAwIC4yNS4wOTEuNDQ1LjI3My41ODQuMTgyLjEzOS4zOTUuMjA5LjYzOS4yMDkuMjM2IDAgLjQ0NC0uMDcuNjI0LS4yMTFzLjI3LS4zMzUuMjctLjU4MWMwLS4yMjItLjA4Ni0uNDA5LS4yNTgtLjU2LS4xNzItLjE1MS0uMzg0LS4yMjctLjYzNi0uMjI3em0uMTQ0LTYuNDJjLS42MjQgMC0xLjE3LjExMy0xLjYzOC4zMzgtLjQ2OC4yMjUtLjgyNC41MS0xLjA2OC44NTMtLjI0NC4zNDMtLjM2Ni42ODMtLjM2NiAxLjAxNyAwIC4xNjIuMDc3LjMxMy4yMzEuNDUyLjE1NC4xMzkuMzQzLjIwOS41NjcuMjA5LjM4IDAgLjYzOC0uMTk5Ljc3NC0uNTk3LjE0NC0uMzguMzItLjY2OC41MjgtLjg2NC4yMDgtLjE5Ni41MzItLjI5My45NzItLjI5My4zNzYgMCAuNjgzLjA5Ny45MjEuMjkxLjIzOC4xOTQuMzU3LjQzMi4zNTcuNzEzIDAgLjE0NC0uMDM5LjI3OC0uMTE3LjQwMi0uMDc4LjEyMy0uMTc0LjIzNS0uMjg4LjMzNi0uMTE0LjEtLjI5OS4yNDktLjU1NS40NDYtLjI5Mi4yMjUtLjUyNC40Mi0uNjk2LjU4NC0uMTcyLjE2NC0uMzEuMzU0LS40MTQuNTcxLS4xMDQuMjE3LS4xNTYuNDczLS4xNTYuNzY5IDAgLjIzNi4wNzEuNDE0LjIxMy41MzQuMTQyLjEyLjMxNy4xOC41MjUuMTguNCAwIC42MzgtLjE4My43MTQtLjU1bC4wOTktLjM2Mi4wOTMtLjIwNi4xODMtLjIyNy4zMjctLjI4OGMuNDkyLS4zODcuODMzLS42NjMgMS4wMjMtLjgyNy4xOS0uMTY0LjM1NC0uMzU4LjQ5Mi0uNTg0LjEzOC0uMjI1LjIwNy0uNDg4LjIwNy0uNzg3IDAtLjM4LS4xMjEtLjczMy0uMzYzLTEuMDU3LS4yNDItLjMyNC0uNTg1LS41OC0xLjAyOS0uNzY5LS40NDQtLjE4OC0uOTU2LS4yODMtMS41MzYtLjI4M3oiIGlkPSJhIi8+PC9kZWZzPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yIC0yKSIgZmlsbD0ibm9uZSI+PG1hc2s+PHVzZSB4bGluazpocmVmPSIjYSIvPjwvbWFzaz48dXNlIGZpbGw9IiNmZmYiIHhsaW5rOmhyZWY9IiNhIi8+PC9nPjwvc3ZnPg==\"","module.exports = \"data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjEiIGhlaWdodD0iMjAiIHZpZXdCb3g9IjAgMCAyMSAyMCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik05LjY0NDY5IDE0LjUwN0M5LjU1ODYxIDE0LjU5MzEgOS40NjE0NSAxNC42NDg0IDkuMzQ1MjUgMTQuNzAwOEw3LjM3ODczIDE1LjUyNjZDNy4zMDcyOCAxNS4yODMgNy4xMzAzNCAxNC45NzM0IDYuODAzMjkgMTQuNjQ2M0M2LjQ4NzIxIDE0LjMzMDIgNi4xODg1MyAxNC4xNjQzIDUuOTUzNzggMTQuMDgxOUw2Ljc2OTc1IDEyLjEyNTNDNi44MTIxNyAxMS45OTkxIDYuODg4MjggMTEuOTAzMSA2Ljk3MzQ3IDExLjgxNzlDNi45OTMzIDExLjgxOCA3LjAxMjEzIDExLjc5OTIgNy4wMjIgMTEuNzg5M0w3LjA0OTc5IDExLjc2MTVDNy4xODI1MSAxMS42Mjg4IDcuMzY4OTYgMTEuNTQ4IDcuNTg3NDMgMTEuNTE5QzguMTQyNzggMTEuNDUwMiA4Ljc4NjU2IDExLjcxMzggOS4yNzIxNSAxMi4xOTk0QzkuNzU3NzMgMTIuNjg1IDEwLjAyMTMgMTMuMzI4OCA5Ljk0MTU4IDEzLjg3MzFDOS45MDk1NSAxNC4wNTI3IDkuODUwNDEgMTQuMjM3NSA5Ljc1NzU3IDE0LjM3NDJDOS43Mjk4OCAxNC40MjE5IDkuNjkyMjIgMTQuNDU5NSA5LjY1MzY2IDE0LjQ5ODFMOS42NDQ2OSAxNC41MDdaTTEyLjg2ODYgNS45NDI3NEMxMy4xNzUyIDUuNjM2MDYgMTMuNjQ1OCA1LjU3MDM2IDE0LjEyNzQgNS43MTQ4NkMxNC40MDY2IDUuNzk4NTkgMTQuNTIzMiA2LjE0NDcgMTQuMzMyMiA2LjMzNTdMOS43NTE3OSAxMC45MTYxQzkuNjQyMzkgMTEuMDI1NSA5LjQ2NDg4IDExLjA0MzUgOS4zMjEyMiAxMC45NTE4QzkuMTcyNzcgMTAuODU5IDkuMDE5MzQgMTAuNzc5MSA4Ljg2NDczIDEwLjcxMjNDOC42MTI1MiAxMC42MDM2IDguNTI0ODkgMTAuMjg2NCA4LjcwMTU0IDEwLjEwOThMMTIuODY4NiA1Ljk0Mjc0Wk0xNS41Mjg4IDguNjAyOTlMMTEuMzYyNyAxMi43NjkxQzExLjE4OTYgMTIuOTQyMiAxMC44NzEyIDEyLjg2NzcgMTAuNzY1NyAxMi42MjIzQzEwLjY5NzYgMTIuNDU5MSAxMC42MTI3IDEyLjMwMDcgMTAuNTE0OCAxMi4xNDcyQzEwLjQxODEgMTEuOTk2NyAxMC40NDIyIDExLjgwOTEgMTAuNTU2IDExLjY5NTJMMTUuMTI1NyA3LjEyNTZDMTUuMzE0OSA2LjkzNjM5IDE1LjY2MDkgNy4wNTEwNCAxNS43NDY1IDcuMzMwMzZDMTUuODk2IDcuODE3MDEgMTUuODM3MyA4LjI5NDUyIDE1LjUyODggOC42MDI5OVpNMTcuMzQ5NyA0LjEyMTgyQzE2LjE3ODEgMi45NTAyMyAxNC40ODgxIDIuNzM5NzkgMTMuNTc2MiAzLjY1MTc0TDYuMjIwNDQgMTEuMDA3NUM2LjA0MDIgMTEuMTg3NyA1Ljg4MDkgMTEuMzg4OSA1Ljc4NDQxIDExLjYzNDlMNC4yMzMxMiAxNS4zNTk5QzQuMDM4MDQgMTUuODMwMiA0LjE4OTA2IDE2LjQxNyA0LjYyMTggMTYuODQ5N0M1LjA1NDU0IDE3LjI4MjUgNS42NDEzNyAxNy40MzM1IDYuMTExNjUgMTcuMjM4NEw5LjgzNjYxIDE1LjY4NzFDMTAuMDgxNyAxNS41ODk2IDEwLjI4MjggMTUuNDMwMyAxMC40NjMxIDE1LjI1MDFMMTcuODE4OCA3Ljg5NDM4QzE4LjczMDggNi45ODI0MyAxOC41MjEzIDUuMjkzNDEgMTcuMzQ5NyA0LjEyMTgyWiIgZmlsbD0id2hpdGUiLz4KPC9zdmc+Cg==\"","module.exports = \"data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjAiIGhlaWdodD0iMjAiIHZpZXdCb3g9IjAgMCAyMCAyMCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik00Ljk4MTE2IDFIMTUuMDE5NkMxNi40MDQyIDEgMTcuNjE1OCAyLjIxMTU0IDE3LjYxNTggMy41OTYxNVYxMC44NjU0SDEzLjYzNUMxMS4zODUgMTAuODY1NCA5LjY1NDI0IDEyLjc2OTIgOS42NTQyNCAxNC44NDYyVjE4LjgyNjlINC45ODExNkMzLjU5NjU1IDE4LjgyNjkgMi4zODUwMSAxNy42MTU0IDIuMzg1MDEgMTYuMjMwOFYzLjU5NjE1QzIuMzg1MDEgMi4yMTE1NCAzLjU5NjU1IDEgNC45ODExNiAxWk02LjAxOTYzIDkuODI2OTJIOC43ODg4NkM5LjQ4MTE2IDkuODI2OTIgMTAuMDAwNCA5LjQ4MDc3IDEwLjAwMDQgOC43ODg0NkMxMC4wMDA0IDguMDk2MTUgOS40ODExNiA3Ljc1IDguOTYxOTMgNy43NUg2LjAxOTYzQzUuNTAwMzkgNy43NSA0Ljk4MTE2IDguMjY5MjMgNC45ODExNiA4Ljc4ODQ2QzQuOTgxMTYgOS4zMDc2OSA1LjUwMDM5IDkuODI2OTIgNi4wMTk2MyA5LjgyNjkyWk0xNC4xNTQyIDUuODQ2MTVINi4wMTk2M0M1LjMyNzMyIDUuODQ2MTUgNC45ODExNiA1LjMyNjkyIDQuOTgxMTYgNC44MDc2OUM0Ljk4MTE2IDQuMjg4NDYgNS41MDAzOSAzLjc2OTIzIDYuMDE5NjMgMy43NjkyM0gxNC4xNTQyQzE0LjY3MzUgMy43NjkyMyAxNS4xOTI3IDQuMjg4NDYgMTUuMTkyNyA0LjgwNzY5QzE1LjAxOTYgNS4zMjY5MiAxNC42NzM1IDUuODQ2MTUgMTQuMTU0MiA1Ljg0NjE1Wk0xNy40NDI3IDEyLjI1SDEzLjQ2MTlDMTIuMDc3MyAxMi4yNSAxMC44NjU4IDEzLjQ2MTUgMTAuODY1OCAxNS4wMTkyVjE5TDE3LjQ0MjcgMTIuMjVaIiBmaWxsPSJ3aGl0ZSIvPgo8L3N2Zz4K\"","module.exports = \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAoCAYAAAC4h3lxAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyhpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMDY3IDc5LjE1Nzc0NywgMjAxNS8wMy8zMC0yMzo0MDo0MiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTUgKE1hY2ludG9zaCkiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6ODk0NzIwNTI1OTc1MTFFNTk3QzdGRjJDNDczODI4MEIiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6ODk0NzIwNTM1OTc1MTFFNTk3QzdGRjJDNDczODI4MEIiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo4OTQ3MjA1MDU5NzUxMUU1OTdDN0ZGMkM0NzM4MjgwQiIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo4OTQ3MjA1MTU5NzUxMUU1OTdDN0ZGMkM0NzM4MjgwQiIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PhTdRY8AAAImSURBVHja7JlfKENRHMePWYuNSP6UlJWU8iAPipe9KPmTJ09rD5QiJcW7Z3lQPMgTnjyqpSmaPHkgsRISSdZq5IGSWTZd35/dW9exzf5cOlfnV5+1/c7dvb/v2e937u7vMEVRWAY0gUPwrmRvd8Cd4XWypoBefrAKcAScLHeLglZwwQw2yw/jhWAtz+DJisCKer4/FTANug26VgcYN1pAuhTqBT46RucLgR4QyXByvKBZ53sBLeD6NwVUgi6wCMp1/jfgAgdZnL8d7HGpcwz8WcYZA5dgCzx8GdFVtAMsgGiK1WQsx5ViTjHOYmAJlGnn1y5SBQJpvriax1JXDC4VY+0c1GkCKI120xxMwux5rtcuEDdYxD6wUPD9yKQNLueo2HbAGZj/lne5WScYyHEp1eqyhPN7aHbWOWXXoOG37px5UA9OuVi3aSDEOd0CBq/Rx8X6aMXPUM39LHTXXQaNwM7EsFdwBQKcv5xqQGEmNgszuZlegDWF/0Stg7AgcVKdDoK2byNJbhB+YBNwBbICLx9sshSaVf+4iWZxMJNJDdwLnPJhuQpJAVKAFCAFSAFSgBQgBfwzAU+czy5wvHxfKEYCbjjnkMACBrnPQXqk3GSJ3RPNRlmie0bd6WdBAneAYTDB+X3UVqlhiZ5LqcnSn7atmizqExjNutn6Q5PgVv/Q7AERRXyj/YuRVLuUtWAKUMfaCWyCzDbt0ATVep1T33/ahwADAHdtdQ8icCDFAAAAAElFTkSuQmCC\"","module.exports = __webpack_public_path__ + \"static/assets/7808d3b49fdf33cb82e053f00a27ba33.png\";","module.exports = __webpack_public_path__ + \"static/assets/7c67e2601425784a243cd7e0f15c50a3.svg\";","module.exports = __webpack_public_path__ + \"static/assets/b3a6f3783f393f641dc3e51211dd50f4.svg\";","module.exports = \"data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjAiIGhlaWdodD0iMjAiIHZpZXdCb3g9IjAgMCAyMCAyMCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik04LjI3MjA2IDIuNjgzNzdDOC40MDgxOCAyLjI3NTQzIDguNzkwMzIgMiA5LjIyMDc1IDJIMTAuNzc5MkMxMS4yMDk3IDIgMTEuNTkxOCAyLjI3NTQzIDExLjcyNzkgMi42ODM3N0wxMi4zMjE5IDQuNDY1OEMxMi43OTE0IDQuNjYzIDEzLjIzMDQgNC45MTgxOCAxMy42MzAyIDUuMjIyMzhMMTUuNDcyMSA0Ljg0NTQ3QzE1Ljg5MzggNC43NTkxNyAxNi4zMjM0IDQuOTUyNCAxNi41Mzg2IDUuMzI1MTZMMTcuMzE3OCA2LjY3NDg1QzE3LjUzMyA3LjA0NzYxIDE3LjQ4NTYgNy41MTYyNyAxNy4yIDcuODM4MzJMMTUuOTUyOSA5LjI0NDY4QzE1Ljk4NCA5LjQ5MjA4IDE2IDkuNzQ0MTcgMTYgMTBDMTYgMTAuMjU1OCAxNS45ODQgMTAuNTA3OSAxNS45NTI5IDEwLjc1NTNMMTcuMiAxMi4xNjE3QzE3LjQ4NTYgMTIuNDgzNyAxNy41MzMgMTIuOTUyNCAxNy4zMTc4IDEzLjMyNTJMMTYuNTM4NiAxNC42NzQ4QzE2LjMyMzQgMTUuMDQ3NiAxNS44OTM4IDE1LjI0MDggMTUuNDcyMSAxNS4xNTQ1TDEzLjYzMDIgMTQuNzc3NkMxMy4yMzA0IDE1LjA4MTggMTIuNzkxNCAxNS4zMzcgMTIuMzIxOSAxNS41MzQyTDExLjcyNzkgMTcuMzE2MkMxMS41OTE4IDE3LjcyNDYgMTEuMjA5NyAxOCAxMC43NzkyIDE4SDkuMjIwNzVDOC43OTAzMiAxOCA4LjQwODE4IDE3LjcyNDYgOC4yNzIwNiAxNy4zMTYyTDcuNjc4MDUgMTUuNTM0MkM3LjIwODYyIDE1LjMzNyA2Ljc2OTU1IDE1LjA4MTggNi4zNjk4MiAxNC43Nzc2TDQuNTI3OTIgMTUuMTU0NUM0LjEwNjIzIDE1LjI0MDggMy42NzY2MyAxNS4wNDc2IDMuNDYxNDEgMTQuNjc0OEwyLjY4MjE3IDEzLjMyNTJDMi40NjY5NiAxMi45NTI0IDIuNTE0NDIgMTIuNDgzNyAyLjggMTIuMTYxN0w0LjA0NzA4IDEwLjc1NTNDNC4wMTYgMTAuNTA3OSAzLjk5OTk5IDEwLjI1NTggMy45OTk5OSAxMEMzLjk5OTk5IDkuNzQ0MTYgNC4wMTYgOS40OTIwNyA0LjA0NzA3IDkuMjQ0NjZMMi44IDcuODM4MzJDMi41MTQ0MiA3LjUxNjI3IDIuNDY2OTYgNy4wNDc2MSAyLjY4MjE3IDYuNjc0ODVMMy40NjE0MSA1LjMyNTE2QzMuNjc2NjMgNC45NTI0IDQuMTA2MjMgNC43NTkxNyA0LjUyNzkyIDQuODQ1NDdMNi4zNjk4IDUuMjIyMzhDNi43Njk1NCA0LjkxODE4IDcuMjA4NjEgNC42NjMgNy42NzgwNSA0LjQ2NThMOC4yNzIwNiAyLjY4Mzc3Wk05Ljk5OTk5IDhDOC44OTU0MiA4IDcuOTk5OTkgOC44OTU0MyA3Ljk5OTk5IDEwQzcuOTk5OTkgMTEuMTA0NiA4Ljg5NTQyIDEyIDkuOTk5OTkgMTJDMTEuMTA0NiAxMiAxMiAxMS4xMDQ2IDEyIDEwQzEyIDguODk1NDMgMTEuMTA0NiA4IDkuOTk5OTkgOFoiIGZpbGw9IndoaXRlIi8+Cjwvc3ZnPgo=\"","import classNames from 'classnames';\nimport bindAll from 'lodash.bindall';\nimport PropTypes from 'prop-types';\nimport React from 'react';\nimport {FormattedMessage} from 'react-intl';\nimport {connect} from 'react-redux';\nimport locales from '@turbowarp/scratch-l10n';\n\nimport check from './check.svg';\nimport {MenuItem, Submenu} from '../menu/menu.jsx';\nimport languageIcon from '../language-selector/language-icon.svg';\nimport {languageMenuOpen, openLanguageMenu} from '../../reducers/menus.js';\nimport {selectLocale} from '../../reducers/locales.js';\n\nimport styles from './settings-menu.css';\n\nimport dropdownCaret from './dropdown-caret.svg';\n\nclass LanguageMenu extends React.PureComponent {\n constructor (props) {\n super(props);\n bindAll(this, [\n 'setRef',\n 'handleMouseOver'\n ]);\n }\n\n componentDidUpdate (prevProps) {\n // If the submenu has been toggled open, try scrolling the selected option into view.\n if (!prevProps.menuOpen && this.props.menuOpen && this.selectedRef) {\n this.scrollSelectedIntoView();\n }\n }\n\n setRef (component) {\n this.selectedRef = component;\n }\n\n handleMouseOver () {\n // If we are using hover rather than clicks for submenus, scroll the selected option into view\n if (!this.props.menuOpen && this.selectedRef) {\n this.scrollSelectedIntoView();\n }\n }\n\n scrollSelectedIntoView () {\n // the native scrollIntoView() scrolls the entire page when used outside the editor,\n // so we do this manually instead.\n // selectedRef is the checkmark , its parent is a from