Skip to content

Commit

Permalink
Content Model: Go back to getDarkColor (#2239)
Browse files Browse the repository at this point in the history
* Content Model: go back to getDarkColor

* fix test
  • Loading branch information
JiuqingSong authored Dec 4, 2023
1 parent 89a61d0 commit 2bee980
Show file tree
Hide file tree
Showing 6 changed files with 30 additions and 58 deletions.
2 changes: 2 additions & 0 deletions demo/scripts/controls/ContentModelEditorMainPane.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { ContentModelRibbonPlugin } from './ribbonButtons/contentModel/ContentMo
import { ContentModelSegmentFormat } from 'roosterjs-content-model-types';
import { createEmojiPlugin, createPasteOptionPlugin, RibbonPlugin } from 'roosterjs-react';
import { EditorPlugin } from 'roosterjs-editor-types';
import { getDarkColor } from 'roosterjs-color-utils';
import { PartialTheme } from '@fluentui/react/lib/Theme';
import { trustedHTMLHandler } from '../utils/trustedHTMLHandler';
import {
Expand Down Expand Up @@ -236,6 +237,7 @@ class ContentModelEditorMainPane extends MainPaneBase<ContentModelMainPaneState>
plugins={allPlugins}
defaultSegmentFormat={defaultFormat}
inDarkMode={this.state.isDarkMode}
getDarkColor={getDarkColor}
experimentalFeatures={this.state.initState.experimentalFeatures}
undoMetadataSnapshotService={this.snapshotPlugin.getSnapshotService()}
trustedHTMLHandler={trustedHTMLHandler}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
import * as Color from 'color';
import { getObjectKeys, parseColor, setColor } from 'roosterjs-editor-dom';
import type {
ColorKeyAndValue,
DarkColorHandler,
ModeIndependentColor,
} from 'roosterjs-editor-types';

const DefaultLightness = 21.25; // Lightness for #333333
const VARIABLE_REGEX = /^\s*var\(\s*(\-\-[a-zA-Z0-9\-_]+)\s*(?:,\s*(.*))?\)\s*$/;
const VARIABLE_PREFIX = 'var(';
const COLOR_VAR_PREFIX = 'darkColor';
Expand All @@ -30,11 +28,8 @@ const ColorAttributeName: { [key in ColorAttributeEnum]: string }[] = [
*/
export class DarkColorHandlerImpl implements DarkColorHandler {
private knownColors: Record<string, Readonly<ModeIndependentColor>> = {};
readonly baseLightness: number;

constructor(private contentDiv: HTMLElement, baseDarkColor?: string) {
this.baseLightness = getLightness(baseDarkColor);
}
constructor(private contentDiv: HTMLElement, private getDarkColor: (color: string) => string) {}

/**
* Get a copy of known colors
Expand Down Expand Up @@ -66,7 +61,7 @@ export class DarkColorHandlerImpl implements DarkColorHandler {
colorKey || `--${COLOR_VAR_PREFIX}_${lightModeColor.replace(/[^\d\w]/g, '_')}`;

if (!this.knownColors[colorKey]) {
darkModeColor = darkModeColor || getDarkColor(lightModeColor, this.baseLightness);
darkModeColor = darkModeColor || this.getDarkColor(lightModeColor);

this.knownColors[colorKey] = { lightModeColor, darkModeColor };
this.contentDiv.style.setProperty(colorKey, darkModeColor);
Expand Down Expand Up @@ -176,30 +171,3 @@ export class DarkColorHandlerImpl implements DarkColorHandler {
});
}
}

function getDarkColor(color: string, baseLightness: number): string {
try {
const computedColor = Color(color || undefined);
const colorLab = computedColor.lab().array();
const newLValue = (100 - colorLab[0]) * ((100 - baseLightness) / 100) + baseLightness;
color = Color.lab(newLValue, colorLab[1], colorLab[2])
.rgb()
.alpha(computedColor.alpha())
.toString();
} catch {}

return color;
}

function getLightness(color?: string): number {
let result = DefaultLightness;

if (color) {
try {
const computedColor = Color(color || undefined);
result = computedColor.lab().array()[0];
} catch {}
}

return result;
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,10 @@ export function createStandaloneEditorCore(
corePlugins.lifecycle,
],
environment: createEditorEnvironment(),
darkColorHandler: new DarkColorHandlerImpl(contentDiv, options.baseDarkColor),
darkColorHandler: new DarkColorHandlerImpl(
contentDiv,
options.getDarkColor ?? getDarkColorFallback
),
trustedHTMLHandler: options.trustedHTMLHandler || defaultTrustHtmlHandler,
...createStandaloneEditorDefaultSettings(options),
...getPluginState(corePlugins),
Expand Down Expand Up @@ -82,3 +85,8 @@ function getPluginState(corePlugins: StandaloneEditorCorePlugins): StandaloneEdi
selection: corePlugins.selection.getState(),
};
}

// A fallback function, always return original color
function getDarkColorFallback(color: string) {
return color;
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
"description": "Content Model for roosterjs (Under development)",
"dependencies": {
"tslib": "^2.3.1",
"color": "^3.0.0",
"roosterjs-editor-types": "",
"roosterjs-editor-dom": "",
"roosterjs-content-model-dom": "",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,26 +1,21 @@
import { ColorKeyAndValue } from 'roosterjs-editor-types';
import { DarkColorHandlerImpl } from '../../lib/editor/DarkColorHandlerImpl';

function getDarkColor(color: string) {
return 'Dark_' + color;
}

describe('DarkColorHandlerImpl.ctor', () => {
it('No additional param', () => {
const div = document.createElement('div');
const handler = new DarkColorHandlerImpl(div);

expect(handler).toBeDefined();
expect(handler.baseLightness).toBe(21.25);
});

it('With customized base color', () => {
const div = document.createElement('div');
const handler = new DarkColorHandlerImpl(div, '#555555');
const handler = new DarkColorHandlerImpl(div, getDarkColor);

expect(handler).toBeDefined();
expect(Math.round(handler.baseLightness)).toBe(36);
});

it('Calculate color using customized base color', () => {
const div = document.createElement('div');
const handler = new DarkColorHandlerImpl(div, '#555555');
const handler = new DarkColorHandlerImpl(div, getDarkColor);

const darkColor = handler.registerColor('red', true);
const parsedColor = handler.parseColorValue(darkColor);
Expand All @@ -29,7 +24,7 @@ describe('DarkColorHandlerImpl.ctor', () => {
expect(parsedColor).toEqual({
key: '--darkColor_red',
lightModeColor: 'red',
darkModeColor: 'rgb(255, 72, 40)',
darkModeColor: 'Dark_red',
});
});
});
Expand All @@ -40,7 +35,7 @@ describe('DarkColorHandlerImpl.parseColorValue', () => {

beforeEach(() => {
div = document.createElement('div');
handler = new DarkColorHandlerImpl(div);
handler = new DarkColorHandlerImpl(div, getDarkColor);
});

function runTest(input: string, expectedOutput: ColorKeyAndValue) {
Expand Down Expand Up @@ -143,7 +138,7 @@ describe('DarkColorHandlerImpl.registerColor', () => {
setProperty,
},
} as any) as HTMLElement;
handler = new DarkColorHandlerImpl(div);
handler = new DarkColorHandlerImpl(div, getDarkColor);
});

function runTest(
Expand Down Expand Up @@ -186,10 +181,10 @@ describe('DarkColorHandlerImpl.registerColor', () => {
{
'--darkColor_red': {
lightModeColor: 'red',
darkModeColor: 'rgb(255, 39, 17)',
darkModeColor: 'Dark_red',
},
},
[['--darkColor_red', 'rgb(255, 39, 17)']]
[['--darkColor_red', 'Dark_red']]
);
});

Expand Down Expand Up @@ -222,10 +217,10 @@ describe('DarkColorHandlerImpl.registerColor', () => {
{
'--aa': {
lightModeColor: 'red',
darkModeColor: 'rgb(255, 39, 17)',
darkModeColor: 'Dark_red',
},
},
[['--aa', 'rgb(255, 39, 17)']]
[['--aa', 'Dark_red']]
);
});

Expand Down Expand Up @@ -395,7 +390,7 @@ describe('DarkColorHandlerImpl.transformElementColor', () => {

beforeEach(() => {
contentDiv = document.createElement('div');
handler = new DarkColorHandlerImpl(contentDiv);
handler = new DarkColorHandlerImpl(contentDiv, getDarkColor);

parseColorSpy = spyOn(handler, 'parseColorValue').and.callThrough();
registerColorSpy = spyOn(handler, 'registerColor').and.callThrough();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,10 @@ export interface StandaloneEditorOptions {
scrollContainer?: HTMLElement;

/**
* Base dark mode color. We will use this color to calculate the dark mode color from a given light mode color
* @default #333333
* A util function to transform light mode color to dark mode color
* Default value is to return the original light color
*/
baseDarkColor?: string;
getDarkColor?: (lightColor: string) => string;

/**
* Customized trusted type handler used for sanitizing HTML string before assign to DOM tree
Expand Down

0 comments on commit 2bee980

Please sign in to comment.