feat: store color theme in state
This commit is contained in:
1 parent
79c46e5405
commit
b2d4021455
12 files changed
+410
-58
No files matched your search
@@ -117,6 +117,7 @@ const GUIComponent = props => {
|
||||
stageSizeMode,
|
||||
targetIsStage,
|
||||
telemetryModalVisible,
|
||||
theme,
|
||||
tipsLibraryVisible,
|
||||
vm,
|
||||
...componentProps
|
||||
@@ -303,10 +304,12 @@ const GUIComponent = props => {
|
||||
canUseCloud={canUseCloud}
|
||||
grow={1}
|
||||
isVisible={blocksTabVisible}
|
||||
key={theme}
|
||||
options={{
|
||||
media: `${basePath}static/blocks-media/`
|
||||
}}
|
||||
stageSize={stageSize}
|
||||
theme={theme}
|
||||
vm={vm}
|
||||
/>
|
||||
</Box>
|
||||
@@ -422,6 +425,7 @@ GUIComponent.propTypes = {
|
||||
stageSizeMode: PropTypes.oneOf(Object.keys(STAGE_SIZE_MODES)),
|
||||
targetIsStage: PropTypes.bool,
|
||||
telemetryModalVisible: PropTypes.bool,
|
||||
theme: PropTypes.string,
|
||||
tipsLibraryVisible: PropTypes.bool,
|
||||
vm: PropTypes.instanceOf(VM).isRequired
|
||||
};
|
||||
@@ -448,7 +452,8 @@ GUIComponent.defaultProps = {
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
// This is the button's mode, as opposed to the actual current state
|
||||
stageSizeMode: state.scratchGui.stageSize.stageSize
|
||||
stageSizeMode: state.scratchGui.stageSize.stageSize,
|
||||
theme: state.scratchGui.theme.theme
|
||||
});
|
||||
|
||||
export default injectIntl(connect(
|
||||
|
||||
@@ -18,6 +18,7 @@ import {BLOCKS_DEFAULT_SCALE, STAGE_DISPLAY_SIZES} from '../lib/layout-constants
|
||||
import DropAreaHOC from '../lib/drop-area-hoc.jsx';
|
||||
import DragConstants from '../lib/drag-constants';
|
||||
import defineDynamicBlock from '../lib/define-dynamic-block';
|
||||
import {getColorsForTheme, themes} from '../lib/themes';
|
||||
|
||||
import {connect} from 'react-redux';
|
||||
import {updateToolbox} from '../reducers/toolbox';
|
||||
@@ -94,7 +95,7 @@ class Blocks extends React.Component {
|
||||
const workspaceConfig = defaultsDeep({},
|
||||
Blocks.defaultOptions,
|
||||
this.props.options,
|
||||
{rtl: this.props.isRtl, toolbox: this.props.toolboxXML}
|
||||
{rtl: this.props.isRtl, toolbox: this.props.toolboxXML, colours: getColorsForTheme(this.props.theme)}
|
||||
);
|
||||
this.workspace = this.ScratchBlocks.inject(this.blocks, workspaceConfig);
|
||||
|
||||
@@ -351,7 +352,8 @@ class Blocks extends React.Component {
|
||||
return makeToolboxXML(false, target.isStage, target.id, dynamicBlocksXML,
|
||||
targetCostumes[targetCostumes.length - 1].name,
|
||||
stageCostumes[stageCostumes.length - 1].name,
|
||||
targetSounds.length > 0 ? targetSounds[targetSounds.length - 1].name : ''
|
||||
targetSounds.length > 0 ? targetSounds[targetSounds.length - 1].name : '',
|
||||
getColorsForTheme(this.props.theme)
|
||||
);
|
||||
} catch {
|
||||
return null;
|
||||
@@ -620,22 +622,11 @@ Blocks.propTypes = {
|
||||
wheel: PropTypes.bool,
|
||||
startScale: PropTypes.number
|
||||
}),
|
||||
colours: PropTypes.shape({
|
||||
workspace: PropTypes.string,
|
||||
flyout: PropTypes.string,
|
||||
toolbox: PropTypes.string,
|
||||
toolboxSelected: PropTypes.string,
|
||||
scrollbar: PropTypes.string,
|
||||
scrollbarHover: PropTypes.string,
|
||||
insertionMarker: PropTypes.string,
|
||||
insertionMarkerOpacity: PropTypes.number,
|
||||
fieldShadow: PropTypes.string,
|
||||
dragShadowOpacity: PropTypes.number
|
||||
}),
|
||||
comments: PropTypes.bool,
|
||||
collapse: PropTypes.bool
|
||||
}),
|
||||
stageSize: PropTypes.oneOf(Object.keys(STAGE_DISPLAY_SIZES)).isRequired,
|
||||
theme: PropTypes.oneOf(themes),
|
||||
toolboxXML: PropTypes.string,
|
||||
updateMetrics: PropTypes.func,
|
||||
updateToolboxState: PropTypes.func,
|
||||
@@ -656,18 +647,6 @@ Blocks.defaultOptions = {
|
||||
length: 2,
|
||||
colour: '#ddd'
|
||||
},
|
||||
colours: {
|
||||
workspace: '#F9F9F9',
|
||||
flyout: '#F9F9F9',
|
||||
toolbox: '#FFFFFF',
|
||||
toolboxSelected: '#E9EEF2',
|
||||
scrollbar: '#CECDCE',
|
||||
scrollbarHover: '#CECDCE',
|
||||
insertionMarker: '#000000',
|
||||
insertionMarkerOpacity: 0.2,
|
||||
fieldShadow: 'rgba(255, 255, 255, 0.3)',
|
||||
dragShadowOpacity: 0.6
|
||||
},
|
||||
comments: true,
|
||||
collapse: false,
|
||||
sounds: false
|
||||
@@ -675,7 +654,8 @@ Blocks.defaultOptions = {
|
||||
|
||||
Blocks.defaultProps = {
|
||||
isVisible: true,
|
||||
options: Blocks.defaultOptions
|
||||
options: Blocks.defaultOptions,
|
||||
theme: 'standard'
|
||||
};
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
|
||||
+54
-30
@@ -1,17 +1,19 @@
|
||||
import ScratchBlocks from 'scratch-blocks';
|
||||
import {defaultColors} from './themes';
|
||||
|
||||
const categorySeparator = '<sep gap="36"/>';
|
||||
|
||||
const blockSeparator = '<sep gap="36"/>'; // At default scale, about 28px
|
||||
|
||||
/* eslint-disable no-unused-vars */
|
||||
const motion = function (isInitialSetup, isStage, targetId) {
|
||||
const motion = function (isInitialSetup, isStage, targetId, colors) {
|
||||
const stageSelected = ScratchBlocks.ScratchMsgs.translate(
|
||||
'MOTION_STAGE_SELECTED',
|
||||
'Stage selected: no motion blocks'
|
||||
);
|
||||
// Note: the category's secondaryColour matches up with the blocks' tertiary color, both used for border color.
|
||||
return `
|
||||
<category name="%{BKY_CATEGORY_MOTION}" id="motion" colour="#4C97FF" secondaryColour="#3373CC">
|
||||
<category name="%{BKY_CATEGORY_MOTION}" id="motion" colour="${colors.primary}" secondaryColour="${colors.tertiary}">
|
||||
${isStage ? `
|
||||
<label text="${stageSelected}"></label>
|
||||
` : `
|
||||
@@ -151,11 +153,12 @@ const xmlEscape = function (unsafe) {
|
||||
});
|
||||
};
|
||||
|
||||
const looks = function (isInitialSetup, isStage, targetId, costumeName, backdropName) {
|
||||
const looks = function (isInitialSetup, isStage, targetId, costumeName, backdropName, colors) {
|
||||
const hello = ScratchBlocks.ScratchMsgs.translate('LOOKS_HELLO', 'Hello!');
|
||||
const hmm = ScratchBlocks.ScratchMsgs.translate('LOOKS_HMM', 'Hmm...');
|
||||
// Note: the category's secondaryColour matches up with the blocks' tertiary color, both used for border color.
|
||||
return `
|
||||
<category name="%{BKY_CATEGORY_LOOKS}" id="looks" colour="#9966FF" secondaryColour="#774DCB">
|
||||
<category name="%{BKY_CATEGORY_LOOKS}" id="looks" colour="${colors.primary}" secondaryColour="${colors.tertiary}">
|
||||
${isStage ? '' : `
|
||||
<block type="looks_sayforsecs">
|
||||
<value name="MESSAGE">
|
||||
@@ -288,9 +291,10 @@ const looks = function (isInitialSetup, isStage, targetId, costumeName, backdrop
|
||||
`;
|
||||
};
|
||||
|
||||
const sound = function (isInitialSetup, isStage, targetId, soundName) {
|
||||
const sound = function (isInitialSetup, isStage, targetId, soundName, colors) {
|
||||
// Note: the category's secondaryColour matches up with the blocks' tertiary color, both used for border color.
|
||||
return `
|
||||
<category name="%{BKY_CATEGORY_SOUND}" id="sound" colour="#D65CD6" secondaryColour="#BD42BD">
|
||||
<category name="%{BKY_CATEGORY_SOUND}" id="sound" colour="${colors.primary}" secondaryColour="${colors.tertiary}">
|
||||
<block id="${targetId}_sound_playuntildone" type="sound_playuntildone">
|
||||
<value name="SOUND_MENU">
|
||||
<shadow type="sound_sounds_menu">
|
||||
@@ -343,9 +347,10 @@ const sound = function (isInitialSetup, isStage, targetId, soundName) {
|
||||
`;
|
||||
};
|
||||
|
||||
const events = function (isInitialSetup, isStage) {
|
||||
const events = function (isInitialSetup, isStage, targetId, colors) {
|
||||
// Note: the category's secondaryColour matches up with the blocks' tertiary color, both used for border color.
|
||||
return `
|
||||
<category name="%{BKY_CATEGORY_EVENTS}" id="events" colour="#FFD500" secondaryColour="#CC9900">
|
||||
<category name="%{BKY_CATEGORY_EVENTS}" id="events" colour="${colors.primary}" secondaryColour="${colors.tertiary}">
|
||||
<block type="event_whenflagclicked"/>
|
||||
<block type="event_whenkeypressed">
|
||||
</block>
|
||||
@@ -382,9 +387,14 @@ const events = function (isInitialSetup, isStage) {
|
||||
`;
|
||||
};
|
||||
|
||||
const control = function (isInitialSetup, isStage) {
|
||||
const control = function (isInitialSetup, isStage, targetId, colors) {
|
||||
// Note: the category's secondaryColour matches up with the blocks' tertiary color, both used for border color.
|
||||
return `
|
||||
<category name="%{BKY_CATEGORY_CONTROL}" id="control" colour="#FFAB19" secondaryColour="#CF8B17">
|
||||
<category
|
||||
name="%{BKY_CATEGORY_CONTROL}"
|
||||
id="control"
|
||||
colour="${colors.primary}"
|
||||
secondaryColour="${colors.tertiary}">
|
||||
<block type="control_wait">
|
||||
<value name="DURATION">
|
||||
<shadow type="math_positive_number">
|
||||
@@ -429,10 +439,15 @@ const control = function (isInitialSetup, isStage) {
|
||||
`;
|
||||
};
|
||||
|
||||
const sensing = function (isInitialSetup, isStage) {
|
||||
const sensing = function (isInitialSetup, isStage, targetId, colors) {
|
||||
const name = ScratchBlocks.ScratchMsgs.translate('SENSING_ASK_TEXT', 'What\'s your name?');
|
||||
// Note: the category's secondaryColour matches up with the blocks' tertiary color, both used for border color.
|
||||
return `
|
||||
<category name="%{BKY_CATEGORY_SENSING}" id="sensing" colour="#4CBFE6" secondaryColour="#2E8EB8">
|
||||
<category
|
||||
name="%{BKY_CATEGORY_SENSING}"
|
||||
id="sensing"
|
||||
colour="${colors.primary}"
|
||||
secondaryColour="${colors.tertiary}">
|
||||
${isStage ? '' : `
|
||||
<block type="sensing_touchingobject">
|
||||
<value name="TOUCHINGOBJECTMENU">
|
||||
@@ -504,12 +519,17 @@ const sensing = function (isInitialSetup, isStage) {
|
||||
`;
|
||||
};
|
||||
|
||||
const operators = function (isInitialSetup) {
|
||||
const operators = function (isInitialSetup, isStage, targetId, colors) {
|
||||
const apple = ScratchBlocks.ScratchMsgs.translate('OPERATORS_JOIN_APPLE', 'apple');
|
||||
const banana = ScratchBlocks.ScratchMsgs.translate('OPERATORS_JOIN_BANANA', 'banana');
|
||||
const letter = ScratchBlocks.ScratchMsgs.translate('OPERATORS_LETTEROF_APPLE', 'a');
|
||||
// Note: the category's secondaryColour matches up with the blocks' tertiary color, both used for border color.
|
||||
return `
|
||||
<category name="%{BKY_CATEGORY_OPERATORS}" id="operators" colour="#40BF4A" secondaryColour="#389438">
|
||||
<category
|
||||
name="%{BKY_CATEGORY_OPERATORS}"
|
||||
id="operators"
|
||||
colour="${colors.primary}"
|
||||
secondaryColour="${colors.tertiary}">
|
||||
<block type="operator_add">
|
||||
<value name="NUM1">
|
||||
<shadow type="math_number">
|
||||
@@ -691,25 +711,27 @@ const operators = function (isInitialSetup) {
|
||||
`;
|
||||
};
|
||||
|
||||
const variables = function () {
|
||||
const variables = function (isInitialSetup, isStage, targetId, colors) {
|
||||
// Note: the category's secondaryColour matches up with the blocks' tertiary color, both used for border color.
|
||||
return `
|
||||
<category
|
||||
name="%{BKY_CATEGORY_VARIABLES}"
|
||||
id="variables"
|
||||
colour="#FF8C1A"
|
||||
secondaryColour="#DB6E00"
|
||||
colour="${colors.primary}"
|
||||
secondaryColour="${colors.tertiary}"
|
||||
custom="VARIABLE">
|
||||
</category>
|
||||
`;
|
||||
};
|
||||
|
||||
const myBlocks = function () {
|
||||
const myBlocks = function (isInitialSetup, isStage, targetId, colors) {
|
||||
// Note: the category's secondaryColour matches up with the blocks' tertiary color, both used for border color.
|
||||
return `
|
||||
<category
|
||||
name="%{BKY_CATEGORY_MYBLOCKS}"
|
||||
id="myBlocks"
|
||||
colour="#FF6680"
|
||||
secondaryColour="#FF4D6A"
|
||||
colour="${colors.primary}"
|
||||
secondaryColour="${colors.tertiary}"
|
||||
custom="PROCEDURE">
|
||||
</category>
|
||||
`;
|
||||
@@ -732,10 +754,11 @@ const xmlClose = '</xml>';
|
||||
* @param {?string} costumeName - The name of the default selected costume dropdown.
|
||||
* @param {?string} backdropName - The name of the default selected backdrop dropdown.
|
||||
* @param {?string} soundName - The name of the default selected sound dropdown.
|
||||
* @param {?object} colors - The colors for the theme.
|
||||
* @returns {string} - a ScratchBlocks-style XML document for the contents of the toolbox.
|
||||
*/
|
||||
const makeToolboxXML = function (isInitialSetup, isStage = true, targetId, categoriesXML = [],
|
||||
costumeName = '', backdropName = '', soundName = '') {
|
||||
costumeName = '', backdropName = '', soundName = '', colors = defaultColors) {
|
||||
isStage = isInitialSetup || isStage;
|
||||
const gap = [categorySeparator];
|
||||
|
||||
@@ -753,15 +776,16 @@ const makeToolboxXML = function (isInitialSetup, isStage = true, targetId, categ
|
||||
}
|
||||
// return `undefined`
|
||||
};
|
||||
const motionXML = moveCategory('motion') || motion(isInitialSetup, isStage, targetId);
|
||||
const looksXML = moveCategory('looks') || looks(isInitialSetup, isStage, targetId, costumeName, backdropName);
|
||||
const soundXML = moveCategory('sound') || sound(isInitialSetup, isStage, targetId, soundName);
|
||||
const eventsXML = moveCategory('event') || events(isInitialSetup, isStage, targetId);
|
||||
const controlXML = moveCategory('control') || control(isInitialSetup, isStage, targetId);
|
||||
const sensingXML = moveCategory('sensing') || sensing(isInitialSetup, isStage, targetId);
|
||||
const operatorsXML = moveCategory('operators') || operators(isInitialSetup, isStage, targetId);
|
||||
const variablesXML = moveCategory('data') || variables(isInitialSetup, isStage, targetId);
|
||||
const myBlocksXML = moveCategory('procedures') || myBlocks(isInitialSetup, isStage, targetId);
|
||||
const motionXML = moveCategory('motion') || motion(isInitialSetup, isStage, targetId, colors.motion);
|
||||
const looksXML = moveCategory('looks') ||
|
||||
looks(isInitialSetup, isStage, targetId, costumeName, backdropName, colors.looks);
|
||||
const soundXML = moveCategory('sound') || sound(isInitialSetup, isStage, targetId, soundName, colors.sounds);
|
||||
const eventsXML = moveCategory('event') || events(isInitialSetup, isStage, targetId, colors.event);
|
||||
const controlXML = moveCategory('control') || control(isInitialSetup, isStage, targetId, colors.control);
|
||||
const sensingXML = moveCategory('sensing') || sensing(isInitialSetup, isStage, targetId, colors.sensing);
|
||||
const operatorsXML = moveCategory('operators') || operators(isInitialSetup, isStage, targetId, colors.operators);
|
||||
const variablesXML = moveCategory('data') || variables(isInitialSetup, isStage, targetId, colors.data);
|
||||
const myBlocksXML = moveCategory('procedures') || myBlocks(isInitialSetup, isStage, targetId, colors.more);
|
||||
|
||||
const everything = [
|
||||
xmlOpen,
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
const blockColors = {
|
||||
motion: {
|
||||
primary: '#AAAAAA'
|
||||
},
|
||||
text: '#BBBBBB'
|
||||
};
|
||||
|
||||
export default blockColors;
|
||||
@@ -0,0 +1,11 @@
|
||||
const blockColors = {
|
||||
motion: {
|
||||
primary: '#111111',
|
||||
secondary: '#222222',
|
||||
tertiary: '#333333'
|
||||
},
|
||||
text: '#444444',
|
||||
workspace: '#555555'
|
||||
};
|
||||
|
||||
export default blockColors;
|
||||
@@ -0,0 +1,66 @@
|
||||
const blockColors = {
|
||||
motion: {
|
||||
primary: '#0F1E33',
|
||||
secondary: '#4C4C4C',
|
||||
tertiary: '#4C97FF'
|
||||
},
|
||||
looks: {
|
||||
primary: '#1E1433',
|
||||
secondary: '#4C4C4C',
|
||||
tertiary: '#9966FF'
|
||||
},
|
||||
sounds: {
|
||||
primary: '#291329',
|
||||
secondary: '#4C4C4C',
|
||||
tertiary: '#CF63CF'
|
||||
},
|
||||
control: {
|
||||
primary: '#332205',
|
||||
secondary: '#4C4C4C',
|
||||
tertiary: '#FFAB19'
|
||||
},
|
||||
event: {
|
||||
primary: '#332600',
|
||||
secondary: '#4C4C4C',
|
||||
tertiary: '#FFBF00'
|
||||
},
|
||||
sensing: {
|
||||
primary: '#12232A',
|
||||
secondary: '#4C4C4C',
|
||||
tertiary: '#5CB1D6'
|
||||
},
|
||||
pen: {
|
||||
primary: '#03251C',
|
||||
secondary: '#4C4C4C',
|
||||
tertiary: '#0fBD8C'
|
||||
},
|
||||
operators: {
|
||||
primary: '#112611',
|
||||
secondary: '#4C4C4C',
|
||||
tertiary: '#59C059'
|
||||
},
|
||||
data: {
|
||||
primary: '#331C05',
|
||||
secondary: '#4C4C4C',
|
||||
tertiary: '#FF8C1A'
|
||||
},
|
||||
data_lists: {
|
||||
primary: '#331405',
|
||||
secondary: '#4C4C4C',
|
||||
tertiary: '#FF661A'
|
||||
},
|
||||
more: {
|
||||
primary: '#331419',
|
||||
secondary: '#4C4C4C',
|
||||
tertiary: '#FF6680'
|
||||
},
|
||||
text: '#E5E5E5',
|
||||
workspace: '#121212',
|
||||
toolboxSelected: '#4C4C4C',
|
||||
toolboxText: '#E5E5E5',
|
||||
toolbox: '#121212',
|
||||
flyout: '#121212',
|
||||
textField: '#4C4C4C'
|
||||
};
|
||||
|
||||
export default blockColors;
|
||||
@@ -0,0 +1,90 @@
|
||||
const blockColors = {
|
||||
motion: {
|
||||
primary: '#4C97FF',
|
||||
secondary: '#4280D7',
|
||||
tertiary: '#3373CC'
|
||||
},
|
||||
looks: {
|
||||
primary: '#9966FF',
|
||||
secondary: '#855CD6',
|
||||
tertiary: '#774DCB'
|
||||
},
|
||||
sounds: {
|
||||
primary: '#CF63CF',
|
||||
secondary: '#C94FC9',
|
||||
tertiary: '#BD42BD'
|
||||
},
|
||||
control: {
|
||||
primary: '#FFAB19',
|
||||
secondary: '#EC9C13',
|
||||
tertiary: '#CF8B17'
|
||||
},
|
||||
event: {
|
||||
primary: '#FFBF00',
|
||||
secondary: '#E6AC00',
|
||||
tertiary: '#CC9900'
|
||||
},
|
||||
sensing: {
|
||||
primary: '#5CB1D6',
|
||||
secondary: '#47A8D1',
|
||||
tertiary: '#2E8EB8'
|
||||
},
|
||||
pen: {
|
||||
primary: '#0fBD8C',
|
||||
secondary: '#0DA57A',
|
||||
tertiary: '#0B8E69'
|
||||
},
|
||||
operators: {
|
||||
primary: '#59C059',
|
||||
secondary: '#46B946',
|
||||
tertiary: '#389438'
|
||||
},
|
||||
data: {
|
||||
primary: '#FF8C1A',
|
||||
secondary: '#FF8000',
|
||||
tertiary: '#DB6E00'
|
||||
},
|
||||
// This is not a new category, but rather for differentiation
|
||||
// between lists and scalar variables.
|
||||
data_lists: {
|
||||
primary: '#FF661A',
|
||||
secondary: '#FF5500',
|
||||
tertiary: '#E64D00'
|
||||
},
|
||||
more: {
|
||||
primary: '#FF6680',
|
||||
secondary: '#FF4D6A',
|
||||
tertiary: '#FF3355'
|
||||
},
|
||||
text: '#575E75',
|
||||
workspace: '#F9F9F9',
|
||||
toolboxHover: '#4C97FF',
|
||||
toolboxSelected: '#E9EEF2',
|
||||
toolboxText: '#575E75',
|
||||
toolbox: '#FFFFFF',
|
||||
flyout: '#F9F9F9',
|
||||
scrollbar: '#CECDCE',
|
||||
scrollbarHover: '#CECDCE',
|
||||
textField: '#FFFFFF',
|
||||
insertionMarker: '#000000',
|
||||
insertionMarkerOpacity: 0.2,
|
||||
dragShadowOpacity: 0.6,
|
||||
stackGlow: '#FFF200',
|
||||
stackGlowSize: 4,
|
||||
stackGlowOpacity: 1,
|
||||
replacementGlow: '#FFFFFF',
|
||||
replacementGlowSize: 2,
|
||||
replacementGlowOpacity: 1,
|
||||
colourPickerStroke: '#FFFFFF',
|
||||
// CSS colours: support RGBA
|
||||
fieldShadow: 'rgba(255, 255, 255, 0.3)',
|
||||
dropDownShadow: 'rgba(0, 0, 0, .3)',
|
||||
numPadBackground: '#547AB2',
|
||||
numPadBorder: '#435F91',
|
||||
numPadActiveBackground: '#435F91',
|
||||
numPadText: 'white', // Do not use hex here, it cannot be inlined with data-uri SVG
|
||||
valueReportBackground: '#FFFFFF',
|
||||
valueReportBorder: '#AAAAAA'
|
||||
};
|
||||
|
||||
export default blockColors;
|
||||
@@ -0,0 +1,87 @@
|
||||
const blockColors = {
|
||||
motion: {
|
||||
primary: '#80B5FF',
|
||||
secondary: '#B3D2FF',
|
||||
tertiary: '#3373CC',
|
||||
// this field is not used in the "classic" Scratch 3 color scheme
|
||||
// If we add "modes" we'd have to handle what happens when this field is not defined.
|
||||
quaternary: '#CCE1FF'
|
||||
},
|
||||
looks: {
|
||||
primary: '#CCB3FF',
|
||||
secondary: '#DDCCFF',
|
||||
tertiary: '#774DCB',
|
||||
quaternary: '#EEE5FF'
|
||||
},
|
||||
sounds: {
|
||||
primary: '#E19DE1',
|
||||
secondary: '#FFB3FF',
|
||||
tertiary: '#BD42BD',
|
||||
quaternary: '#FFCCFF'
|
||||
|
||||
},
|
||||
control: {
|
||||
primary: '#FFBE4C',
|
||||
secondary: '#FFDA99',
|
||||
tertiary: '#CF8B17',
|
||||
quaternary: '#FFE3B3'
|
||||
},
|
||||
event: {
|
||||
primary: '#FFD966',
|
||||
secondary: '#FFECB3',
|
||||
tertiary: '#CC9900',
|
||||
quaternary: '#FFF2CC'
|
||||
},
|
||||
sensing: {
|
||||
primary: '#85C4E0',
|
||||
secondary: '#AED8EA',
|
||||
tertiary: '#2E8EB8',
|
||||
quaternary: '#C2E2F0'
|
||||
},
|
||||
pen: {
|
||||
primary: '#13ECAF',
|
||||
secondary: '#75F0CD',
|
||||
tertiary: '#0B8E69',
|
||||
quaternary: '#A3F5DE'
|
||||
},
|
||||
operators: {
|
||||
primary: '#7ECE7E',
|
||||
secondary: '#B5E3B5',
|
||||
tertiary: '#389438',
|
||||
quaternary: '#DAF1DA'
|
||||
},
|
||||
data: {
|
||||
primary: '#FFA54C',
|
||||
secondary: '#FFCC99',
|
||||
tertiary: '#DB6E00',
|
||||
quaternary: '#FFE5CC'
|
||||
},
|
||||
// This is not a new category, but rather for differentiation
|
||||
// between lists and scalar variables.
|
||||
data_lists: {
|
||||
primary: '#FF9966',
|
||||
secondary: '#FFCAB0', // I don't think this is used, b/c we don't have any droppable fields in list blocks
|
||||
tertiary: '#E64D00',
|
||||
quaternary: '#FFDDCC'
|
||||
},
|
||||
more: {
|
||||
primary: '#FF99AA',
|
||||
secondary: '#FFCCD5',
|
||||
tertiary: '#FF3355',
|
||||
quaternary: '#FFE5EA'
|
||||
},
|
||||
// For productionizing: we should look into making this field be the color of the text on the blocks
|
||||
// e.g. move and steps in move (10) steps, and rename this property below for controlling the text inside
|
||||
// of inputs e.g. 10
|
||||
text: '#000000', // Text inside of inputs e.g. 90 in [point in direction (90)]
|
||||
|
||||
toolboxText: '#000000', // Toolbox text, color picker text (used to be #575E75)
|
||||
// The color that the category menu label (e.g. 'motion', 'looks', etc.) changes to on hover
|
||||
toolboxHover: '#3373CC',
|
||||
insertionMarker: '#000000',
|
||||
insertionMarkerOpacity: 0.2,
|
||||
fieldShadow: 'rgba(255, 255, 255, 0.3)',
|
||||
dragShadowOpacity: 0.6
|
||||
};
|
||||
|
||||
export default blockColors;
|
||||
@@ -0,0 +1,31 @@
|
||||
import defaultsDeep from 'lodash.defaultsdeep';
|
||||
|
||||
import darkMode from './dark-mode';
|
||||
import highContrast from './high-contrast';
|
||||
import defaultColors from './default-colors';
|
||||
|
||||
const mergeWithDefaults = colors => defaultsDeep({}, colors, defaultColors);
|
||||
|
||||
const themeMap = {
|
||||
'dark-mode': mergeWithDefaults(darkMode),
|
||||
'high-contrast': mergeWithDefaults(highContrast),
|
||||
'standard': defaultColors
|
||||
};
|
||||
|
||||
const getColorsForTheme = theme => {
|
||||
const colors = themeMap[theme];
|
||||
|
||||
if (!colors) {
|
||||
throw new Error(`Undefined theme ${theme}`);
|
||||
}
|
||||
|
||||
return colors;
|
||||
};
|
||||
|
||||
const themes = Object.keys(themeMap);
|
||||
|
||||
export {
|
||||
defaultColors,
|
||||
getColorsForTheme,
|
||||
themes
|
||||
};
|
||||
@@ -21,6 +21,7 @@ import fontsLoadedReducer, {fontsLoadedInitialState} from './fonts-loaded';
|
||||
import restoreDeletionReducer, {restoreDeletionInitialState} from './restore-deletion';
|
||||
import stageSizeReducer, {stageSizeInitialState} from './stage-size';
|
||||
import targetReducer, {targetsInitialState} from './targets';
|
||||
import themeReducer, {themeInitialState} from './theme';
|
||||
import timeoutReducer, {timeoutInitialState} from './timeout';
|
||||
import toolboxReducer, {toolboxInitialState} from './toolbox';
|
||||
import vmReducer, {vmInitialState} from './vm';
|
||||
@@ -55,6 +56,7 @@ const guiInitialState = {
|
||||
fontsLoaded: fontsLoadedInitialState,
|
||||
restoreDeletion: restoreDeletionInitialState,
|
||||
targets: targetsInitialState,
|
||||
theme: themeInitialState,
|
||||
timeout: timeoutInitialState,
|
||||
toolbox: toolboxInitialState,
|
||||
vm: vmInitialState,
|
||||
@@ -154,6 +156,7 @@ const guiReducer = combineReducers({
|
||||
fontsLoaded: fontsLoadedReducer,
|
||||
restoreDeletion: restoreDeletionReducer,
|
||||
targets: targetReducer,
|
||||
theme: themeReducer,
|
||||
timeout: timeoutReducer,
|
||||
toolbox: toolboxReducer,
|
||||
vm: vmReducer,
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
const SET_THEME = 'scratch-gui/theme/SET_THEME';
|
||||
|
||||
const initialState = {
|
||||
theme: 'standard'
|
||||
};
|
||||
|
||||
const reducer = (state = initialState, action) => {
|
||||
switch (action.type) {
|
||||
case SET_THEME:
|
||||
return {...state, theme: action.theme};
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
};
|
||||
|
||||
const setTheme = theme => ({
|
||||
type: SET_THEME,
|
||||
theme
|
||||
});
|
||||
|
||||
export {
|
||||
reducer as default,
|
||||
initialState as themeInitialState,
|
||||
setTheme
|
||||
};
|
||||
@@ -0,0 +1,22 @@
|
||||
import {defaultColors, getColorsForTheme} from '../../../src/lib/themes';
|
||||
|
||||
jest.mock('../../../src/lib/themes/default-colors');
|
||||
jest.mock('../../../src/lib/themes/dark-mode');
|
||||
|
||||
describe('themes', () => {
|
||||
test('provides the default theme colors', () => {
|
||||
expect(defaultColors.motion.primary).toEqual('#111111');
|
||||
});
|
||||
|
||||
test('returns the dark mode', () => {
|
||||
const colors = getColorsForTheme('dark-mode');
|
||||
|
||||
expect(colors.motion.primary).toEqual('#AAAAAA');
|
||||
});
|
||||
|
||||
test('uses default theme colors when not specified', () => {
|
||||
const colors = getColorsForTheme('dark-mode');
|
||||
|
||||
expect(colors.motion.secondary).toEqual('#222222');
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user