Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
"@ant-design/icons": "^6.0.0",
"@ant-design/v5-patch-for-react-19": "^1.0.3",
"@blockly/theme-dark": "^8.0.1",
"@blockly/theme-deuteranopia": "7.0.1",
"@blockly/theme-tritanopia": "7.0.1",
"@blockly/theme-highcontrast": "7.0.1",
"@tailwindcss/postcss": "^4.1.10",
"@types/react": "^19.0.2",
"@types/react-dom": "^19.0.2",
Expand Down
4 changes: 2 additions & 2 deletions src/blocks/mrc_class_method_def.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
* @author [email protected] (Alan Smith)
*/
import * as Blockly from 'blockly';
import { MRC_STYLE_CLASS_BLOCKS } from '../themes/styles';
import { MRC_STYLE_FUNCTIONS } from '../themes/styles';
import { createFieldNonEditableText } from '../fields/FieldNonEditableText'
import { createFieldFlydown } from '../fields/field_flydown';
import { Order } from 'blockly/python';
Expand Down Expand Up @@ -88,7 +88,7 @@ const CLASS_METHOD_DEF = {
this.appendDummyInput("TITLE")
.appendField('', 'NAME');
this.setOutput(false);
this.setStyle(MRC_STYLE_CLASS_BLOCKS);
this.setStyle(MRC_STYLE_FUNCTIONS);
this.appendStatementInput('STACK').appendField('');
this.mrcParameters = [];
this.setPreviousStatement(false);
Expand Down
18 changes: 9 additions & 9 deletions src/reactComponents/BlocklyComponent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,7 @@
import * as React from 'react';
import * as Blockly from 'blockly/core';
import * as locale from 'blockly/msg/en';
import * as MrcDarkTheme from '../themes/mrc_theme_dark';
import * as MrcLightTheme from '../themes/mrc_theme_light';
import { themes } from '../themes/mrc_themes';
import {pluginInfo as HardwareConnectionsPluginInfo} from '../blocks/utils/connection_checker';

import 'blockly/blocks'; // Includes standard blocks like controls_if, logic_compare, etc.
Expand Down Expand Up @@ -80,14 +79,15 @@ const BlocklyComponent = React.forwardRef<BlocklyComponentType | null, BlocklyCo
const workspaceRef = React.useRef<Blockly.WorkspaceSvg | null>(null);

const getBlocklyTheme = (): Blockly.Theme => {
if (theme === 'dark' || theme === 'compact-dark') {
return MrcDarkTheme.theme;
const blocklyTheme = 'mrc_theme_' + theme.replace(/-/g, '_');
// Find the theme by key
const themeObj = themes.find(t => t.name === blocklyTheme);
if (!themeObj) {
throw new Error(`Theme not found: ${blocklyTheme}`);
}
if (theme === 'light' || theme === 'compact') {
return MrcLightTheme.theme;
}
// Default to light theme if unknown
return MrcLightTheme.theme;

// Return the corresponding Blockly theme
return themeObj;
};

/** Creates the Blockly workspace configuration object. */
Expand Down
16 changes: 6 additions & 10 deletions src/reactComponents/CodeDisplay.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,16 +55,12 @@ const COPY_ERROR_MESSAGE_PREFIX = 'Could not copy code: ';
*/
export default function CodeDisplay(props: CodeDisplayProps): React.JSX.Element {
const syntaxHighligherFromTheme = (theme: string) => {
switch (theme) {
case 'dark':
case 'compact-dark':
return dracula;
case 'light':
case 'compact':
return oneLight;
default:
return dracula; // Default to dracula if theme is unknown
const isDarkTheme = theme.endsWith('-dark') || theme === 'dark';

if (isDarkTheme){
return dracula
}
return oneLight
}

const { token } = Antd.theme.useToken();
Expand Down Expand Up @@ -122,4 +118,4 @@ export default function CodeDisplay(props: CodeDisplayProps): React.JSX.Element
{renderCodeBlock()}
</Antd.Flex>
);
}
}
42 changes: 28 additions & 14 deletions src/reactComponents/ThemeModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import {
CheckOutlined,
MoonOutlined,
SunOutlined,
DesktopOutlined,
} from '@ant-design/icons';

export interface ThemeOption {
Expand Down Expand Up @@ -40,16 +39,28 @@ const THEME_OPTIONS: ThemeOption[] = [
description: 'Easy on the eyes for low-light environments',
},
{
key: 'compact',
name: 'Compact Theme',
icon: <DesktopOutlined />,
description: 'More content in less space',
key: 'tritanopia',
name: 'Tritanopia Theme',
icon: <SunOutlined />,
description: 'Designed for those with Tritanopia color blindness',
},
{
key: 'tritanopia-dark',
name: 'Tritanopia Dark',
icon: <MoonOutlined />,
description: 'Dark theme for those with Tritanopia color blindness',
},
{
key: 'deuteranopia',
name: 'Deuteranopia Theme',
icon: <SunOutlined />,
description: 'Designed for those with Deuteranopia color blindness',
},
{
key: 'compact-dark',
name: 'Compact Dark',
icon: <BgColorsOutlined />,
description: 'Dark theme with compact layout',
key: 'deuteranopia-dark',
name: 'Deuteranopia Dark',
icon: <MoonOutlined />,
description: 'Dark theme for those with Deuteranopia color blindness',
},
];

Expand Down Expand Up @@ -195,15 +206,16 @@ export default ThemeModal;

export const antdThemeFromString = (theme: string): Antd.ThemeConfig => {
let compact = false;

if (theme == 'compact-dark') {
compact = true;
theme = 'dark';
}
else if (theme == 'compact') {
compact = true;
theme = 'light';
}
if (theme === 'dark') {
const isDarkTheme = theme.endsWith('-dark') || theme === 'dark';

if (isDarkTheme) {
return {
algorithm: compact ? [Antd.theme.darkAlgorithm, Antd.theme.compactAlgorithm] : Antd.theme.darkAlgorithm,
components: {
Expand All @@ -219,7 +231,7 @@ export const antdThemeFromString = (theme: string): Antd.ThemeConfig => {
}
}
}
else if (theme === 'light') {
else {
return {
algorithm: compact ? [Antd.theme.defaultAlgorithm, Antd.theme.compactAlgorithm] : Antd.theme.defaultAlgorithm,
components: {
Expand All @@ -230,10 +242,12 @@ export const antdThemeFromString = (theme: string): Antd.ThemeConfig => {
triggerColor: '#000000',
},
Menu: {
darkItemDisabledColor: '#cccccc',
darkItemBg: '#ffffff',
darkSubMenuItemBg: '#ffffff',
darkItemColor: '#000000',
darkItemColor: '#666666',
darkItemSelectedColor: '#000000',
darkItemHoverColor: '#000000',
}
}
}
Expand Down
22 changes: 0 additions & 22 deletions src/themes/external_themes.d.ts

This file was deleted.

36 changes: 0 additions & 36 deletions src/themes/mrc_theme_dark.ts

This file was deleted.

35 changes: 0 additions & 35 deletions src/themes/mrc_theme_light.ts

This file was deleted.

54 changes: 54 additions & 0 deletions src/themes/mrc_themes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import * as Blockly from 'blockly/core';

import DeuteranopiaTheme from '@blockly/theme-deuteranopia';
import TritanopiaTheme from '@blockly/theme-tritanopia';
import HighContrastTheme from '@blockly/theme-highcontrast';

import { add_mrc_styles } from './styles';

export const DARK_THEME_NAME = 'mrc_theme_dark';
export const LIGHT_THEME_NAME = 'mrc_theme_light';
export const DEUTERANOPIA_THEME_NAME = 'mrc_theme_deuteranopia';
export const TRITANOPIA_THEME_NAME = 'mrc_theme_tritanopia';
export const HIGHCONTRAST_THEME_NAME = 'mrc_theme_highcontrast';
export const DEUTERANOPIA_DARK_THEME_NAME = 'mrc_theme_deuteranopia_dark';
export const TRITANOPIA_DARK_THEME_NAME = 'mrc_theme_tritanopia_dark';
export const HIGHCONTRAST_DARK_THEME_NAME = 'mrc_theme_highcontrast_dark';

const create_theme = function (name: string, base: Blockly.Theme, dark: boolean = false): Blockly.Theme {
let newTheme = Blockly.Theme.defineTheme(name, {
name: name,
base: base,
});
if (dark) {
// These all come from the Blockly Dark theme plugin at
// https://github.com/google/blockly-samples/blob/master/plugins/theme-dark/src/index.ts
newTheme.setComponentStyle('workspaceBackgroundColour', '#1e1e1e');
newTheme.setComponentStyle('toolboxBackgroundColour', '#333');
newTheme.setComponentStyle('toolboxForegroundColour', '#fff');
newTheme.setComponentStyle('flyoutBackgroundColour', '#252526');
newTheme.setComponentStyle('flyoutForegroundColour', '#ccc');
newTheme.setComponentStyle('flyoutOpacity', 1);
newTheme.setComponentStyle('scrollbarColour', '#797979');
newTheme.setComponentStyle('insertionMarkerColour', '#fff');
newTheme.setComponentStyle('insertionMarkerOpacity', 0.3);
newTheme.setComponentStyle('scrollbarOpacity', 0.4);
newTheme.setComponentStyle('cursorColour', '#d0d0d0');
}
return add_mrc_styles(newTheme);
};

const create_themes = function (): Blockly.Theme[] {
return [
create_theme(DARK_THEME_NAME, Blockly.Themes.Classic, true),
create_theme(LIGHT_THEME_NAME, Blockly.Themes.Classic),
create_theme(DEUTERANOPIA_THEME_NAME, DeuteranopiaTheme),
create_theme(TRITANOPIA_THEME_NAME, TritanopiaTheme),
create_theme(HIGHCONTRAST_THEME_NAME, HighContrastTheme),
create_theme(DEUTERANOPIA_DARK_THEME_NAME, DeuteranopiaTheme, true),
create_theme(TRITANOPIA_DARK_THEME_NAME, TritanopiaTheme, true),
create_theme(HIGHCONTRAST_DARK_THEME_NAME, HighContrastTheme, true),
];
};

export const themes = create_themes();
Loading