diff --git a/src/components/gui/gui.jsx b/src/components/gui/gui.jsx index 360c725b7..bb8585d1a 100644 --- a/src/components/gui/gui.jsx +++ b/src/components/gui/gui.jsx @@ -33,6 +33,7 @@ import TelemetryModal from '../telemetry-modal/telemetry-modal.jsx'; import layout, {STAGE_SIZE_MODES} from '../../lib/layout-constants'; import {resolveStageSize} from '../../lib/screen-utils'; +import {themeMap} from '../../lib/themes'; import styles from './gui.css'; import addExtensionIcon from './icon--extensions.svg'; @@ -308,7 +309,7 @@ const GUIComponent = props => { isVisible={blocksTabVisible} key={theme} options={{ - media: `${basePath}static/blocks-media/` + media: `${basePath}static/${themeMap[theme].blocksMediaFolder}/` }} stageSize={stageSize} theme={theme} diff --git a/src/components/record-modal/record-modal.css b/src/components/record-modal/record-modal.css index 41fc90a96..42f00649a 100644 --- a/src/components/record-modal/record-modal.css +++ b/src/components/record-modal/record-modal.css @@ -106,7 +106,8 @@ text-align: center; } -.record-button { +/* Increase specificity to make sure this wins out over normalize.css */ +svg.record-button { overflow: visible; } diff --git a/src/containers/blocks.jsx b/src/containers/blocks.jsx index ae5e175e7..f890f7984 100644 --- a/src/containers/blocks.jsx +++ b/src/containers/blocks.jsx @@ -19,7 +19,7 @@ import DropAreaHOC from '../lib/drop-area-hoc.jsx'; import DragConstants from '../lib/drag-constants'; import defineDynamicBlock from '../lib/define-dynamic-block'; import {DEFAULT_THEME, getColorsForTheme, themeMap} from '../lib/themes'; -import {injectExtensionBlockColors, injectExtensionCategoryColors} from '../lib/themes/blockHelpers'; +import {injectExtensionBlockTheme, injectExtensionCategoryTheme} from '../lib/themes/blockHelpers'; import {connect} from 'react-redux'; import {updateToolbox} from '../reducers/toolbox'; @@ -349,7 +349,7 @@ class Blocks extends React.Component { const stageCostumes = stage.getCostumes(); const targetCostumes = target.getCostumes(); const targetSounds = target.getSounds(); - const dynamicBlocksXML = injectExtensionCategoryColors( + const dynamicBlocksXML = injectExtensionCategoryTheme( this.props.vm.runtime.getBlocksXML(target), this.props.theme ); @@ -436,7 +436,7 @@ class Blocks extends React.Component { if (blockInfo.info && blockInfo.info.isDynamic) { dynamicBlocksInfo.push(blockInfo); } else if (blockInfo.json) { - staticBlocksJson.push(injectExtensionBlockColors(blockInfo.json, this.props.theme)); + staticBlocksJson.push(injectExtensionBlockTheme(blockInfo.json, this.props.theme)); } // otherwise it's a non-block entry such as '---' }); diff --git a/src/lib/themes/__mocks__/dark-mode.js b/src/lib/themes/__mocks__/dark-mode.js index 793270dd6..b3bcd65fd 100644 --- a/src/lib/themes/__mocks__/dark-mode.js +++ b/src/lib/themes/__mocks__/dark-mode.js @@ -10,4 +10,9 @@ const blockColors = { text: '#BBBBBB' }; -export default blockColors; +const extensions = {}; + +export { + blockColors, + extensions +} diff --git a/src/lib/themes/__mocks__/default-colors.js b/src/lib/themes/__mocks__/default-colors.js index f5e7aa48c..d3b3bc94b 100644 --- a/src/lib/themes/__mocks__/default-colors.js +++ b/src/lib/themes/__mocks__/default-colors.js @@ -13,4 +13,6 @@ const blockColors = { workspace: '#555555' }; -export default blockColors; +export { + blockColors +}; diff --git a/src/lib/themes/blockHelpers.js b/src/lib/themes/blockHelpers.js index baf0cb0f9..72ef02237 100644 --- a/src/lib/themes/blockHelpers.js +++ b/src/lib/themes/blockHelpers.js @@ -1,4 +1,4 @@ -import {DEFAULT_THEME, getColorsForTheme} from '.'; +import {DEFAULT_THEME, getColorsForTheme, themeMap} from '.'; // scratch-blocks colours has a pen property that scratch-gui uses for all extensions const getExtensionColors = theme => getColorsForTheme(theme).pen; @@ -12,11 +12,12 @@ const getExtensionColors = theme => getColorsForTheme(theme).pen; * @param {string} theme - Theme name * @returns {Array.} Dynamic block XML updated with colors. */ -const injectExtensionCategoryColors = (dynamicBlockXML, theme) => { +const injectExtensionCategoryTheme = (dynamicBlockXML, theme) => { // Don't do any manipulation for the default theme if (theme === DEFAULT_THEME) return dynamicBlockXML; const extensionColors = getExtensionColors(theme); + const extensionIcons = themeMap[theme].extensions; const parser = new DOMParser(); const serializer = new XMLSerializer(); @@ -27,6 +28,10 @@ const injectExtensionCategoryColors = (dynamicBlockXML, theme) => { // Note: the category's secondaryColour matches up with the blocks' tertiary color, both used for border color. dom.documentElement.setAttribute('secondaryColour', extensionColors.tertiary); + if (extensionIcons[extension.id] && extensionIcons[extension.id].menuIconURI) { + dom.documentElement.setAttribute('iconURI', extensionIcons[extension.id].menuIconURI); + } + return { ...extension, xml: serializer.serializeToString(dom) @@ -34,6 +39,29 @@ const injectExtensionCategoryColors = (dynamicBlockXML, theme) => { }); }; +const isScratchExtension = blockInfoJson => (blockInfoJson.extensions || []).includes('scratch_extension'); + +const injectBlockIcons = (blockInfoJson, theme) => { + if (!blockInfoJson.args0 || blockInfoJson.args0[0].type !== 'field_image') return blockInfoJson; + + const extensionIcons = themeMap[theme].extensions; + const extension = blockInfoJson.type.substring(0, blockInfoJson.type.indexOf('_')); + + if (!extensionIcons[extension] || !extensionIcons[extension].blockIconURI) return blockInfoJson; + + return { + ...blockInfoJson, + args0: blockInfoJson.args0.map((value, index) => { + if (index !== 0) return value; + + return { + ...value, + src: extensionIcons[extension].blockIconURI + }; + }) + }; +}; + /** * Applies extension color theme to static block json. * No changes are applied if called with the default theme, allowing extensions to provide their own colors. @@ -41,14 +69,14 @@ const injectExtensionCategoryColors = (dynamicBlockXML, theme) => { * @param {string} theme - Theme name * @returns {object} Block info json with updated colors. The original blockInfoJson is not modified. */ -const injectExtensionBlockColors = (blockInfoJson, theme) => { +const injectExtensionBlockTheme = (blockInfoJson, theme) => { // Don't do any manipulation for the default theme if (theme === DEFAULT_THEME) return blockInfoJson; const extensionColors = getExtensionColors(theme); return { - ...blockInfoJson, + ...injectBlockIcons(blockInfoJson, theme), colour: extensionColors.primary, colourSecondary: extensionColors.secondary, colourTertiary: extensionColors.tertiary, @@ -57,6 +85,6 @@ const injectExtensionBlockColors = (blockInfoJson, theme) => { }; export { - injectExtensionBlockColors, - injectExtensionCategoryColors + injectExtensionBlockTheme, + injectExtensionCategoryTheme }; diff --git a/src/lib/themes/dark-mode.js b/src/lib/themes/dark-mode.js index 6842c8b39..d1e865163 100644 --- a/src/lib/themes/dark-mode.js +++ b/src/lib/themes/dark-mode.js @@ -76,4 +76,9 @@ const blockColors = { menuHover: 'rgba(255, 255, 255, 0.3)' }; -export default blockColors; +const extensions = {}; + +export { + blockColors, + extensions +}; diff --git a/src/lib/themes/default-colors.js b/src/lib/themes/default-colors.js index 1b53026c5..3a754dca3 100644 --- a/src/lib/themes/default-colors.js +++ b/src/lib/themes/default-colors.js @@ -100,4 +100,6 @@ const blockColors = { menuHover: 'rgba(0, 0, 0, 0.2)' }; -export default blockColors; +export { + blockColors +}; diff --git a/src/lib/themes/high-contrast.js b/src/lib/themes/high-contrast.js index e8f7c0121..16a09283f 100644 --- a/src/lib/themes/high-contrast.js +++ b/src/lib/themes/high-contrast.js @@ -80,4 +80,30 @@ const blockColors = { menuHover: 'rgba(255, 255, 255, 0.3)' }; -export default blockColors; +const extensions = { + music: { + // eslint-disable-next-line max-len + blockIconURI: 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDAiIGhlaWdodD0iNDAiIHZpZXdCb3g9IjAgMCA0MCA0MCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTI2LjQzMzggMzBDMjkuNTEzIDMwIDMxLjYzNjYgMjguMTU2OSAzMS4xNzkgMjUuODc0QzI4LjI5OTQgMTMuMDQzNiAyNy40MjU2IDkuODUxMzQgMjcuOTQ1NCA5LjYwNTQ3QzI4LjMxMjUgOS40MzE4MyAyOS4zNzQ2IDEwLjcyNzYgMzAuOTE2MiAxMS4xMzU5QzM0LjY0MTYgMTIuMTEyNiA0MC4yNzQyIDYuNDA3NTEgMzQuNTY1NSA3LjI5MTg2QzMyLjMyMjQgNy42MzkgMzAuMTU4NyA2LjIzODM2IDI4LjQ4NzkgNS4xNTY3OUMyNS45MDcyIDMuNDg2MiAyNC41MDI0IDIuNTc2ODQgMjUuNzk3NCAxMC4wNDUxQzI2LjQzNDkgMTMuNzAzNSAyNi45Njk3IDE2LjMyMzEgMjcuMzQ3NSAxOC4xNzM5QzI3Ljk5NTcgMjEuMzQ5NCAyOC4xODE5IDIyLjI2MTYgMjcuNjMyNSAyMi4yNzQxQzI3LjMzMjEgMjIuMTUyIDI3LjAzMjcgMjIuMDU3OCAyNi42OTU3IDIxLjk3MjRDMjYuMDg4IDIxLjgyMjUgMjUuNDUxNiAyMS43MzgyIDI0LjgwNTMgMjEuNzM4MkMyMS43MjcxIDIxLjczODIgMTkuNjAzNiAyMy41ODkyIDIwLjA2MjEgMjUuODc0QzIwLjUxMDcgMjguMTU2OSAyMy4zNjQ2IDMwIDI2LjQzMzggMzBaIiBmaWxsPSJibGFjayIvPgo8cGF0aCBkPSJNOS40Mzg2MSAzNi4wMDAxQzEyLjUwNjUgMzYuMDAwMSAxNC42MzAyIDM0LjE0OCAxNC4xODE3IDMxLjg2NDJDMTEuMzAzMiAxOS4wMzM2IDEwLjQyOTkgMTUuODQxNiAxMC45NDk2IDE1LjU5NThDMTEuMzE2NiAxNS40MjIyIDEyLjM3ODMgMTYuNzE3NyAxMy45MTkgMTcuMTI2QzE3LjY0MjggMTguMTEzNiAyMy4yNzI5IDEyLjM5ODUgMTcuNTY2NyAxMy4yOTE4QzE1LjMyNDggMTMuNjM4NiAxMy4xNjIzIDEyLjIzODIgMTEuNDkyMiAxMS4xNTY5QzguOTEyMzcgOS40ODYzNiA3LjUwNzk3IDguNTc2OTggOC44MDI1MSAxNi4wNDUxQzkuNDQyOTQgMTkuNzI4NiA5Ljk3OTggMjIuMzU5NCAxMC4zNTggMjQuMjEyNUMxMC45OTEyIDI3LjMxNTQgMTEuMTc5NSAyOC4yMzg0IDEwLjY2NDQgMjguMjczMkM5Ljc4NDMyIDI3LjkyNTggOC44MTIzOSAyNy43MjkzIDcuODEwODIgMjcuNzI5M0M0LjczNCAyNy43MjkzIDIuNjExMzQgMjkuNTgwNCAzLjA1OTc4IDMxLjg2NDJDMy41MTgwOSAzNC4xNDggNi4zNzA2OSAzNi4wMDAxIDkuNDM4NjEgMzYuMDAwMVoiIGZpbGw9ImJsYWNrIi8+Cjwvc3ZnPgo=' + }, + pen: { + // eslint-disable-next-line max-len + blockIconURI: 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDAiIGhlaWdodD0iNDAiIHZpZXdCb3g9IjAgMCA0MCA0MCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik04Ljc1MjkgMzQuNjAyNUw0LjUwMTkgMzYuMzgwNUw2LjI4NTkgMzIuMTQ0NUM3LjUwMzkgMjkuMjUzNSA5LjE5MjkgMjYuNzIyNSAxMS4zMTU5IDI0LjYwNzVMMzEuMDY2OSA0LjkyOTVDMzEuOTExOSA0LjA4NzUgMzMuNzE2OSA0LjUyMDUgMzUuMDk3OSA1Ljg5NjVDMzYuNDc4OSA3LjI3MjUgMzYuOTEzOSA5LjA3MDUgMzYuMDY3OSA5LjkxMjVMMTYuMzE3OSAyOS41OTA1QzE0LjE5NDkgMzEuNzA1NSAxMS42NTM5IDMzLjM4ODUgOC43NTI5IDM0LjYwMjVaIiBmaWxsPSJ3aGl0ZSIvPgo8cGF0aCBkPSJNOC43NTI5IDM0LjYwMjVMNC41MDE5IDM2LjM4MDVMNi4yODU5IDMyLjE0NDVDNy41MDM5IDI5LjI1MzUgOS4xOTI5IDI2LjcyMjUgMTEuMzE1OSAyNC42MDc1TDMxLjA2NjkgNC45Mjk1QzMxLjkxMTkgNC4wODc1IDMzLjcxNjkgNC41MjA1IDM1LjA5NzkgNS44OTY1QzM2LjQ3ODkgNy4yNzI1IDM2LjkxMzkgOS4wNzA1IDM2LjA2NzkgOS45MTI1TDE2LjMxNzkgMjkuNTkwNUMxNC4xOTQ5IDMxLjcwNTUgMTEuNjUzOSAzMy4zODg1IDguNzUyOSAzNC42MDI1IiBzdHJva2U9IiMwQjhFNjkiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIvPgo8cGF0aCBkPSJNMjkuNDA5MiA2LjExMTNDMjkuNDA5MiA2LjExMTMgMjQuOTYwMiAzLjczMjMgMjEuMjA4MiAxMS44ODIzQzE5LjQ3NDIgMTUuNjQ4MyAxNi44NTgyIDEzLjQyODMgMTYuODU4MiAxMy40MjgzIiBzdHJva2U9IiMwQjhFNjkiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIvPgo8cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTM2LjQyMDkgOC44MjUxQzM2LjQyMDkgOS4yODgxIDM2LjI3OTkgOS42OTgxIDM1Ljk4NzkgOS45ODkxTDI2LjY1MjkgMTkuMjkwMUMyNi45MzQ5IDE4Ljk5OTEgMjcuMDYzOSAxOC42MjIxIDI3LjA2MzkgMTguMTY5MUMyNy4wNjM5IDE3LjI5NjEgMjYuNTU1OSAxNi4yMDcxIDI1LjY1NjkgMTUuMzAyMUMyNC4yOTQ5IDEzLjk0NDEgMjIuNTA5OSAxMy41MDIxIDIxLjY1NDkgMTQuMzExMUwzMC45ODk5IDUuMDEwMUMzMS44MzM5IDQuMTY5MSAzMy42NDA5IDQuNjAwMSAzNS4wMjQ5IDUuOTY5MUMzNS45MjI5IDYuODc0MSAzNi40MjA5IDcuOTUyMSAzNi40MjA5IDguODI1MVoiIGZpbGw9IiM0Qzk3RkYiLz4KPHBhdGggZD0iTTM2LjQyMDkgOC44MjUxQzM2LjQyMDkgOS4yODgxIDM2LjI3OTkgOS42OTgxIDM1Ljk4NzkgOS45ODkxTDI2LjY1MjkgMTkuMjkwMUMyNi45MzQ5IDE4Ljk5OTEgMjcuMDYzOSAxOC42MjIxIDI3LjA2MzkgMTguMTY5MUMyNy4wNjM5IDE3LjI5NjEgMjYuNTU1OSAxNi4yMDcxIDI1LjY1NjkgMTUuMzAyMUMyNC4yOTQ5IDEzLjk0NDEgMjIuNTA5OSAxMy41MDIxIDIxLjY1NDkgMTQuMzExMUwzMC45ODk5IDUuMDEwMUMzMS44MzM5IDQuMTY5MSAzMy42NDA5IDQuNjAwMSAzNS4wMjQ5IDUuOTY5MUMzNS45MjI5IDYuODc0MSAzNi40MjA5IDcuOTUyMSAzNi40MjA5IDguODI1MSIgc3Ryb2tlPSIjMEI4RTY5IiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiLz4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0xMC41MTQ2IDMzLjc3MzlDOS45NDE2IDM0LjA3NTkgOS4zNTc2IDM0LjM0NDkgOC43NTA2IDM0LjYwMzlMNC40OTk2IDM2LjM4MTlMNi4yODU2IDMyLjE0NjlDNi41NDM2IDMxLjU0MjkgNi44MTQ2IDMwLjk2MDkgNy4xMTg2IDMwLjM4OTlDNy44MDk2IDMwLjU3MjkgOC41Njc2IDMxLjAxNDkgOS4yMjc2IDMxLjY3MTlDOS44ODY2IDMyLjMyOTkgMTAuMzI5NiAzMy4wODM5IDEwLjUxNDYgMzMuNzczOVoiIGZpbGw9IiM0Qzk3RkYiLz4KPHBhdGggZD0iTTEwLjUxNDYgMzMuNzczOUM5Ljk0MTYgMzQuMDc1OSA5LjM1NzYgMzQuMzQ0OSA4Ljc1MDYgMzQuNjAzOUw0LjQ5OTYgMzYuMzgxOUw2LjI4NTYgMzIuMTQ2OUM2LjU0MzYgMzEuNTQyOSA2LjgxNDYgMzAuOTYwOSA3LjExODYgMzAuMzg5OUM3LjgwOTYgMzAuNTcyOSA4LjU2NzYgMzEuMDE0OSA5LjIyNzYgMzEuNjcxOUM5Ljg4NjYgMzIuMzI5OSAxMC4zMjk2IDMzLjA4MzkgMTAuNTE0NiAzMy43NzM5IiBzdHJva2U9IiMwQjhFNjkiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIvPgo8ZyBvcGFjaXR5PSIwLjE1Ij4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0zNi40OTggOC43NDg1QzM2LjQ5OCA5LjIxMTUgMzYuMzU3IDkuNjIxNSAzNi4wNjUgOS45MTI1TDE2LjMyMyAyOS41OTI1QzE0LjE5MiAzMS43MDQ1IDExLjY1IDMzLjM4NTUgOC43NTEgMzQuNjAzNUw0LjUgMzYuMzgxNUw1LjQ3NCAzNC4wNjQ1TDcuMzk5IDMzLjI1NjVDMTAuMjk4IDMyLjAzODUgMTIuODQgMzAuMzU3NSAxNC45NzEgMjguMjQ1NUwzNC43MTMgOC41NjU1QzM1LjAwNSA4LjI3NDUgMzUuMTQ1IDcuODY0NSAzNS4xNDUgNy40MDE1QzM1LjE0NSA2Ljc1NDUgMzQuODc1IDYuMDAwNSAzNC4zNjYgNS4yNzg1QzM0LjYxNSA1LjQ1MDUgMzQuODY0IDUuNjU1NSAzNS4xMDIgNS44OTI1QzM2IDYuNzk3NSAzNi40OTggNy44NzU1IDM2LjQ5OCA4Ljc0ODVaIiBmaWxsPSIjMEI4RTY5Ii8+CjxwYXRoIGQ9Ik0zNi40OTggOC43NDg1QzM2LjQ5OCA5LjIxMTUgMzYuMzU3IDkuNjIxNSAzNi4wNjUgOS45MTI1TDE2LjMyMyAyOS41OTI1QzE0LjE5MiAzMS43MDQ1IDExLjY1IDMzLjM4NTUgOC43NTEgMzQuNjAzNUw0LjUgMzYuMzgxNUw1LjQ3NCAzNC4wNjQ1TDcuMzk5IDMzLjI1NjVDMTAuMjk4IDMyLjAzODUgMTIuODQgMzAuMzU3NSAxNC45NzEgMjguMjQ1NUwzNC43MTMgOC41NjU1QzM1LjAwNSA4LjI3NDUgMzUuMTQ1IDcuODY0NSAzNS4xNDUgNy40MDE1QzM1LjE0NSA2Ljc1NDUgMzQuODc1IDYuMDAwNSAzNC4zNjYgNS4yNzg1QzM0LjYxNSA1LjQ1MDUgMzQuODY0IDUuNjU1NSAzNS4xMDIgNS44OTI1QzM2IDYuNzk3NSAzNi40OTggNy44NzU1IDM2LjQ5OCA4Ljc0ODUiIHN0cm9rZT0iIzBCOEU2OSIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIi8+CjwvZz4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0xOC40NTAyIDEyLjgzMUMxOC40NTAyIDEzLjMzIDE4LjA0NjIgMTMuNzM1IDE3LjU0NjIgMTMuNzM1QzE3LjA0NzIgMTMuNzM1IDE2LjY0MTIgMTMuMzMgMTYuNjQxMiAxMi44MzFDMTYuNjQxMiAxMi4zMzEgMTcuMDQ3MiAxMS45MjcgMTcuNTQ2MiAxMS45MjdDMTguMDQ2MiAxMS45MjcgMTguNDUwMiAxMi4zMzEgMTguNDUwMiAxMi44MzFaIiBmaWxsPSIjMEI4RTY5IiBzdHJva2U9IiMwQjhFNjkiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIvPgo8L3N2Zz4K' + }, + text2speech: { + // eslint-disable-next-line max-len + blockIconURI: 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDAiIGhlaWdodD0iNDAiIHZpZXdCb3g9IjAgMCA0MCA0MCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTE2IDIxLjY2OTNWMzQuMjgzNEMxNiAzNS44MTUxIDE0IDM2LjUzNTkgMTIuOCAzNS41NDQ4TDEwLjIgMzMuMzgyNEM5LjIgMzIuNTcxNSA4IDMyLjIxMTEgNi43IDMyLjIxMTFINi4zQzUgMzIuMjExMSA0IDMxLjMxMDEgNCAzMC4xMzg4VjI1LjkwNDFDNCAyNC43MzI4IDUgMjMuODMxOCA2LjMgMjMuODMxOEg2LjdDOCAyMy44MzE4IDkuMiAyMy4zODEzIDEwLjEgMjIuNjYwNEwxMi44IDIwLjQ5OEMxNCAxOS40MTY4IDE2IDIwLjIyNzcgMTYgMjEuNjY5M1oiIGZpbGw9ImJsYWNrIi8+CjxwYXRoIGQ9Ik0yNCA0QzE5LjU4MTcgNCAxNiA3LjU4MTcyIDE2IDEyQzE2IDE1LjExNDcgMTcuNzc5OSAxNy44MTM2IDIwLjM3ODEgMTkuMTM1MUMyMC4yMDk1IDIwLjkwODcgMTkuNjU2NCAyMS42NjU1IDE5LjMwNDIgMjIuMTQ3M0MxOS4xMjY1IDIyLjM5MDQgMTkgMjIuNTYzNSAxOSAyMi43NjE5QzE5IDIzLjQyODYgMTkuNjY2NyAyMy40Mjg2IDE5LjY2NjcgMjMuNDI4NkMyMC42MTMyIDIzLjQyODYgMjMuNTgxMyAyMi4yNjIzIDI1LjQwOTcgMjBIMjhDMzIuNDE4MyAyMCAzNiAxNi40MTgzIDM2IDEyQzM2IDcuNTgxNzIgMzIuNDE4MyA0IDI4IDRIMjRaIiBmaWxsPSJ3aGl0ZSIgc3Ryb2tlPSIjMEI4RTY5Ii8+Cjwvc3ZnPgo=' + }, + translate: { + // eslint-disable-next-line max-len + blockIconURI: 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDAiIGhlaWdodD0iNDAiIHZpZXdCb3g9IjAgMCA0MCA0MCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTggNUM1Ljc5MDg2IDUgNCA2Ljc5MDg2IDQgOVYxN0M0IDE5LjIwOTEgNS43OTA4NiAyMSA4IDIxSDguMjUyNzdDOC4wMTY0OCAyMi4xNzI4IDcuNTkyODMgMjIuNzUyNCA3LjMwNDIzIDIzLjE0NzNDNy4xMjY1MSAyMy4zOTA0IDcgMjMuNTYzNSA3IDIzLjc2MTlDNyAyNC40Mjg2IDcuNjY2NjcgMjQuNDI4NiA3LjY2NjY3IDI0LjQyODZDOC42MTMyNCAyNC40Mjg2IDExLjU4MTMgMjMuMjYyMyAxMy40MDk3IDIxSDIwQzIyLjIwOTEgMjEgMjQgMTkuMjA5MSAyNCAxN1Y5QzI0IDYuNzkwODYgMjIuMjA5MSA1IDIwIDVIOFoiIGZpbGw9IndoaXRlIiBzdHJva2U9IiMwQjhFNjkiLz4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0xMy40MjE4IDcuOTEzMDJDMTMuNTUyMSA3LjgwMTUzIDEzLjcyMzkgNy43NSAxMy45MDY3IDcuNzVDMTQuMDkyOCA3Ljc1IDE0LjI2NyA3LjgwMDM2IDE0LjM5OTQgNy45MTE1QzE0LjUzNTQgOC4wMjU2MSAxNC42MDY3IDguMTg3NDggMTQuNjA2NyA4LjM2MjE2VjkuNTI4NDFIMTguNzAzNkMxOC44Nzk5IDkuNTI4NDEgMTkuMDI3MiA5LjYxMDE3IDE5LjEyMjkgOS43Mzk1N0MxOS4yMTM0IDkuODYyMDEgMTkuMjUgMTAuMDE0NiAxOS4yNSAxMC4xNjI2QzE5LjI1IDEwLjMxMzYgMTkuMjE0NyAxMC40NzAyIDE5LjEyOTMgMTAuNTk3MUMxOS4wMzk1IDEwLjczMDYgMTguODkyNyAxMC44Mjk3IDE4LjcwMzYgMTAuODI5N0gxNy4xMDEyQzE2LjY2MDggMTIuMjgwMiAxNS45NDgyIDEzLjYzODEgMTQuOTI3IDE0Ljc4MTlDMTUuMDYwNiAxNC44OTE2IDE1LjE4OSAxNC45OTIxIDE1LjMyMTMgMTUuMDgyNkwxNS4zMjc5IDE1LjA4NzFDMTYuMzIxOSAxNS44MTQgMTcuNTQ3MiAxNi4zODUgMTguNzM1MSAxNi43NjI5QzE5LjAzOTUgMTYuODU5IDE5LjIyODIgMTcuMTAzNiAxOS4yMjgyIDE3LjQwNzNDMTkuMjI4MiAxNy40OTM2IDE5LjIxMTIgMTcuNTc3IDE5LjE4MDYgMTcuNjU2MUMxOS4xMzIgMTcuODA1NSAxOS4wNTU1IDE3LjkzNDUgMTguOTQyOCAxOC4wMjY1QzE4LjgyNTEgMTguMTIyNiAxOC42ODc0IDE4LjE2MjQgMTguNTUgMTguMTYyNEMxOC40NDgxIDE4LjE2MjQgMTguMzQyNyAxOC4xNDc3IDE4LjIyNiAxOC4xMDQ3QzE2Ljc5OTcgMTcuNjM1OSAxNS41Nzc3IDE3LjAyMDEgMTQuNDMzIDE2LjEyMjVMMTQuNDMwOSAxNi4xMjA4QzE0LjQxNDIgMTYuMTA3NCAxNC4zOTc1IDE2LjA5NDEgMTQuMzgwOSAxNi4wODA3QzE0LjIzOTEgMTUuOTY3MyAxNC4wOTc1IDE1Ljg1MzggMTMuOTU5MiAxNS43MzM1QzEzLjgwNTUgMTUuODY1NyAxMy42NTIyIDE1Ljk4OTggMTMuNDg2NyAxNi4xMTQxQzEyLjI3NzIgMTcuMDMyMyAxMS4xMjMgMTcuNjAyNyA5Ljc0NTUgMTguMTEzOUw5LjczODE3IDE4LjExNjZDOS42NDc4MSAxOC4xNDcgOS41NTQ4NiAxOC4xNjI0IDkuNDYxMTIgMTguMTYyNEM5LjMxOTgyIDE4LjE2MjQgOS4xNzk5MSAxOC4xMjY3IDkuMDU4NTggMTguMDQyQzguOTM4MDggMTcuOTU3OSA4Ljg1MjUxIDE3LjgzNzIgOC43OTk0NyAxNy42OTQ1QzguNzY3MjYgMTcuNjEzIDguNzUgMTcuNTI3OCA4Ljc1IDE3LjQ0MDJDOC43NSAxNy4xMjA3IDguOTc2NDEgMTYuODkyMSA5LjIzODg0IDE2Ljc5MDNMOS4yNDk0OSAxNi43ODYyQzEwLjQ2NzkgMTYuMzc2NSAxMS42MTQgMTUuODUxNSAxMi44Nzk3IDE0Ljg2NkMxMi45MTQ5IDE0LjgzNSAxMi45NTA5IDE0LjgwNTUgMTIuOTg1NCAxNC43Nzc5QzExLjk4NDUgMTMuNjMzNyAxMS4yODM0IDEyLjI2ODkgMTAuODQ0MiAxMC44Mjk3SDkuMzA3NUM5LjExNjIyIDEwLjgyOTcgOC45NjY4NyAxMC43MzM2IDguODc1ODMgMTAuNTk0NkM4Ljc5MTQ0IDEwLjQ2NTcgOC43NjA4OCAxMC4zMDg3IDguNzYwODggMTAuMTYyNkM4Ljc2MDg4IDEwLjAxOTkgOC43OTIzNSA5Ljg2Njc0IDguODgyMSA5Ljc0MjEyQzguOTc5MDYgOS42MDc0OCA5LjEyOTEgOS41Mjg0MSA5LjMwNzUgOS41Mjg0MUgxMy4yMTc5VjguMzYyMTZDMTMuMjE3OSA4LjE4ODA1IDEzLjI4ODYgOC4wMjcgMTMuNDIxOCA3LjkxMzAyWk0xMi4yMzg2IDEwLjgyOTdDMTIuNjA5MSAxMS45MzE2IDEzLjIwNTYgMTIuOTU4OCAxMy45NjI2IDEzLjgzNzdDMTQuNzI1NyAxMi45NTkzIDE1LjMwNTEgMTEuOTM4OSAxNS42NDkzIDEwLjgyOTdIMTIuMjM4NloiIGZpbGw9IiM0Qzk3RkYiLz4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0zMiAxNkMzNC4yMDkxIDE2IDM2IDE3Ljc5MDkgMzYgMjBWMjhDMzYgMzAuMjA5MSAzNC4yMDkxIDMyIDMyIDMySDMxLjc0NzJDMzEuOTgzNSAzMy4xNzI4IDMyLjQwNzIgMzMuNzUyNCAzMi42OTU4IDM0LjE0NzNDMzIuODczNSAzNC4zOTA0IDMzIDM0LjU2MzUgMzMgMzQuNzYxOUMzMyAzNS40Mjg2IDMyLjMzMzMgMzUuNDI4NiAzMi4zMzMzIDM1LjQyODZDMzEuMzg2OCAzNS40Mjg2IDI4LjQxODcgMzQuMjYyMyAyNi41OTAzIDMySDIwQzE3Ljc5MDkgMzIgMTYgMzAuMjA5MSAxNiAyOFYyMEMxNiAxNy43OTA5IDE3Ljc5MDkgMTYgMjAgMTZIMzJaIiBmaWxsPSJ3aGl0ZSIvPgo8cGF0aCBkPSJNMzEuNzQ3MiAzMkwzMS4yNTcxIDMyLjA5ODhMMzEuMTM2NCAzMS41SDMxLjc0NzJWMzJaTTMyLjY5NTggMzQuMTQ3M0wzMy4wOTk0IDMzLjg1MjJIMzMuMDk5NEwzMi42OTU4IDM0LjE0NzNaTTI2LjU5MDMgMzJWMzEuNUgyNi44MjkxTDI2Ljk3OTIgMzEuNjg1N0wyNi41OTAzIDMyWk0zNS41IDIwQzM1LjUgMTguMDY3IDMzLjkzMyAxNi41IDMyIDE2LjVWMTUuNUMzNC40ODUzIDE1LjUgMzYuNSAxNy41MTQ3IDM2LjUgMjBIMzUuNVpNMzUuNSAyOFYyMEgzNi41VjI4SDM1LjVaTTMyIDMxLjVDMzMuOTMzIDMxLjUgMzUuNSAyOS45MzMgMzUuNSAyOEgzNi41QzM2LjUgMzAuNDg1MyAzNC40ODUzIDMyLjUgMzIgMzIuNVYzMS41Wk0zMS43NDcyIDMxLjVIMzJWMzIuNUgzMS43NDcyVjMxLjVaTTMyLjI5MjEgMzQuNDQyM0MzMS45ODM4IDM0LjAyMDYgMzEuNTEzOCAzMy4zNzI3IDMxLjI1NzEgMzIuMDk4OEwzMi4yMzc0IDMxLjkwMTJDMzIuNDUzMyAzMi45NzI5IDMyLjgzMDUgMzMuNDg0MyAzMy4wOTk0IDMzLjg1MjJMMzIuMjkyMSAzNC40NDIzWk0zMi41IDM0Ljc2MTlDMzIuNSAzNC43NzU1IDMyLjUwNjEgMzQuNzY2NiAzMi40NzU4IDM0LjcxMTNDMzIuNDQxIDM0LjY0NzUgMzIuMzg2OSAzNC41NzIxIDMyLjI5MjEgMzQuNDQyM0wzMy4wOTk0IDMzLjg1MjJDMzMuMTgyMyAzMy45NjU2IDMzLjI4MDQgMzQuMDk4MyAzMy4zNTMyIDM0LjIzMTVDMzMuNDMwNyAzNC4zNzMxIDMzLjUgMzQuNTUgMzMuNSAzNC43NjE5SDMyLjVaTTMyLjMzMzMgMzUuNDI4NkMzMi4zMzMzIDM0LjkyODYgMzIuMzMzMSAzNC45Mjg2IDMyLjMzMjkgMzQuOTI4NkMzMi4zMzI4IDM0LjkyODYgMzIuMzMyNSAzNC45Mjg2IDMyLjMzMjQgMzQuOTI4NkMzMi4zMzIxIDM0LjkyODYgMzIuMzMxOCAzNC45Mjg2IDMyLjMzMTUgMzQuOTI4NkMzMi4zMzA5IDM0LjkyODYgMzIuMzMwNCAzNC45Mjg2IDMyLjMyOTggMzQuOTI4NkMzMi4zMjg4IDM0LjkyODYgMzIuMzI3OSAzNC45Mjg2IDMyLjMyNzIgMzQuOTI4NkMzMi4zMjU3IDM0LjkyODYgMzIuMzI0NyAzNC45Mjg3IDMyLjMyNDIgMzQuOTI4N0MzMi4zMjMxIDM0LjkyODcgMzIuMzI0IDM0LjkyODcgMzIuMzI2NCAzNC45Mjg1QzMyLjMzMTMgMzQuOTI4MiAzMi4zNDE2IDM0LjkyNzIgMzIuMzU1MyAzNC45MjVDMzIuMzg1MSAzNC45MiAzMi40MTcxIDM0LjkxMSAzMi40NDMxIDM0Ljg5OEMzMi40NjcxIDM0Ljg4NiAzMi40NzU5IDM0Ljg3NTkgMzIuNDc5OCAzNC44N0MzMi40ODE2IDM0Ljg2NzIgMzIuNSAzNC44NDExIDMyLjUgMzQuNzYxOUgzMy41QzMzLjUgMzUuMDE2MSAzMy40MzUgMzUuMjM5OSAzMy4zMTE5IDM1LjQyNDdDMzMuMTkwOCAzNS42MDYzIDMzLjAzMjkgMzUuNzIxMSAzMi44OTAzIDM1Ljc5MjVDMzIuNzQ5NiAzNS44NjI4IDMyLjYxNDkgMzUuODk1NSAzMi41MTk3IDM1LjkxMTRDMzIuNDcwOSAzNS45MTk1IDMyLjQyOTEgMzUuOTIzNyAzMi4zOTc2IDM1LjkyNkMzMi4zODE4IDM1LjkyNzEgMzIuMzY4MyAzNS45Mjc4IDMyLjM1NzUgMzUuOTI4MUMzMi4zNTIxIDM1LjkyODMgMzIuMzQ3MyAzNS45Mjg0IDMyLjM0MzMgMzUuOTI4NUMzMi4zNDEzIDM1LjkyODUgMzIuMzM5NCAzNS45Mjg1IDMyLjMzNzggMzUuOTI4NkMzMi4zMzcgMzUuOTI4NiAzMi4zMzYyIDM1LjkyODYgMzIuMzM1NCAzNS45Mjg2QzMyLjMzNTEgMzUuOTI4NiAzMi4zMzQ3IDM1LjkyODYgMzIuMzM0MyAzNS45Mjg2QzMyLjMzNDIgMzUuOTI4NiAzMi4zMzM5IDM1LjkyODYgMzIuMzMzOCAzNS45Mjg2QzMyLjMzMzYgMzUuOTI4NiAzMi4zMzMzIDM1LjkyODYgMzIuMzMzMyAzNS40Mjg2Wk0yNi45NzkyIDMxLjY4NTdDMjcuODM5NyAzMi43NTA0IDI4Ljk3OTEgMzMuNTY4MyAzMC4wMjU4IDM0LjEyMDRDMzAuNTQ3NSAzNC4zOTU2IDMxLjAzODYgMzQuNjAwNyAzMS40NSAzNC43MzZDMzEuODcyNyAzNC44NzUgMzIuMTc2IDM0LjkyODYgMzIuMzMzMyAzNC45Mjg2VjM1LjkyODZDMzIuMDE3MyAzNS45Mjg2IDMxLjU5NDcgMzUuODM2MyAzMS4xMzc2IDM1LjY4NkMzMC42NjkgMzUuNTMxOSAzMC4xMjY0IDM1LjMwNDEgMjkuNTU5MiAzNS4wMDQ5QzI4LjQyODEgMzQuNDA4MyAyNy4xNjkzIDMzLjUxMTkgMjYuMjAxNSAzMi4zMTQzTDI2Ljk3OTIgMzEuNjg1N1pNMjAgMzEuNUgyNi41OTAzVjMyLjVIMjBWMzEuNVpNMTYuNSAyOEMxNi41IDI5LjkzMyAxOC4wNjcgMzEuNSAyMCAzMS41VjMyLjVDMTcuNTE0NyAzMi41IDE1LjUgMzAuNDg1MyAxNS41IDI4SDE2LjVaTTE2LjUgMjBWMjhIMTUuNVYyMEgxNi41Wk0yMCAxNi41QzE4LjA2NyAxNi41IDE2LjUgMTguMDY3IDE2LjUgMjBIMTUuNUMxNS41IDE3LjUxNDcgMTcuNTE0NyAxNS41IDIwIDE1LjVWMTYuNVpNMzIgMTYuNUgyMFYxNS41SDMyVjE2LjVaIiBmaWxsPSIjMEI4RTY5Ii8+CjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNMjQuOTIyNiAyNS4wMjAxSDI3LjA0M0wyNi4wMTE1IDIyLjAxNzJIMjUuOTg4NUwyNC45MjI2IDI1LjAyMDFaTTI1LjA5NDYgMjBIMjYuOTM5OEwzMCAyOC4xODM0SDI4LjEzMThMMjcuNTEyOSAyNi4zNjFIMjQuNDUyN0wyMy44MTA5IDI4LjE4MzRIMjJMMjUuMDk0NiAyMFoiIGZpbGw9ImJsYWNrIi8+CjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNMzMuMDMzIDEyLjg3NjNDMzIuODMzNSAxMy4wNzEzIDMyLjU2MzUgMTMuMTgxMyAzMi4yODMgMTMuMTgxM0MzMi4wMDM0IDEzLjE4MTMgMzEuNzMzNCAxMy4wNzEzIDMxLjUzMjkgMTIuODc2M0wyOC44Nzg0IDEwLjIxNjJDMjguNTczNCA5LjkxMTIyIDI4LjQ4MzQgOS40NTYyMSAyOC42NDg0IDkuMDYxMkMyOC44MTM0IDguNjY2MTkgMjkuMTkzNCA4LjQxMTE5IDI5LjYyMzQgOC40MTExOUgzMC41Nzg0QzMwLjU1MzQgOC4xODExOSAzMC40ODg0IDcuOTIxMTggMzAuMzc4NCA3LjY0NjE4QzMwLjM0MzkgNy41NjYxNyAzMC4zMDg0IDcuNDg2MTcgMzAuMjY4NCA3LjQwNjE3QzMwLjIxMzQgNy4zMTYxNyAzMC4yMTg5IDcuMjkxMTcgMzAuMTQzNCA3LjE4MTE3QzMwLjAyMzQgNy4wMDExNiAyOS45MTM0IDYuODY2MTYgMjkuNzgyOSA2LjcxMTE2QzI5LjUxODQgNi40MjYxNSAyOS4xOTg0IDYuMTgxMTUgMjguODU4NCA2LjAwMTE1QzI4LjUxMzQgNS44MjExNCAyOC4xNTM0IDUuNzExMTQgMjcuODMzNCA1LjY1MTE0QzI3LjUxODQgNS41OTYxNCAyNy4yMjg0IDUuNTkxMTQgMjcuMDU4NCA1LjU5MTE0QzI2Ljk3MzQgNS41ODYxNCAyNi44NjM0IDUuNjA2MTQgMjYuODA4NCA1LjYxMTE0QzI2Ljc0ODQgNS42MTYxNCAyNi43MTM0IDUuNjIxMTQgMjYuNzEzNCA1LjYyMTE0QzI2LjM1ODMgNS42NTYxNCAyNi4wMzgzIDUuMzk2MTQgMjYuMDAzMyA1LjA0MTEzQzI1Ljk3MzMgNC43NDExMiAyNi4xNDgzIDQuNDcxMTIgMjYuNDEzMyA0LjM3MTEyQzI2LjQxMzMgNC4zNzExMiAyNi40NDgzIDQuMzU2MTIgMjYuNTAzMyA0LjMzNjEyQzI2LjU2ODMgNC4zMTYxMiAyNi42Mjg0IDQuMjgxMTIgMjYuNzY4NCA0LjI0MTEyQzI3LjA0ODQgNC4xNTYxMSAyNy40MDM0IDQuMDY2MTEgMjcuODY4NCA0LjAyMTExQzI4LjMyODQgMy45ODExMSAyOC44ODM0IDMuOTkxMTEgMjkuNDY4OSA0LjExMTExQzMwLjA1MzQgNC4yMzYxMiAzMC42Njg0IDQuNDcxMTIgMzEuMjM4NCA0LjgxMTEzQzMxLjUwODQgNC45ODYxMyAzMS43OTg0IDUuMTkxMTMgMzIuMDIzNCA1LjM5MTE0QzMyLjEyMzQgNS40NjYxNCAzMi4yOTM1IDUuNjM2MTQgMzIuMzkzNSA1Ljc0MTE0QzMyLjUwODUgNS44NjExNCAzMi42MTM1IDUuOTgxMTUgMzIuNzE5IDYuMTA2MTVDMzMuMTIzNSA2LjYwNjE2IDMzLjQyMzUgNy4xNDYxNyAzMy42MTg1IDcuNjM2MThDMzMuNzMzNSA3LjkxNjE4IDMzLjgxMzUgOC4xODExOSAzMy44NzM1IDguNDExMTlIMzQuOTQzNUMzNS4zNzM1IDguNDExMTkgMzUuNzUzNSA4LjY2NjE5IDM1LjkxODUgOS4wNjEyQzM2LjA4MzUgOS40NTYyMSAzNS45OTM1IDkuOTExMjIgMzUuNjg4NSAxMC4yMTYyTDMzLjAzMyAxMi44NzYzWiIgZmlsbD0iYmxhY2siLz4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik02Ljk2NzA0IDI3LjEyNUM3LjE2NjU0IDI2LjkzIDcuNDM2NTQgMjYuODIgNy43MTcwNSAyNi44MkM3Ljk5NjU1IDI2LjgyIDguMjY2NTYgMjYuOTMgOC40NjcwNiAyNy4xMjVMMTEuMTIxNiAyOS43ODUxQzExLjQyNjYgMzAuMDkwMSAxMS41MTY2IDMwLjU0NTEgMTEuMzUxNiAzMC45NDAxQzExLjE4NjYgMzEuMzM1MSAxMC44MDY2IDMxLjU5MDEgMTAuMzc2NiAzMS41OTAxSDkuNDIxNThDOS40NDY1OCAzMS44MjAxIDkuNTExNTggMzIuMDgwMSA5LjYyMTU4IDMyLjM1NTFDOS42NTYwOCAzMi40MzUxIDkuNjkxNTggMzIuNTE1MSA5LjczMTU4IDMyLjU5NTFDOS43ODY1OSAzMi42ODUxIDkuNzgxMDkgMzIuNzEwMSA5Ljg1NjU5IDMyLjgyMDFDOS45NzY1OSAzMy4wMDAxIDEwLjA4NjYgMzMuMTM1MSAxMC4yMTcxIDMzLjI5MDFDMTAuNDgxNiAzMy41NzUxIDEwLjgwMTYgMzMuODIwMSAxMS4xNDE2IDM0LjAwMDFDMTEuNDg2NiAzNC4xODAxIDExLjg0NjYgMzQuMjkwMSAxMi4xNjY2IDM0LjM1MDFDMTIuNDgxNiAzNC40MDUxIDEyLjc3MTYgMzQuNDEwMSAxMi45NDE2IDM0LjQxMDFDMTMuMDI2NiAzNC40MTUxIDEzLjEzNjYgMzQuMzk1MSAxMy4xOTE2IDM0LjM5MDFDMTMuMjUxNiAzNC4zODUxIDEzLjI4NjYgMzQuMzgwMSAxMy4yODY2IDM0LjM4MDFDMTMuNjQxNyAzNC4zNDUxIDEzLjk2MTcgMzQuNjA1MSAxMy45OTY3IDM0Ljk2MDJDMTQuMDI2NyAzNS4yNjAyIDEzLjg1MTcgMzUuNTMwMiAxMy41ODY3IDM1LjYzMDJDMTMuNTg2NyAzNS42MzAyIDEzLjU1MTcgMzUuNjQ1MiAxMy40OTY3IDM1LjY2NTJDMTMuNDMxNyAzNS42ODUyIDEzLjM3MTYgMzUuNzIwMiAxMy4yMzE2IDM1Ljc2MDJDMTIuOTUxNiAzNS44NDUyIDEyLjU5NjYgMzUuOTM1MiAxMi4xMzE2IDM1Ljk4MDJDMTEuNjcxNiAzNi4wMjAyIDExLjExNjYgMzYuMDEwMiAxMC41MzExIDM1Ljg5MDJDOS45NDY1OSAzNS43NjUyIDkuMzMxNTggMzUuNTMwMiA4Ljc2MTU3IDM1LjE5MDJDOC40OTE1NiAzNS4wMTUyIDguMjAxNTYgMzQuODEwMSA3Ljk3NjU1IDM0LjYxMDFDNy44NzY1NSAzNC41MzUxIDcuNzA2NTUgMzQuMzY1MSA3LjYwNjU1IDM0LjI2MDFDNy40OTE1NCAzNC4xNDAxIDcuMzg2NTQgMzQuMDIwMSA3LjI4MTA0IDMzLjg5NTFDNi44NzY1MyAzMy4zOTUxIDYuNTc2NTMgMzIuODU1MSA2LjM4MTUzIDMyLjM2NTFDNi4yNjY1MiAzMi4wODUxIDYuMTg2NTIgMzEuODIwMSA2LjEyNjUyIDMxLjU5MDFINS4wNTY1QzQuNjI2NDkgMzEuNTkwMSA0LjI0NjQ5IDMxLjMzNTEgNC4wODE0OCAzMC45NDAxQzMuOTE2NDggMzAuNTQ1MSA0LjAwNjQ4IDMwLjA5MDEgNC4zMTE0OSAyOS43ODUxTDYuOTY3MDQgMjcuMTI1WiIgZmlsbD0iYmxhY2siLz4KPC9zdmc+Cg==' + }, + videoSensing: { + // eslint-disable-next-line max-len + blockIconURI: 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDAiIGhlaWdodD0iNDAiIHZpZXdCb3g9IjAgMCA0MCA0MCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPGNpcmNsZSBvcGFjaXR5PSIwLjI1IiBjeD0iMzIiIGN5PSIyNiIgcj0iNCIgZmlsbD0id2hpdGUiIHN0cm9rZT0iIzBCOEU2OSIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIi8+CjxjaXJjbGUgb3BhY2l0eT0iMC41IiBjeD0iMzIiIGN5PSIyMiIgcj0iNCIgZmlsbD0id2hpdGUiIHN0cm9rZT0iIzBCOEU2OSIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIi8+CjxjaXJjbGUgb3BhY2l0eT0iMC43NSIgY3g9IjMyIiBjeT0iMTgiIHI9IjQiIGZpbGw9IndoaXRlIiBzdHJva2U9IiMwQjhFNjkiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIvPgo8Y2lyY2xlIGN4PSIzMiIgY3k9IjE0IiByPSI0IiBmaWxsPSJ3aGl0ZSIgc3Ryb2tlPSIjMEI4RTY5IiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiLz4KPHBhdGggZD0iTTE3IDE3LjVMMjIuNCAxNEMyMi45IDEzLjcgMjMuNSAxMy44IDIzLjggMTQuM0MyMy45IDE0LjUgMjQgMTQuNyAyNCAxNC44VjI1LjFDMjQgMjUuNyAyMy41IDI2LjEgMjMgMjYuMUMyMi44IDI2LjEgMjIuNiAyNiAyMi41IDI1LjlMMTcgMjIuNlYyNEMxNyAyNi4yIDE1LjIgMjguMSAxMyAyOC4xSDQuMUMxLjggMjggMCAyNi4yIDAgMjRWMTYuMUMwIDEzLjggMS44IDEyIDQuMSAxMkgxM0MxNS4yIDEyIDE3IDEzLjggMTcgMTYuMVYxNy41WiIgZmlsbD0iYmxhY2siLz4KPC9zdmc+Cg==' + } +}; + +export { + blockColors, + extensions +}; diff --git a/src/lib/themes/index.js b/src/lib/themes/index.js index 000960e4a..d77a7a6f3 100644 --- a/src/lib/themes/index.js +++ b/src/lib/themes/index.js @@ -1,9 +1,15 @@ import defaultsDeep from 'lodash.defaultsdeep'; import {defineMessages} from 'react-intl'; -import darkMode from './dark-mode'; -import highContrast from './high-contrast'; -import defaultColors from './default-colors'; +import { + blockColors as darkModeBlockColors, + extensions as darkModeExtensions +} from './dark-mode'; +import { + blockColors as highContrastBlockColors, + extensions as highContrastExtensions +} from './high-contrast'; +import {blockColors as defaultColors} from './default-colors'; import defaultIcon from './standard.svg'; import highContrastIcon from './high-contrast.svg'; @@ -34,16 +40,22 @@ const messages = defineMessages({ const themeMap = { [DEFAULT_THEME]: { + blocksMediaFolder: 'blocks-media', colors: defaultColors, + extensions: {}, label: messages[DEFAULT_THEME], icon: defaultIcon }, [DARK_THEME]: { - colors: mergeWithDefaults(darkMode), + blocksMediaFolder: 'blocks-media', + colors: mergeWithDefaults(darkModeBlockColors), + extensions: darkModeExtensions, label: messages[DARK_THEME] }, [HIGH_CONTRAST_THEME]: { - colors: mergeWithDefaults(highContrast), + blocksMediaFolder: 'blocks-media-high-contrast', + colors: mergeWithDefaults(highContrastBlockColors), + extensions: highContrastExtensions, label: messages[HIGH_CONTRAST_THEME], icon: highContrastIcon } diff --git a/static/blocks-media-high-contrast/comment-arrow-down.svg b/static/blocks-media-high-contrast/comment-arrow-down.svg new file mode 100644 index 000000000..9753f40b0 --- /dev/null +++ b/static/blocks-media-high-contrast/comment-arrow-down.svg @@ -0,0 +1,10 @@ + + + + dropdown-caret-up + Created with Sketch. + + + + + diff --git a/static/blocks-media-high-contrast/comment-arrow-up.svg b/static/blocks-media-high-contrast/comment-arrow-up.svg new file mode 100644 index 000000000..a118883f4 --- /dev/null +++ b/static/blocks-media-high-contrast/comment-arrow-up.svg @@ -0,0 +1,10 @@ + + + + dropdown-caret-down + Created with Sketch. + + + + + diff --git a/static/blocks-media-high-contrast/delete-x.svg b/static/blocks-media-high-contrast/delete-x.svg new file mode 100644 index 000000000..46d898a9a --- /dev/null +++ b/static/blocks-media-high-contrast/delete-x.svg @@ -0,0 +1,10 @@ + + + + delete-x + Created with Sketch. + + + + + diff --git a/static/blocks-media-high-contrast/dropdown-arrow.svg b/static/blocks-media-high-contrast/dropdown-arrow.svg new file mode 100644 index 000000000..585e5cc4f --- /dev/null +++ b/static/blocks-media-high-contrast/dropdown-arrow.svg @@ -0,0 +1 @@ +dropdown-arrow \ No newline at end of file diff --git a/static/blocks-media-high-contrast/eyedropper.svg b/static/blocks-media-high-contrast/eyedropper.svg new file mode 100644 index 000000000..c7a7cfc9a --- /dev/null +++ b/static/blocks-media-high-contrast/eyedropper.svg @@ -0,0 +1,22 @@ + + + + Artboard + Created with Sketch. + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/static/blocks-media-high-contrast/icons/arrow_button.svg b/static/blocks-media-high-contrast/icons/arrow_button.svg new file mode 100644 index 000000000..5fa8ffee2 --- /dev/null +++ b/static/blocks-media-high-contrast/icons/arrow_button.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/static/blocks-media-high-contrast/repeat.svg b/static/blocks-media-high-contrast/repeat.svg new file mode 100644 index 000000000..70d02b909 --- /dev/null +++ b/static/blocks-media-high-contrast/repeat.svg @@ -0,0 +1,13 @@ + + + + +repeat + + diff --git a/static/blocks-media-high-contrast/rotate-left.svg b/static/blocks-media-high-contrast/rotate-left.svg new file mode 100644 index 000000000..eb120afa4 --- /dev/null +++ b/static/blocks-media-high-contrast/rotate-left.svg @@ -0,0 +1 @@ +rotate-clockwise \ No newline at end of file diff --git a/static/blocks-media-high-contrast/rotate-right.svg b/static/blocks-media-high-contrast/rotate-right.svg new file mode 100644 index 000000000..960c00bbe --- /dev/null +++ b/static/blocks-media-high-contrast/rotate-right.svg @@ -0,0 +1 @@ +rotate-counter-clockwise \ No newline at end of file diff --git a/static/blocks-media-high-contrast/zoom-in.svg b/static/blocks-media-high-contrast/zoom-in.svg new file mode 100644 index 000000000..6395eb2d4 --- /dev/null +++ b/static/blocks-media-high-contrast/zoom-in.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/static/blocks-media-high-contrast/zoom-out.svg b/static/blocks-media-high-contrast/zoom-out.svg new file mode 100644 index 000000000..3dc33cd6e --- /dev/null +++ b/static/blocks-media-high-contrast/zoom-out.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/static/blocks-media-high-contrast/zoom-reset.svg b/static/blocks-media-high-contrast/zoom-reset.svg new file mode 100644 index 000000000..2e358b0d7 --- /dev/null +++ b/static/blocks-media-high-contrast/zoom-reset.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/test/unit/util/themes.test.js b/test/unit/util/themes.test.js index 575f7e886..d12139e20 100644 --- a/test/unit/util/themes.test.js +++ b/test/unit/util/themes.test.js @@ -5,7 +5,7 @@ import { getColorsForTheme, HIGH_CONTRAST_THEME } from '../../../src/lib/themes'; -import {injectExtensionBlockColors, injectExtensionCategoryColors} from '../../../src/lib/themes/blockHelpers'; +import {injectExtensionBlockTheme, injectExtensionCategoryTheme} from '../../../src/lib/themes/blockHelpers'; import {detectTheme, persistTheme} from '../../../src/lib/themes/themePersistance'; jest.mock('../../../src/lib/themes/default-colors'); @@ -49,7 +49,7 @@ describe('themes', () => { colourTertiary: '#0B8E69' }; - const updated = injectExtensionBlockColors(blockInfoJson, DARK_THEME); + const updated = injectExtensionBlockTheme(blockInfoJson, DARK_THEME); expect(updated).toEqual({ type: 'dummy_block', @@ -69,7 +69,7 @@ describe('themes', () => { colourTertiary: '#0B8E69' }; - const updated = injectExtensionBlockColors(blockInfoJson, DEFAULT_THEME); + const updated = injectExtensionBlockTheme(blockInfoJson, DEFAULT_THEME); expect(updated).toEqual({ type: 'dummy_block', @@ -87,7 +87,7 @@ describe('themes', () => { } ]; - injectExtensionCategoryColors(dynamicBlockXML, DARK_THEME); + injectExtensionCategoryTheme(dynamicBlockXML, DARK_THEME); // XMLSerializer is not available outside the browser. // Verify the mocked XMLSerializer.serializeToString is called with updated colors. diff --git a/webpack.config.js b/webpack.config.js index 168faa396..a59eb263d 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -171,6 +171,15 @@ module.exports = [ { from: 'node_modules/scratch-blocks/media', to: 'static/blocks-media' + }, + { + from: 'node_modules/scratch-blocks/media', + to: 'static/blocks-media-high-contrast' + }, + { + from: 'static/blocks-media-high-contrast', + to: 'static/blocks-media-high-contrast', + force: true } ] }),