From 158ba2ce129e85c610320f33d5447c5c06d730e5 Mon Sep 17 00:00:00 2001 From: Nathan Bierema Date: Mon, 11 Dec 2023 23:02:35 -0500 Subject: [PATCH] [inspector-monitor] Replace jss with Emotion (#1560) * Setup Emotion * Fix setup * Start conversion * actionList * actionListHeader * actionListRows * actionListHeaderSelector * actionListItem * actionListItemTime * actionListItemSelector * actionListItemName * actionListHeaderSearch * actionListHeaderWrapper * actionPreview * Remaining css * Format * Propagate Emotion dependencies * Fix tests * Remove styling prop * Remove jss * Remove themeState * Use color map as Emotion theme * Rework theme resolution * Inline CSS * Remove usage of className * Fix warning * Create large-spoons-yell.md --- .changeset/large-spoons-yell.md | 8 + extension/package.json | 1 + extension/test/chrome/extension.spec.js | 10 +- extension/test/electron/devpanel.spec.js | 4 +- packages/redux-devtools-app/package.json | 2 + packages/redux-devtools-cli/package.json | 1 + .../demo/package.json | 1 + .../demo/src/DevTools.tsx | 9 +- .../package.json | 2 + .../package.json | 2 + .../.eslintrc.js | 3 + .../babel.config.esm.json | 3 +- .../babel.config.json | 3 +- .../demo/package.json | 1 + .../demo/src/DevTools.tsx | 8 +- .../package.json | 5 +- .../src/ActionList.tsx | 32 +- .../src/ActionListHeader.tsx | 51 ++- .../src/ActionListRow.tsx | 101 +++-- .../src/ActionPreview.tsx | 58 ++- .../src/ActionPreviewHeader.tsx | 65 ++- .../src/DevtoolsInspector.tsx | 185 ++++---- .../src/RightSlider.tsx | 37 +- .../src/index.ts | 3 +- .../src/tabs/ActionTab.tsx | 3 +- .../src/tabs/DiffTab.tsx | 2 - .../src/tabs/JSONDiff.tsx | 106 +++-- .../src/tabs/StateTab.tsx | 3 +- .../src/tabs/getItemString.tsx | 4 +- .../src/utils/createStylingFromTheme.ts | 394 ------------------ .../src/utils/selectorButtonStyles.ts | 39 ++ .../src/utils/themes.ts | 76 ++++ .../tsconfig.json | 4 +- pnpm-lock.yaml | 68 ++- 34 files changed, 609 insertions(+), 685 deletions(-) create mode 100644 .changeset/large-spoons-yell.md delete mode 100644 packages/redux-devtools-inspector-monitor/src/utils/createStylingFromTheme.ts create mode 100644 packages/redux-devtools-inspector-monitor/src/utils/selectorButtonStyles.ts create mode 100644 packages/redux-devtools-inspector-monitor/src/utils/themes.ts diff --git a/.changeset/large-spoons-yell.md b/.changeset/large-spoons-yell.md new file mode 100644 index 00000000..71faf692 --- /dev/null +++ b/.changeset/large-spoons-yell.md @@ -0,0 +1,8 @@ +--- +'@redux-devtools/app': major +'@redux-devtools/inspector-monitor-test-tab': major +'@redux-devtools/inspector-monitor-trace-tab': major +'@redux-devtools/inspector-monitor': major +--- + +Replace jss with Emotion in inspector-monitor. `@emotion/react` is now a required peer dependency. diff --git a/extension/package.json b/extension/package.json index 9d9a3f48..8988174b 100644 --- a/extension/package.json +++ b/extension/package.json @@ -24,6 +24,7 @@ }, "dependencies": { "@babel/polyfill": "^7.12.1", + "@emotion/react": "^11.11.1", "@redux-devtools/app": "^4.0.1", "@redux-devtools/core": "^3.13.2", "@redux-devtools/instrument": "^2.1.0", diff --git a/extension/test/chrome/extension.spec.js b/extension/test/chrome/extension.spec.js index 86fdb064..7c52fe46 100644 --- a/extension/test/chrome/extension.spec.js +++ b/extension/test/chrome/extension.spec.js @@ -40,16 +40,14 @@ describe('Chrome extension', function () { it("should contain inspector monitor's component", async () => { await delay(1000); const val = await driver - .findElement(webdriver.By.xpath('//div[contains(@class, "inspector-")]')) + .findElement(webdriver.By.xpath('//div[@data-testid="inspector"]')) .getText(); expect(val).toBeDefined(); }); it('should contain an empty actions list', async () => { const val = await driver - .findElement( - webdriver.By.xpath('//div[contains(@class, "actionListRows-")]'), - ) + .findElement(webdriver.By.xpath('//div[@data-testid="actionListRows"]')) .getText(); expect(val).toBe(''); }); @@ -72,9 +70,7 @@ describe('Chrome extension', function () { const result = await driver.wait( driver - .findElement( - webdriver.By.xpath('//div[contains(@class, "actionListRows-")]'), - ) + .findElement(webdriver.By.xpath('//div[@data-testid="actionListRows"]')) .getText() .then((val) => { return actionsPattern.test(val); diff --git a/extension/test/electron/devpanel.spec.js b/extension/test/electron/devpanel.spec.js index 94dc5065..ca59117a 100644 --- a/extension/test/electron/devpanel.spec.js +++ b/extension/test/electron/devpanel.spec.js @@ -89,7 +89,7 @@ describe('DevTools panel for Electron', function () { it('should contain INIT action', async () => { const element = await driver.wait( webdriver.until.elementLocated( - webdriver.By.xpath('//div[contains(@class, "actionListRows-")]'), + webdriver.By.xpath('//div[@data-testid="actionListRows"]'), ), 5000, 'Element not found', @@ -100,7 +100,7 @@ describe('DevTools panel for Electron', function () { it("should contain Inspector monitor's component", async () => { const val = await driver - .findElement(webdriver.By.xpath('//div[contains(@class, "inspector-")]')) + .findElement(webdriver.By.xpath('//div[@data-testid="inspector"]')) .getText(); expect(val).toBeDefined(); }); diff --git a/packages/redux-devtools-app/package.json b/packages/redux-devtools-app/package.json index 2a57f0bb..97d62dac 100644 --- a/packages/redux-devtools-app/package.json +++ b/packages/redux-devtools-app/package.json @@ -72,6 +72,7 @@ "@babel/preset-env": "^7.23.5", "@babel/preset-react": "^7.23.3", "@babel/preset-typescript": "^7.23.3", + "@emotion/react": "^11.11.1", "@rjsf/core": "^4.2.3", "@testing-library/jest-dom": "^6.1.5", "@testing-library/react": "^14.1.2", @@ -115,6 +116,7 @@ "webpack-dev-server": "^4.15.1" }, "peerDependencies": { + "@emotion/react": "^11.0.0", "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0", "@types/styled-components": "^5.1.34", "react": "^16.8.0 || ^17.0.0 || ^18.0.0", diff --git a/packages/redux-devtools-cli/package.json b/packages/redux-devtools-cli/package.json index 84fd31b1..61c48e45 100644 --- a/packages/redux-devtools-cli/package.json +++ b/packages/redux-devtools-cli/package.json @@ -42,6 +42,7 @@ }, "dependencies": { "@apollo/server": "^4.9.5", + "@emotion/react": "^11.11.1", "@redux-devtools/app": "^4.0.0", "@types/react": "^18.2.43", "body-parser": "^1.20.2", diff --git a/packages/redux-devtools-inspector-monitor-test-tab/demo/package.json b/packages/redux-devtools-inspector-monitor-test-tab/demo/package.json index 7034354f..57603c2c 100644 --- a/packages/redux-devtools-inspector-monitor-test-tab/demo/package.json +++ b/packages/redux-devtools-inspector-monitor-test-tab/demo/package.json @@ -10,6 +10,7 @@ "type-check": "tsc --noEmit" }, "dependencies": { + "@emotion/react": "^11.11.1", "@redux-devtools/core": "^3.13.2", "@redux-devtools/dock-monitor": "^3.0.2", "@redux-devtools/inspector-monitor": "^4.0.1", diff --git a/packages/redux-devtools-inspector-monitor-test-tab/demo/src/DevTools.tsx b/packages/redux-devtools-inspector-monitor-test-tab/demo/src/DevTools.tsx index 4866708b..8b68a2b6 100644 --- a/packages/redux-devtools-inspector-monitor-test-tab/demo/src/DevTools.tsx +++ b/packages/redux-devtools-inspector-monitor-test-tab/demo/src/DevTools.tsx @@ -1,10 +1,7 @@ import React from 'react'; import { createDevTools } from '@redux-devtools/core'; -import { - InspectorMonitor, - base16Themes, - Tab, -} from '@redux-devtools/inspector-monitor'; +import { InspectorMonitor, Tab } from '@redux-devtools/inspector-monitor'; +import type { Base16ThemeName } from '@redux-devtools/inspector-monitor'; import { DockMonitor } from '@redux-devtools/dock-monitor'; import { useLocation } from 'react-router-dom'; import getOptions from './getOptions'; @@ -20,7 +17,7 @@ export const getDevTools = (location: { search: string }) => changeMonitorKey="ctrl-m" > diff --git a/packages/redux-devtools-inspector-monitor-test-tab/package.json b/packages/redux-devtools-inspector-monitor-test-tab/package.json index bd1615e7..3dd3f8d0 100644 --- a/packages/redux-devtools-inspector-monitor-test-tab/package.json +++ b/packages/redux-devtools-inspector-monitor-test-tab/package.json @@ -60,6 +60,7 @@ "@babel/preset-env": "^7.23.5", "@babel/preset-react": "^7.23.3", "@babel/preset-typescript": "^7.23.3", + "@emotion/react": "^11.11.1", "@redux-devtools/core": "^3.14.0", "@redux-devtools/inspector-monitor": "^4.1.0", "@testing-library/react": "^14.1.2", @@ -85,6 +86,7 @@ "typescript": "~5.2.2" }, "peerDependencies": { + "@emotion/react": "^11.0.0", "@redux-devtools/inspector-monitor": "^4.0.0", "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0", "@types/styled-components": "^5.1.34", diff --git a/packages/redux-devtools-inspector-monitor-trace-tab/package.json b/packages/redux-devtools-inspector-monitor-trace-tab/package.json index c0942ad5..491c79cf 100644 --- a/packages/redux-devtools-inspector-monitor-trace-tab/package.json +++ b/packages/redux-devtools-inspector-monitor-trace-tab/package.json @@ -47,6 +47,7 @@ "@babel/preset-env": "^7.23.5", "@babel/preset-react": "^7.23.3", "@babel/preset-typescript": "^7.23.3", + "@emotion/react": "^11.11.1", "@redux-devtools/core": "^3.14.0", "@redux-devtools/inspector-monitor": "^4.1.0", "@testing-library/react": "^14.1.2", @@ -76,6 +77,7 @@ "typescript": "~5.2.2" }, "peerDependencies": { + "@emotion/react": "^11.0.0", "@redux-devtools/inspector-monitor": "^4.0.0", "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0", "react": "^16.8.0 || ^17.0.0 || ^18.0.0", diff --git a/packages/redux-devtools-inspector-monitor/.eslintrc.js b/packages/redux-devtools-inspector-monitor/.eslintrc.js index 0f447886..2eaf5065 100644 --- a/packages/redux-devtools-inspector-monitor/.eslintrc.js +++ b/packages/redux-devtools-inspector-monitor/.eslintrc.js @@ -8,6 +8,9 @@ module.exports = { tsconfigRootDir: __dirname, project: true, }, + rules: { + 'react/no-unknown-property': ['error', { ignore: ['css'] }], + }, }, { files: ['demo/**/*.ts', 'demo/**/*.tsx'], diff --git a/packages/redux-devtools-inspector-monitor/babel.config.esm.json b/packages/redux-devtools-inspector-monitor/babel.config.esm.json index d616aff2..df022b0e 100644 --- a/packages/redux-devtools-inspector-monitor/babel.config.esm.json +++ b/packages/redux-devtools-inspector-monitor/babel.config.esm.json @@ -2,7 +2,8 @@ "presets": [ ["@babel/preset-env", { "targets": "defaults", "modules": false }], "@babel/preset-react", - "@babel/preset-typescript" + "@babel/preset-typescript", + "@emotion/babel-preset-css-prop" ], "plugins": ["@babel/plugin-transform-runtime"] } diff --git a/packages/redux-devtools-inspector-monitor/babel.config.json b/packages/redux-devtools-inspector-monitor/babel.config.json index 814fca2b..053337b2 100644 --- a/packages/redux-devtools-inspector-monitor/babel.config.json +++ b/packages/redux-devtools-inspector-monitor/babel.config.json @@ -2,7 +2,8 @@ "presets": [ ["@babel/preset-env", { "targets": "defaults" }], "@babel/preset-react", - "@babel/preset-typescript" + "@babel/preset-typescript", + "@emotion/babel-preset-css-prop" ], "plugins": ["@babel/plugin-transform-runtime"] } diff --git a/packages/redux-devtools-inspector-monitor/demo/package.json b/packages/redux-devtools-inspector-monitor/demo/package.json index 681d3479..d570fc09 100644 --- a/packages/redux-devtools-inspector-monitor/demo/package.json +++ b/packages/redux-devtools-inspector-monitor/demo/package.json @@ -10,6 +10,7 @@ "type-check": "tsc --noEmit" }, "dependencies": { + "@emotion/react": "^11.11.1", "@redux-devtools/core": "^3.13.0", "@redux-devtools/dock-monitor": "^3.0.0", "@redux-devtools/inspector-monitor": "^4.0.0", diff --git a/packages/redux-devtools-inspector-monitor/demo/src/DevTools.tsx b/packages/redux-devtools-inspector-monitor/demo/src/DevTools.tsx index 4cdd6079..38d248e8 100644 --- a/packages/redux-devtools-inspector-monitor/demo/src/DevTools.tsx +++ b/packages/redux-devtools-inspector-monitor/demo/src/DevTools.tsx @@ -1,10 +1,8 @@ import React from 'react'; import { createDevTools } from '@redux-devtools/core'; import { DockMonitor } from '@redux-devtools/dock-monitor'; -import { - InspectorMonitor, - base16Themes, -} from '@redux-devtools/inspector-monitor'; +import { InspectorMonitor } from '@redux-devtools/inspector-monitor'; +import type { Base16ThemeName } from '@redux-devtools/inspector-monitor'; import { useLocation } from 'react-router-dom'; import getOptions from './getOptions'; @@ -32,7 +30,7 @@ export const getDevTools = (location: { search: string }) => changeMonitorKey="ctrl-m" > [ diff --git a/packages/redux-devtools-inspector-monitor/package.json b/packages/redux-devtools-inspector-monitor/package.json index b0c9bda9..558849d6 100644 --- a/packages/redux-devtools-inspector-monitor/package.json +++ b/packages/redux-devtools-inspector-monitor/package.json @@ -47,8 +47,6 @@ "immutable": "^4.3.4", "javascript-stringify": "^2.1.0", "jsondiffpatch": "^0.5.0", - "jss": "^10.10.0", - "jss-preset-default": "^10.10.0", "lodash.debounce": "^4.0.8", "react-base16-styling": "^0.9.1", "react-json-tree": "^0.18.0", @@ -62,6 +60,8 @@ "@babel/preset-env": "^7.23.5", "@babel/preset-react": "^7.23.3", "@babel/preset-typescript": "^7.23.3", + "@emotion/babel-preset-css-prop": "^11.11.0", + "@emotion/react": "^11.11.1", "@redux-devtools/core": "^3.14.0", "@types/dateformat": "^5.0.2", "@types/hex-rgba": "^1.0.3", @@ -80,6 +80,7 @@ "typescript": "~5.2.2" }, "peerDependencies": { + "@emotion/react": "^11.0.0", "@redux-devtools/core": "^3.0.0", "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0", "react": "^16.8.0 || ^17.0.0 || ^18.0.0", diff --git a/packages/redux-devtools-inspector-monitor/src/ActionList.tsx b/packages/redux-devtools-inspector-monitor/src/ActionList.tsx index d745d5d5..05485674 100644 --- a/packages/redux-devtools-inspector-monitor/src/ActionList.tsx +++ b/packages/redux-devtools-inspector-monitor/src/ActionList.tsx @@ -1,7 +1,6 @@ import React, { ReactNode, useCallback, useLayoutEffect, useRef } from 'react'; import { Action } from 'redux'; import { PerformAction } from '@redux-devtools/core'; -import { StylingFunction } from 'react-base16-styling'; import { closestCenter, DndContext, @@ -51,7 +50,6 @@ interface Props> { draggableActions: boolean; hideMainButtons: boolean | undefined; hideActionButtons: boolean | undefined; - styling: StylingFunction; onSearch: (value: string) => void; onSelect: (e: React.MouseEvent, actionId: number) => void; onToggleAction: (actionId: number) => void; @@ -64,7 +62,6 @@ interface Props> { } export default function ActionList>({ - styling, actions, actionIds, isWideLayout, @@ -150,13 +147,29 @@ export default function ActionList>({
({ + flexBasis: '40%', + flexShrink: 0, + overflowX: 'hidden', + overflowY: 'auto', + borderBottomWidth: '3px', + borderBottomStyle: 'double', + display: 'flex', + flexDirection: 'column', + + backgroundColor: theme.BACKGROUND_COLOR, + borderColor: theme.LIST_BORDER_COLOR, + }), + isWideLayout && { + flexBasis: '40%', + borderBottom: 'none', + borderRightWidth: '3px', + borderRightStyle: 'double', + }, + ]} > >({ />
>({ {filteredActionIds.map((actionId) => ( [hasSkippedActions && 'Sweep', 'Commit'].filter( @@ -8,7 +11,6 @@ const getActiveButtons = (hasSkippedActions: boolean): ('Sweep' | 'Commit')[] => ); interface Props { - styling: StylingFunction; onSearch: (value: string) => void; onCommit: () => void; onSweep: () => void; @@ -19,7 +21,6 @@ interface Props { } const ActionListHeader: FunctionComponent = ({ - styling, onSearch, hasSkippedActions, hasStagedActions, @@ -28,17 +29,45 @@ const ActionListHeader: FunctionComponent = ({ hideMainButtons, searchValue, }) => ( -
+
({ + display: 'flex', + flex: '0 0 auto', + alignItems: 'center', + borderBottomWidth: '1px', + borderBottomStyle: 'solid', + + borderColor: theme.LIST_BORDER_COLOR, + })} + > ({ + outline: 'none', + border: 'none', + width: '100%', + padding: '5px 10px', + fontSize: '1em', + fontFamily: 'monaco, Consolas, "Lucida Console", monospace', + + backgroundColor: theme.BACKGROUND_COLOR, + color: theme.TEXT_COLOR, + + '&::-webkit-input-placeholder': { + color: theme.TEXT_PLACEHOLDER_COLOR, + }, + + '&::-moz-placeholder': { + color: theme.TEXT_PLACEHOLDER_COLOR, + }, + })} onChange={(e) => onSearch(e.target.value)} placeholder="filter..." value={searchValue} /> {!hideMainButtons && ( -
- -
+
+ +
{getActiveButtons(hasSkippedActions).map((btn) => (
= ({ Sweep: onSweep, })[btn]() } - {...styling( - ['selectorButton', 'selectorButtonSmall'], - false, - true, - )} + css={[selectorButtonCss, selectorButtonSmallCss]} > {btn}
diff --git a/packages/redux-devtools-inspector-monitor/src/ActionListRow.tsx b/packages/redux-devtools-inspector-monitor/src/ActionListRow.tsx index a694a36d..3080bc54 100644 --- a/packages/redux-devtools-inspector-monitor/src/ActionListRow.tsx +++ b/packages/redux-devtools-inspector-monitor/src/ActionListRow.tsx @@ -2,17 +2,33 @@ import React, { MouseEvent, MouseEventHandler, PureComponent } from 'react'; import dateformat from 'dateformat'; import type { DebouncedFunc } from 'lodash'; import debounce from 'lodash.debounce'; -import { StylingFunction } from 'react-base16-styling'; import { Action } from 'redux'; +import type { Interpolation, Theme } from '@emotion/react'; import RightSlider from './RightSlider'; +import { + selectorButtonCss, + selectorButtonSelectedCss, + selectorButtonSmallCss, +} from './utils/selectorButtonStyles'; const BUTTON_SKIP = 'Skip'; const BUTTON_JUMP = 'Jump'; type Button = typeof BUTTON_SKIP | typeof BUTTON_JUMP; +const actionListItemTimeCss: Interpolation = (theme) => ({ + display: 'inline', + padding: '4px 6px', + borderRadius: '3px', + fontSize: '0.8em', + lineHeight: '1em', + flexShrink: 0, + + backgroundColor: theme.ACTION_TIME_BACK_COLOR, + color: theme.ACTION_TIME_COLOR, +}); + interface Props> { - styling: StylingFunction; actionId: number; isInitAction: boolean; isSelected: boolean; @@ -38,7 +54,6 @@ export default class ActionListRow< render() { const { - styling, isSelected, action, actionId, @@ -74,28 +89,44 @@ export default class ActionListRow< onMouseDown={this.handleMouseDown} onMouseUp={this.handleMouseEnter} data-id={actionId} - {...styling( - [ - 'actionListItem', - isSelected && 'actionListItemSelected', - isSkipped && 'actionListItemSkipped', - isInFuture && 'actionListFromFuture', - ], - isSelected, - action, - )} + css={[ + (theme) => ({ + borderBottomWidth: '1px', + borderBottomStyle: 'solid', + display: 'flex', + justifyContent: 'space-between', + padding: '5px 10px', + cursor: 'pointer', + userSelect: 'none', + + borderBottomColor: theme.BORDER_COLOR, + }), + isSelected && + ((theme) => ({ + backgroundColor: theme.SELECTED_BACKGROUND_COLOR, + })), + isSkipped && + ((theme) => ({ + backgroundColor: theme.SKIPPED_BACKGROUND_COLOR, + })), + isInFuture && { opacity: '0.6' }, + ]} >
{actionType}
{hideActionButtons ? ( - -
+ +
{timeDelta === 0 ? '+00:00:00' : dateformat( @@ -105,9 +136,9 @@ export default class ActionListRow<
) : ( -
- -
+
+ +
{timeDelta === 0 ? '+00:00:00' : dateformat( @@ -116,23 +147,20 @@ export default class ActionListRow< )}
- -
+ +
{([BUTTON_JUMP, BUTTON_SKIP] as const).map( (btn) => (!isInitAction || btn !== BUTTON_SKIP) && (
this.handleButtonClick(btn, e)} - {...styling( - [ - 'selectorButton', - isButtonSelected(btn) && 'selectorButtonSelected', - 'selectorButtonSmall', - ], - isButtonSelected(btn), - true, - )} + css={[ + selectorButtonCss, + isButtonSelected(btn) && selectorButtonSelectedCss, + selectorButtonSmallCss, + ]} + data-isselectorbutton={true} > {btn}
@@ -177,12 +205,7 @@ export default class ActionListRow< }, 100); handleMouseDown = (e: MouseEvent) => { - if ( - (e.target as unknown as { className: string[] }).className.indexOf( - 'selectorButton', - ) === 0 - ) - return; + if ((e.target as HTMLElement).dataset.isselectorbutton) return; this.handleMouseLeave(); }; } diff --git a/packages/redux-devtools-inspector-monitor/src/ActionPreview.tsx b/packages/redux-devtools-inspector-monitor/src/ActionPreview.tsx index 40bfa36d..c1863d03 100644 --- a/packages/redux-devtools-inspector-monitor/src/ActionPreview.tsx +++ b/packages/redux-devtools-inspector-monitor/src/ActionPreview.tsx @@ -1,7 +1,6 @@ import React, { Component } from 'react'; import { Base16Theme } from 'redux-devtools-themes'; import { Action } from 'redux'; -import type { StylingFunction } from 'react-base16-styling'; import type { LabelRenderer } from 'react-json-tree'; import { PerformAction } from '@redux-devtools/core'; import { Delta } from 'jsondiffpatch'; @@ -13,7 +12,6 @@ import ActionTab from './tabs/ActionTab'; export interface TabComponentProps> { labelRenderer: LabelRenderer; - styling: StylingFunction; computedStates: { state: S; error?: string }[]; actions: { [actionId: number]: PerformAction
}; selectedActionId: number | null; @@ -68,7 +66,6 @@ interface Props> { dataTypeKey: string | symbol | undefined; monitorState: DevtoolsInspectorState; updateMonitorState: (monitorState: Partial) => void; - styling: StylingFunction; onInspectPath: (path: (string | number)[]) => void; inspectedPath: (string | number)[]; onSelectTab: (tabName: string) => void; @@ -85,7 +82,6 @@ class ActionPreview> extends Component< render() { const { - styling, delta, error, nextState, @@ -121,17 +117,34 @@ class ActionPreview> extends Component< renderedTabs.find((tab) => tab.name === DEFAULT_STATE.tabName)!; return ( -
+
({ + flex: 1, + display: 'flex', + flexDirection: 'column', + flexGrow: 1, + overflowY: 'hidden', + + '& pre': { + border: 'inherit', + borderRadius: '3px', + lineHeight: 'inherit', + color: 'inherit', + }, + + backgroundColor: theme.BACKGROUND_COLOR, + })} + > >[]} - {...{ styling, inspectedPath, onInspectPath, tabName, onSelectTab }} + {...{ inspectedPath, onInspectPath, tabName, onSelectTab }} /> {!error && ( -
+
> extends Component< />
)} - {error &&
{error}
} + {error && ( +
({ + padding: '10px', + marginLeft: '14px', + fontWeight: 'bold', + + color: theme.ERROR_COLOR, + })} + > + {error} +
+ )}
); } labelRenderer: LabelRenderer = ([key, ...rest], nodeType, expanded) => { - const { styling, onInspectPath, inspectedPath } = this.props; + const { onInspectPath, inspectedPath } = this.props; return ( - {key} + {key} ({ + fontSize: '0.7em', + paddingLeft: '5px', + cursor: 'pointer', + '&:hover': { + textDecoration: 'underline', + }, + + color: theme.PIN_COLOR, + })} onClick={() => onInspectPath([ ...inspectedPath.slice(0, inspectedPath.length - 1), diff --git a/packages/redux-devtools-inspector-monitor/src/ActionPreviewHeader.tsx b/packages/redux-devtools-inspector-monitor/src/ActionPreviewHeader.tsx index 3a810b7a..385b1495 100644 --- a/packages/redux-devtools-inspector-monitor/src/ActionPreviewHeader.tsx +++ b/packages/redux-devtools-inspector-monitor/src/ActionPreviewHeader.tsx @@ -1,11 +1,30 @@ import React, { FunctionComponent } from 'react'; import { Action } from 'redux'; -import { StylingFunction } from 'react-base16-styling'; +import { css } from '@emotion/react'; +import type { Interpolation, Theme } from '@emotion/react'; import { Tab } from './ActionPreview'; +import { + selectorButtonCss, + selectorButtonSelectedCss, +} from './utils/selectorButtonStyles'; + +const inspectedPathKeyCss = css({ + '&:not(:last-child):after': { + content: '" > "', + }, +}); + +const inspectedPathKeyLinkCss: Interpolation = (theme) => ({ + cursor: 'pointer', + color: theme.LINK_COLOR, + '&:hover': { + textDecoration: 'underline', + color: theme.LINK_HOVER_COLOR, + }, +}); interface Props> { tabs: Tab[]; - styling: StylingFunction; inspectedPath: (string | number)[]; onInspectPath: (path: (string | number)[]) => void; tabName: string; @@ -14,32 +33,38 @@ interface Props> { const ActionPreviewHeader: FunctionComponent< Props> -> = ({ styling, inspectedPath, onInspectPath, tabName, onSelectTab, tabs }) => ( -
-
+> = ({ inspectedPath, onInspectPath, tabName, onSelectTab, tabs }) => ( +
({ + flex: '0 0 30px', + padding: '5px 10px', + alignItems: 'center', + borderBottomWidth: '1px', + borderBottomStyle: 'solid', + + backgroundColor: theme.HEADER_BACKGROUND_COLOR, + borderBottomColor: theme.HEADER_BORDER_COLOR, + })} + > +
{tabs.map((tab) => (
onSelectTab(tab.name)} key={tab.name} - {...styling( - [ - 'selectorButton', - tab.name === tabName && 'selectorButtonSelected', - ], - tab.name === tabName, - )} + css={[ + selectorButtonCss, + tab.name === tabName && selectorButtonSelectedCss, + ]} > {tab.name}
))}
-
+
{inspectedPath.length ? ( - - onInspectPath([])} - {...styling('inspectedPathKeyLink')} - > + + onInspectPath([])} css={inspectedPathKeyLinkCss}> {tabName} @@ -50,10 +75,10 @@ const ActionPreviewHeader: FunctionComponent< idx === inspectedPath.length - 1 ? ( {key} ) : ( - + onInspectPath(inspectedPath.slice(0, idx + 1))} - {...styling('inspectedPathKeyLink')} + css={inspectedPathKeyLinkCss} > {key} diff --git a/packages/redux-devtools-inspector-monitor/src/DevtoolsInspector.tsx b/packages/redux-devtools-inspector-monitor/src/DevtoolsInspector.tsx index ff03ae80..7e788c21 100644 --- a/packages/redux-devtools-inspector-monitor/src/DevtoolsInspector.tsx +++ b/packages/redux-devtools-inspector-monitor/src/DevtoolsInspector.tsx @@ -1,10 +1,5 @@ import React, { PureComponent } from 'react'; import { Base16Theme } from 'redux-devtools-themes'; -import { - getBase16Theme, - invertTheme, - StylingFunction, -} from 'react-base16-styling'; import { ActionCreators, LiftedAction, @@ -13,9 +8,10 @@ import { import { Action, Dispatch } from 'redux'; import { Delta, DiffContext } from 'jsondiffpatch'; import { - createStylingFromTheme, - base16Themes, -} from './utils/createStylingFromTheme'; + createInspectorMonitorThemeFromBase16Theme, + resolveBase16Theme, +} from './utils/themes'; +import type { Base16ThemeName } from './utils/themes'; import ActionList from './ActionList'; import ActionPreview, { Tab } from './ActionPreview'; import getInspectedState from './utils/getInspectedState'; @@ -26,6 +22,7 @@ import { reducer, updateMonitorState, } from './redux'; +import { ThemeProvider } from '@emotion/react'; const { // eslint-disable-next-line @typescript-eslint/unbound-method @@ -125,17 +122,6 @@ function createIntermediateState>( }; } -function createThemeState>( - props: DevtoolsInspectorProps, -) { - const base16Theme = getBase16Theme(props.theme, base16Themes)!; - - const theme = props.invertTheme ? invertTheme(props.theme) : props.theme; - const styling = createStylingFromTheme(theme); - - return { base16Theme, styling }; -} - export interface ExternalProps> { dispatch: Dispatch< DevtoolsInspectorAction | LiftedAction @@ -143,7 +129,7 @@ export interface ExternalProps> { preserveScrollTop?: boolean; draggableActions: boolean; select: (state: S) => unknown; - theme: keyof typeof base16Themes | Base16Theme; + theme: Base16ThemeName | Base16Theme; supportImmutable: boolean; diffObjectHash?: (item: unknown, index: number) => string; diffPropertyFilter?: (name: string, context: DiffContext) => boolean; @@ -160,7 +146,7 @@ interface DefaultProps { select: (state: unknown) => unknown; supportImmutable: boolean; draggableActions: boolean; - theme: keyof typeof base16Themes; + theme: Base16ThemeName; invertTheme: boolean; } @@ -172,7 +158,7 @@ export interface DevtoolsInspectorProps> preserveScrollTop?: boolean; draggableActions: boolean; select: (state: S) => unknown; - theme: keyof typeof base16Themes | Base16Theme; + theme: Base16ThemeName | Base16Theme; supportImmutable: boolean; diffObjectHash?: (item: unknown, index: number) => string; diffPropertyFilter?: (name: string, context: DiffContext) => boolean; @@ -191,7 +177,6 @@ interface State> { action: A; error: string | undefined; isWideLayout: boolean; - themeState: { base16Theme: Base16Theme; styling: StylingFunction }; } class DevtoolsInspector> extends PureComponent< @@ -201,7 +186,6 @@ class DevtoolsInspector> extends PureComponent< state: State = { ...createIntermediateState(this.props, this.props.monitorState), isWideLayout: false, - themeState: createThemeState(this.props), }; static update = reducer; @@ -257,13 +241,6 @@ class DevtoolsInspector> extends PureComponent< ) { this.setState(createIntermediateState(nextProps, nextMonitorState)); } - - if ( - this.props.theme !== nextProps.theme || - this.props.invertTheme !== nextProps.invertTheme - ) { - this.setState({ themeState: createThemeState(nextProps) }); - } } inspectorCreateRef: React.RefCallback = (node) => { @@ -277,6 +254,7 @@ class DevtoolsInspector> extends PureComponent< computedStates, draggableActions, tabs, + theme, invertTheme, skippedActionIds, currentStateIndex, @@ -291,73 +269,88 @@ class DevtoolsInspector> extends PureComponent< monitorState; const inspectedPathType = tabName === 'Action' ? 'inspectedActionPath' : 'inspectedStatePath'; - const { themeState, isWideLayout, action, nextState, delta, error } = - this.state; - const { base16Theme, styling } = themeState; + const { isWideLayout, action, nextState, delta, error } = this.state; + const base16Theme = resolveBase16Theme(theme)!; + const inspectorMonitorTheme = createInspectorMonitorThemeFromBase16Theme( + base16Theme, + invertTheme, + ); return ( -
- - - this.handleInspectPath(inspectedPathType, path) - } - inspectedPath={monitorState[inspectedPathType]} - onSelectTab={this.handleSelectTab} - /> -
+ +
({ + display: 'flex', + flexDirection: 'column', + width: '100%', + height: '100%', + fontFamily: 'monaco, Consolas, "Lucida Console", monospace', + fontSize: '12px', + WebkitFontSmoothing: 'antialiased', + lineHeight: '1.5em', + + backgroundColor: theme.BACKGROUND_COLOR, + color: theme.TEXT_COLOR, + }), + isWideLayout && { flexDirection: 'row' }, + ]} + > + + + this.handleInspectPath(inspectedPathType, path) + } + inspectedPath={monitorState[inspectedPathType]} + onSelectTab={this.handleSelectTab} + /> +
+
); } diff --git a/packages/redux-devtools-inspector-monitor/src/RightSlider.tsx b/packages/redux-devtools-inspector-monitor/src/RightSlider.tsx index 261f9c34..799698a3 100644 --- a/packages/redux-devtools-inspector-monitor/src/RightSlider.tsx +++ b/packages/redux-devtools-inspector-monitor/src/RightSlider.tsx @@ -1,26 +1,35 @@ import React, { FunctionComponent } from 'react'; -import { StylingFunction } from 'react-base16-styling'; interface Props { - styling: StylingFunction; shown?: boolean; children: React.ReactNode; rotate?: boolean; } -const RightSlider: FunctionComponent = ({ - styling, - shown, - children, - rotate, -}) => ( +const RightSlider: FunctionComponent = ({ shown, children, rotate }) => (
{children}
diff --git a/packages/redux-devtools-inspector-monitor/src/index.ts b/packages/redux-devtools-inspector-monitor/src/index.ts index 12c0cc0e..e58bfb51 100644 --- a/packages/redux-devtools-inspector-monitor/src/index.ts +++ b/packages/redux-devtools-inspector-monitor/src/index.ts @@ -1,9 +1,8 @@ -export type { StylingFunction } from 'react-base16-styling'; export type { LabelRenderer } from 'react-json-tree'; export { default as InspectorMonitor } from './DevtoolsInspector'; export type { Tab, TabComponentProps } from './ActionPreview'; export type { DevtoolsInspectorState } from './redux'; -export { base16Themes } from './utils/createStylingFromTheme'; +export type { Base16ThemeName } from './utils/themes'; export * as inspectorThemes from './themes/index'; export { default as ActionTab } from './tabs/ActionTab'; export { default as DiffTab } from './tabs/DiffTab'; diff --git a/packages/redux-devtools-inspector-monitor/src/tabs/ActionTab.tsx b/packages/redux-devtools-inspector-monitor/src/tabs/ActionTab.tsx index d69a7531..94ae02dc 100644 --- a/packages/redux-devtools-inspector-monitor/src/tabs/ActionTab.tsx +++ b/packages/redux-devtools-inspector-monitor/src/tabs/ActionTab.tsx @@ -9,7 +9,6 @@ const ActionTab: FunctionComponent< TabComponentProps> > = ({ action, - styling, base16Theme, invertTheme, labelRenderer, @@ -21,7 +20,7 @@ const ActionTab: FunctionComponent< theme={getJsonTreeTheme(base16Theme)} data={action} getItemString={(type, data) => - getItemString(styling, type, data, dataTypeKey, isWideLayout) + getItemString(type, data, dataTypeKey, isWideLayout) } invertTheme={invertTheme} hideRoot diff --git a/packages/redux-devtools-inspector-monitor/src/tabs/DiffTab.tsx b/packages/redux-devtools-inspector-monitor/src/tabs/DiffTab.tsx index 6b148b14..25f1b95f 100644 --- a/packages/redux-devtools-inspector-monitor/src/tabs/DiffTab.tsx +++ b/packages/redux-devtools-inspector-monitor/src/tabs/DiffTab.tsx @@ -7,7 +7,6 @@ const DiffTab: FunctionComponent< TabComponentProps> > = ({ delta, - styling, base16Theme, invertTheme, labelRenderer, @@ -17,7 +16,6 @@ const DiffTab: FunctionComponent< = (theme) => ({ + padding: '2px 3px', + borderRadius: '3px', + position: 'relative', + + color: theme.TEXT_COLOR, +}); + +const diffWrapCss = css({ position: 'relative', zIndex: 1 }); + interface Props { delta: Delta | null | undefined | false; - styling: StylingFunction; base16Theme: Base16Theme; invertTheme: boolean; labelRenderer: LabelRenderer; @@ -82,10 +92,19 @@ export default class JSONDiff extends Component { } render() { - const { styling, base16Theme, ...props } = this.props; + const { base16Theme, ...props } = this.props; if (!this.state.data) { - return
(states are equal)
; + return ( +
({ + padding: '10px', + color: theme.TEXT_PLACEHOLDER_COLOR, + })} + > + (states are equal) +
+ ); } return ( @@ -105,7 +124,6 @@ export default class JSONDiff extends Component { getItemString = (type: string, data: any) => getItemString( - this.props.styling, type, data, this.props.dataTypeKey, @@ -114,45 +132,71 @@ export default class JSONDiff extends Component { ); valueRenderer = (raw: any, value: any) => { - const { styling, isWideLayout } = this.props; - - function renderSpan(name: string, body: string) { - return ( - - {body} - - ); - } + const { isWideLayout } = this.props; if (Array.isArray(value)) { switch (value.length) { case 1: return ( - - {renderSpan( - 'diffAdd', - stringifyAndShrink(value[0], isWideLayout), - )} + + ({ backgroundColor: theme.DIFF_ADD_COLOR }), + ]} + > + {stringifyAndShrink(value[0], isWideLayout)} + ); case 2: return ( - - {renderSpan( - 'diffUpdateFrom', - stringifyAndShrink(value[0], isWideLayout), - )} - {renderSpan('diffUpdateArrow', ' => ')} - {renderSpan( - 'diffUpdateTo', - stringifyAndShrink(value[1], isWideLayout), - )} + + ({ + textDecoration: 'line-through', + backgroundColor: theme.DIFF_REMOVE_COLOR, + }), + ]} + > + {stringifyAndShrink(value[0], isWideLayout)} + + ({ color: theme.DIFF_ARROW_COLOR })]} + > + {' => '} + + ({ backgroundColor: theme.DIFF_ADD_COLOR }), + ]} + > + {stringifyAndShrink(value[1], isWideLayout)} + ); case 3: return ( - - {renderSpan('diffRemove', stringifyAndShrink(value[0]))} + + ({ + textDecoration: 'line-through', + backgroundColor: theme.DIFF_REMOVE_COLOR, + }), + ]} + > + {stringifyAndShrink(value[0])} + ); } diff --git a/packages/redux-devtools-inspector-monitor/src/tabs/StateTab.tsx b/packages/redux-devtools-inspector-monitor/src/tabs/StateTab.tsx index 95d305d4..20137b59 100644 --- a/packages/redux-devtools-inspector-monitor/src/tabs/StateTab.tsx +++ b/packages/redux-devtools-inspector-monitor/src/tabs/StateTab.tsx @@ -9,7 +9,6 @@ const StateTab: React.FunctionComponent< TabComponentProps> > = ({ nextState, - styling, base16Theme, invertTheme, labelRenderer, @@ -23,7 +22,7 @@ const StateTab: React.FunctionComponent< theme={getJsonTreeTheme(base16Theme)} data={nextState} getItemString={(type, data) => - getItemString(styling, type, data, dataTypeKey, isWideLayout) + getItemString(type, data, dataTypeKey, isWideLayout) } invertTheme={invertTheme} hideRoot diff --git a/packages/redux-devtools-inspector-monitor/src/tabs/getItemString.tsx b/packages/redux-devtools-inspector-monitor/src/tabs/getItemString.tsx index b26880b5..2fb7f33b 100644 --- a/packages/redux-devtools-inspector-monitor/src/tabs/getItemString.tsx +++ b/packages/redux-devtools-inspector-monitor/src/tabs/getItemString.tsx @@ -1,6 +1,5 @@ import React from 'react'; import { isCollection, isIndexed, isKeyed } from 'immutable'; -import { StylingFunction } from 'react-base16-styling'; import isIterable from '../utils/isIterable'; const IS_IMMUTABLE_KEY = '@@__IS_IMMUTABLE__@@'; @@ -72,14 +71,13 @@ function getText( } const getItemString = ( - styling: StylingFunction, type: string, data: any, dataTypeKey: string | symbol | undefined, isWideLayout: boolean, isDiff?: boolean, ) => ( - + ({ color: theme.ITEM_HINT_COLOR })}> {data[IS_IMMUTABLE_KEY] ? 'Immutable' : ''} {dataTypeKey && data[dataTypeKey] ? `${data[dataTypeKey] as string} ` : ''} {getText(type, data, isWideLayout, isDiff)} diff --git a/packages/redux-devtools-inspector-monitor/src/utils/createStylingFromTheme.ts b/packages/redux-devtools-inspector-monitor/src/utils/createStylingFromTheme.ts deleted file mode 100644 index 9bd45ea3..00000000 --- a/packages/redux-devtools-inspector-monitor/src/utils/createStylingFromTheme.ts +++ /dev/null @@ -1,394 +0,0 @@ -import jss, { StyleSheet } from 'jss'; -import preset from 'jss-preset-default'; -import { createStyling, StylingFunction, Theme } from 'react-base16-styling'; -import rgba from 'hex-rgba'; -import { Base16Theme } from 'redux-devtools-themes'; -import type { CurriedFunction1 } from 'lodash'; -import inspector from '../themes/inspector'; -import * as reduxThemes from 'redux-devtools-themes'; -import * as inspectorThemes from '../themes'; - -jss.setup(preset()); - -const colorMap = (theme: Base16Theme) => ({ - TEXT_COLOR: theme.base06, - TEXT_PLACEHOLDER_COLOR: rgba(theme.base06, 60), - BACKGROUND_COLOR: theme.base00, - SELECTED_BACKGROUND_COLOR: rgba(theme.base03, 20), - SKIPPED_BACKGROUND_COLOR: rgba(theme.base03, 10), - HEADER_BACKGROUND_COLOR: rgba(theme.base03, 30), - HEADER_BORDER_COLOR: rgba(theme.base03, 20), - BORDER_COLOR: rgba(theme.base03, 50), - LIST_BORDER_COLOR: rgba(theme.base03, 50), - ACTION_TIME_BACK_COLOR: rgba(theme.base03, 20), - ACTION_TIME_COLOR: theme.base04, - PIN_COLOR: theme.base04, - ITEM_HINT_COLOR: rgba(theme.base0F, 90), - TAB_BACK_SELECTED_COLOR: rgba(theme.base03, 20), - TAB_BACK_COLOR: rgba(theme.base00, 70), - TAB_BACK_HOVER_COLOR: rgba(theme.base03, 40), - TAB_BORDER_COLOR: rgba(theme.base03, 50), - DIFF_ADD_COLOR: rgba(theme.base0B, 40), - DIFF_REMOVE_COLOR: rgba(theme.base08, 40), - DIFF_ARROW_COLOR: theme.base0E, - LINK_COLOR: rgba(theme.base0E, 90), - LINK_HOVER_COLOR: theme.base0E, - ERROR_COLOR: theme.base08, -}); - -type Color = keyof ReturnType; -type ColorMap = { - [color in Color]: string; -}; - -const getSheetFromColorMap = (map: ColorMap) => ({ - inspector: { - display: 'flex', - 'flex-direction': 'column', - width: '100%', - height: '100%', - 'font-family': 'monaco, Consolas, "Lucida Console", monospace', - 'font-size': '12px', - 'font-smoothing': 'antialiased', - 'line-height': '1.5em', - - 'background-color': map.BACKGROUND_COLOR, - color: map.TEXT_COLOR, - }, - - inspectorWide: { - 'flex-direction': 'row', - }, - - actionList: { - 'flex-basis': '40%', - 'flex-shrink': 0, - 'overflow-x': 'hidden', - 'overflow-y': 'auto', - 'border-bottom-width': '3px', - 'border-bottom-style': 'double', - display: 'flex', - 'flex-direction': 'column', - - 'background-color': map.BACKGROUND_COLOR, - 'border-color': map.LIST_BORDER_COLOR, - }, - - actionListHeader: { - display: 'flex', - flex: '0 0 auto', - 'align-items': 'center', - 'border-bottom-width': '1px', - 'border-bottom-style': 'solid', - - 'border-color': map.LIST_BORDER_COLOR, - }, - - actionListRows: { - overflow: 'auto', - }, - - actionListHeaderSelector: { - display: 'inline-flex', - 'margin-right': '10px', - }, - - actionListWide: { - 'flex-basis': '40%', - 'border-bottom': 'none', - 'border-right-width': '3px', - 'border-right-style': 'double', - }, - - actionListItem: { - 'border-bottom-width': '1px', - 'border-bottom-style': 'solid', - display: 'flex', - 'justify-content': 'space-between', - padding: '5px 10px', - cursor: 'pointer', - 'user-select': 'none', - - 'border-bottom-color': map.BORDER_COLOR, - }, - - actionListItemSelected: { - 'background-color': map.SELECTED_BACKGROUND_COLOR, - }, - - actionListItemSkipped: { - 'background-color': map.SKIPPED_BACKGROUND_COLOR, - }, - - actionListFromFuture: { - opacity: '0.6', - }, - - actionListItemButtons: { - position: 'relative', - height: '20px', - display: 'flex', - }, - - actionListItemTime: { - display: 'inline', - padding: '4px 6px', - 'border-radius': '3px', - 'font-size': '0.8em', - 'line-height': '1em', - 'flex-shrink': 0, - - 'background-color': map.ACTION_TIME_BACK_COLOR, - color: map.ACTION_TIME_COLOR, - }, - - actionListItemSelector: { - display: 'inline-flex', - }, - - actionListItemName: { - overflow: 'hidden', - 'text-overflow': 'ellipsis', - 'line-height': '20px', - }, - - actionListItemNameSkipped: { - 'text-decoration': 'line-through', - opacity: 0.3, - }, - - actionListHeaderSearch: { - outline: 'none', - border: 'none', - width: '100%', - padding: '5px 10px', - 'font-size': '1em', - 'font-family': 'monaco, Consolas, "Lucida Console", monospace', - - 'background-color': map.BACKGROUND_COLOR, - color: map.TEXT_COLOR, - - '&::-webkit-input-placeholder': { - color: map.TEXT_PLACEHOLDER_COLOR, - }, - - '&::-moz-placeholder': { - color: map.TEXT_PLACEHOLDER_COLOR, - }, - }, - - actionListHeaderWrapper: { - position: 'relative', - height: '20px', - }, - - actionPreview: { - flex: 1, - display: 'flex', - 'flex-direction': 'column', - 'flex-grow': 1, - 'overflow-y': 'hidden', - - '& pre': { - border: 'inherit', - 'border-radius': '3px', - 'line-height': 'inherit', - color: 'inherit', - }, - - 'background-color': map.BACKGROUND_COLOR, - }, - - actionPreviewContent: { - flex: 1, - 'overflow-y': 'auto', - }, - - stateDiff: { - padding: '5px 0', - }, - - stateDiffEmpty: { - padding: '10px', - - color: map.TEXT_PLACEHOLDER_COLOR, - }, - - stateError: { - padding: '10px', - 'margin-left': '14px', - 'font-weight': 'bold', - - color: map.ERROR_COLOR, - }, - - inspectedPath: { - padding: '6px 0', - }, - - inspectedPathKey: { - '&:not(:last-child):after': { - content: '" > "', - }, - }, - - inspectedPathKeyLink: { - cursor: 'pointer', - color: map.LINK_COLOR, - '&:hover': { - 'text-decoration': 'underline', - color: map.LINK_HOVER_COLOR, - }, - }, - - treeItemPin: { - 'font-size': '0.7em', - 'padding-left': '5px', - cursor: 'pointer', - '&:hover': { - 'text-decoration': 'underline', - }, - - color: map.PIN_COLOR, - }, - - treeItemHint: { - color: map.ITEM_HINT_COLOR, - }, - - previewHeader: { - flex: '0 0 30px', - padding: '5px 10px', - 'align-items': 'center', - 'border-bottom-width': '1px', - 'border-bottom-style': 'solid', - - 'background-color': map.HEADER_BACKGROUND_COLOR, - 'border-bottom-color': map.HEADER_BORDER_COLOR, - }, - - tabSelector: { - position: 'relative', - display: 'inline-flex', - float: 'right', - }, - - selectorButton: { - cursor: 'pointer', - position: 'relative', - padding: '5px 10px', - 'border-style': 'solid', - 'border-width': '1px', - 'border-left-width': 0, - - '&:first-child': { - 'border-left-width': '1px', - 'border-top-left-radius': '3px', - 'border-bottom-left-radius': '3px', - }, - - '&:last-child': { - 'border-top-right-radius': '3px', - 'border-bottom-right-radius': '3px', - }, - - 'background-color': map.TAB_BACK_COLOR, - - '&:hover': { - 'background-color': map.TAB_BACK_HOVER_COLOR, - }, - - 'border-color': map.TAB_BORDER_COLOR, - }, - - selectorButtonSmall: { - padding: '0px 8px', - 'font-size': '0.8em', - }, - - selectorButtonSelected: { - 'background-color': map.TAB_BACK_SELECTED_COLOR, - }, - - diff: { - padding: '2px 3px', - 'border-radius': '3px', - position: 'relative', - - color: map.TEXT_COLOR, - }, - - diffWrap: { - position: 'relative', - 'z-index': 1, - }, - - diffAdd: { - 'background-color': map.DIFF_ADD_COLOR, - }, - - diffRemove: { - 'text-decoration': 'line-through', - 'background-color': map.DIFF_REMOVE_COLOR, - }, - - diffUpdateFrom: { - 'text-decoration': 'line-through', - 'background-color': map.DIFF_REMOVE_COLOR, - }, - - diffUpdateTo: { - 'background-color': map.DIFF_ADD_COLOR, - }, - - diffUpdateArrow: { - color: map.DIFF_ARROW_COLOR, - }, - - rightSlider: { - 'font-smoothing': 'subpixel-antialiased', // http://stackoverflow.com/a/21136111/4218591 - position: 'absolute', - right: 0, - transform: 'translateX(150%)', - transition: 'transform 0.2s ease-in-out', - }, - - rightSliderRotate: { - transform: 'rotateX(90deg)', - transition: 'transform 0.2s ease-in-out 0.08s', - }, - - rightSliderShown: { - position: 'static', - transform: 'translateX(0)', - }, - - rightSliderRotateShown: { - transform: 'rotateX(0)', - transition: 'transform 0.2s ease-in-out 0.18s', - }, -}); - -let themeSheet: StyleSheet; - -const getDefaultThemeStyling = (theme: Base16Theme) => { - if (themeSheet) { - themeSheet.detach(); - } - - themeSheet = jss - .createStyleSheet(getSheetFromColorMap(colorMap(theme))) - .attach(); - - return themeSheet.classes; -}; - -export const base16Themes = { ...reduxThemes, ...inspectorThemes }; - -export const createStylingFromTheme: CurriedFunction1< - Theme | undefined, - StylingFunction -> = createStyling(getDefaultThemeStyling, { - defaultBase16: inspector, - base16Themes, -}); diff --git a/packages/redux-devtools-inspector-monitor/src/utils/selectorButtonStyles.ts b/packages/redux-devtools-inspector-monitor/src/utils/selectorButtonStyles.ts new file mode 100644 index 00000000..9da5188c --- /dev/null +++ b/packages/redux-devtools-inspector-monitor/src/utils/selectorButtonStyles.ts @@ -0,0 +1,39 @@ +import { css } from '@emotion/react'; +import type { Interpolation, Theme } from '@emotion/react'; + +export const selectorButtonCss: Interpolation = (theme) => ({ + cursor: 'pointer', + position: 'relative', + padding: '5px 10px', + borderStyle: 'solid', + borderWidth: '1px', + borderLeftWidth: 0, + + '&:first-of-type': { + borderLeftWidth: '1px', + borderTopLeftRadius: '3px', + borderBottomLeftRadius: '3px', + }, + + '&:last-of-type': { + borderTopRightRadius: '3px', + borderBottomRightRadius: '3px', + }, + + backgroundColor: theme.TAB_BACK_COLOR, + + '&:hover': { + backgroundColor: theme.TAB_BACK_HOVER_COLOR, + }, + + borderColor: theme.TAB_BORDER_COLOR, +}); + +export const selectorButtonSmallCss = css({ + padding: '0px 8px', + fontSize: '0.8em', +}); + +export const selectorButtonSelectedCss: Interpolation = (theme) => ({ + backgroundColor: theme.TAB_BACK_SELECTED_COLOR, +}); diff --git a/packages/redux-devtools-inspector-monitor/src/utils/themes.ts b/packages/redux-devtools-inspector-monitor/src/utils/themes.ts new file mode 100644 index 00000000..d4ce67c6 --- /dev/null +++ b/packages/redux-devtools-inspector-monitor/src/utils/themes.ts @@ -0,0 +1,76 @@ +import rgba from 'hex-rgba'; +import { Base16Theme } from 'redux-devtools-themes'; +import * as reduxThemes from 'redux-devtools-themes'; +import * as inspectorThemes from '../themes'; +import { getBase16Theme, invertBase16Theme } from 'react-base16-styling'; + +const base16Themes = { ...reduxThemes, ...inspectorThemes }; +export type Base16ThemeName = keyof typeof base16Themes; + +export function resolveBase16Theme(theme: Base16ThemeName | Base16Theme) { + return getBase16Theme(theme, base16Themes); +} + +declare module '@emotion/react' { + export interface Theme { + TEXT_COLOR: string; + TEXT_PLACEHOLDER_COLOR: string; + BACKGROUND_COLOR: string; + SELECTED_BACKGROUND_COLOR: string; + SKIPPED_BACKGROUND_COLOR: string; + HEADER_BACKGROUND_COLOR: string; + HEADER_BORDER_COLOR: string; + BORDER_COLOR: string; + LIST_BORDER_COLOR: string; + ACTION_TIME_BACK_COLOR: string; + ACTION_TIME_COLOR: string; + PIN_COLOR: string; + ITEM_HINT_COLOR: string; + TAB_BACK_SELECTED_COLOR: string; + TAB_BACK_COLOR: string; + TAB_BACK_HOVER_COLOR: string; + TAB_BORDER_COLOR: string; + DIFF_ADD_COLOR: string; + DIFF_REMOVE_COLOR: string; + DIFF_ARROW_COLOR: string; + LINK_COLOR: string; + LINK_HOVER_COLOR: string; + ERROR_COLOR: string; + } +} + +const colorMap = (theme: Base16Theme) => ({ + TEXT_COLOR: theme.base06, + TEXT_PLACEHOLDER_COLOR: rgba(theme.base06, 60), + BACKGROUND_COLOR: theme.base00, + SELECTED_BACKGROUND_COLOR: rgba(theme.base03, 20), + SKIPPED_BACKGROUND_COLOR: rgba(theme.base03, 10), + HEADER_BACKGROUND_COLOR: rgba(theme.base03, 30), + HEADER_BORDER_COLOR: rgba(theme.base03, 20), + BORDER_COLOR: rgba(theme.base03, 50), + LIST_BORDER_COLOR: rgba(theme.base03, 50), + ACTION_TIME_BACK_COLOR: rgba(theme.base03, 20), + ACTION_TIME_COLOR: theme.base04, + PIN_COLOR: theme.base04, + ITEM_HINT_COLOR: rgba(theme.base0F, 90), + TAB_BACK_SELECTED_COLOR: rgba(theme.base03, 20), + TAB_BACK_COLOR: rgba(theme.base00, 70), + TAB_BACK_HOVER_COLOR: rgba(theme.base03, 40), + TAB_BORDER_COLOR: rgba(theme.base03, 50), + DIFF_ADD_COLOR: rgba(theme.base0B, 40), + DIFF_REMOVE_COLOR: rgba(theme.base08, 40), + DIFF_ARROW_COLOR: theme.base0E, + LINK_COLOR: rgba(theme.base0E, 90), + LINK_HOVER_COLOR: theme.base0E, + ERROR_COLOR: theme.base08, +}); + +export function createInspectorMonitorThemeFromBase16Theme( + base16Theme: Base16Theme, + invertTheme: boolean, +) { + const finalBase16Theme = invertTheme + ? invertBase16Theme(base16Theme) + : base16Theme; + return colorMap(finalBase16Theme); +} diff --git a/packages/redux-devtools-inspector-monitor/tsconfig.json b/packages/redux-devtools-inspector-monitor/tsconfig.json index 67c88df5..177bc0e8 100644 --- a/packages/redux-devtools-inspector-monitor/tsconfig.json +++ b/packages/redux-devtools-inspector-monitor/tsconfig.json @@ -2,7 +2,9 @@ "extends": "../../tsconfig.react.base.json", "compilerOptions": { "outDir": "lib/types", - "resolveJsonModule": true + "resolveJsonModule": true, + "jsx": "react-jsx", + "jsxImportSource": "@emotion/react" }, "include": ["src"] } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7b4a2c34..3d1fc872 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -59,6 +59,9 @@ importers: '@babel/polyfill': specifier: ^7.12.1 version: 7.12.1 + '@emotion/react': + specifier: ^11.11.1 + version: 11.11.1(@types/react@18.2.43)(react@18.2.0) '@redux-devtools/app': specifier: ^4.0.1 version: link:../packages/redux-devtools-app @@ -1088,6 +1091,9 @@ importers: '@babel/preset-typescript': specifier: ^7.23.3 version: 7.23.3(@babel/core@7.23.5) + '@emotion/react': + specifier: ^11.11.1 + version: 11.11.1(@types/react@18.2.43)(react@18.2.0) '@rjsf/core': specifier: ^4.2.3 version: 4.2.3(react@18.2.0) @@ -1293,6 +1299,9 @@ importers: '@apollo/server': specifier: ^4.9.5 version: 4.9.5(graphql@16.8.1) + '@emotion/react': + specifier: ^11.11.1 + version: 11.11.1(@types/react@18.2.43)(react@18.2.0) '@redux-devtools/app': specifier: ^4.0.0 version: link:../redux-devtools-app @@ -1605,12 +1614,6 @@ importers: jsondiffpatch: specifier: ^0.5.0 version: 0.5.0 - jss: - specifier: ^10.10.0 - version: 10.10.0 - jss-preset-default: - specifier: ^10.10.0 - version: 10.10.0 lodash.debounce: specifier: ^4.0.8 version: 4.0.8 @@ -1648,6 +1651,12 @@ importers: '@babel/preset-typescript': specifier: ^7.23.3 version: 7.23.3(@babel/core@7.23.5) + '@emotion/babel-preset-css-prop': + specifier: ^11.11.0 + version: 11.11.0(@babel/core@7.23.5) + '@emotion/react': + specifier: ^11.11.1 + version: 11.11.1(@types/react@18.2.43)(react@18.2.0) '@redux-devtools/core': specifier: ^3.14.0 version: link:../redux-devtools @@ -1751,6 +1760,9 @@ importers: '@babel/preset-typescript': specifier: ^7.23.3 version: 7.23.3(@babel/core@7.23.5) + '@emotion/react': + specifier: ^11.11.1 + version: 11.11.1(@types/react@18.2.43)(react@18.2.0) '@redux-devtools/core': specifier: ^3.14.0 version: link:../redux-devtools @@ -1823,6 +1835,9 @@ importers: packages/redux-devtools-inspector-monitor-test-tab/demo: dependencies: + '@emotion/react': + specifier: ^11.11.1 + version: 11.11.1(@types/react@18.2.43)(react@18.2.0) '@redux-devtools/core': specifier: ^3.13.2 version: link:../../redux-devtools @@ -2002,6 +2017,9 @@ importers: '@babel/preset-typescript': specifier: ^7.23.3 version: 7.23.3(@babel/core@7.23.5) + '@emotion/react': + specifier: ^11.11.1 + version: 11.11.1(@types/react@18.2.43)(react@18.2.0) '@redux-devtools/core': specifier: ^3.14.0 version: link:../redux-devtools @@ -2086,6 +2104,9 @@ importers: packages/redux-devtools-inspector-monitor/demo: dependencies: + '@emotion/react': + specifier: ^11.11.1 + version: 11.11.1(@types/react@18.2.43)(react@18.2.0) '@redux-devtools/core': specifier: ^3.13.0 version: link:../../redux-devtools @@ -6429,6 +6450,15 @@ packages: transitivePeerDependencies: - supports-color + /@emotion/babel-plugin-jsx-pragmatic@0.2.1(@babel/core@7.23.5): + resolution: {integrity: sha512-xy1SlgEJygAAIvIuC2idkGKJYa6v5iwoyILkvNKgk347bV+IImXrUat5Z86EmLGyWhEoTplVT9EHqTnHZG4HFw==} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.23.5 + '@babel/plugin-syntax-jsx': 7.23.3(@babel/core@7.23.5) + dev: true + /@emotion/babel-plugin@11.11.0: resolution: {integrity: sha512-m4HEDZleaaCH+XgDDsPF15Ht6wTLsgDTeR3WYj9Q/k76JtWhrJjcP4+/XlG8LGT/Rol9qUfOIztXeA84ATpqPQ==} dependencies: @@ -6443,7 +6473,18 @@ packages: find-root: 1.1.0 source-map: 0.5.7 stylis: 4.2.0 - dev: false + + /@emotion/babel-preset-css-prop@11.11.0(@babel/core@7.23.5): + resolution: {integrity: sha512-+1Cba68IyBeltWzvbBSXcBWqP2eKQuQcSUpIu3ma4pOUeRol4EvwWrYS2Rv51aIVqg066fLB+Z9O/8NKR7uUlQ==} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.23.5 + '@babel/plugin-transform-react-jsx': 7.23.4(@babel/core@7.23.5) + '@babel/runtime': 7.23.5 + '@emotion/babel-plugin': 11.11.0 + '@emotion/babel-plugin-jsx-pragmatic': 0.2.1(@babel/core@7.23.5) + dev: true /@emotion/cache@11.11.0: resolution: {integrity: sha512-P34z9ssTCBi3e9EI1ZsWpNHcfY1r09ZO0rZbRO2ob3ZQMnFI35jB536qoXbkdesr5EUhYi22anuEJuyxifaqAQ==} @@ -6453,11 +6494,9 @@ packages: '@emotion/utils': 1.2.1 '@emotion/weak-memoize': 0.3.1 stylis: 4.2.0 - dev: false /@emotion/hash@0.9.1: resolution: {integrity: sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ==} - dev: false /@emotion/is-prop-valid@0.8.8: resolution: {integrity: sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA==} @@ -6500,7 +6539,6 @@ packages: '@types/react': 18.2.43 hoist-non-react-statics: 3.3.2 react: 18.2.0 - dev: false /@emotion/serialize@1.1.2: resolution: {integrity: sha512-zR6a/fkFP4EAcCMQtLOhIgpprZOwNmCldtpaISpvz348+DP4Mz8ZoKaGGCQpbzepNIUWbq4w6hNZkwDyKoS+HA==} @@ -6510,11 +6548,9 @@ packages: '@emotion/unitless': 0.8.1 '@emotion/utils': 1.2.1 csstype: 3.1.2 - dev: false /@emotion/sheet@1.2.2: resolution: {integrity: sha512-0QBtGvaqtWi+nx6doRwDdBIzhNdZrXUppvTM4dtZZWEGTXL/XE/yJxLMGlDT1Gt+UHH5IX1n+jkXyytE/av7OA==} - dev: false /@emotion/styled@11.11.0(@emotion/react@11.11.1)(@types/react@18.2.43)(react@18.2.0): resolution: {integrity: sha512-hM5Nnvu9P3midq5aaXj4I+lnSfNi7Pmd4EWk1fOZ3pxookaQTNew6bp4JaCBYM4HVFZF9g7UjJmsUmC2JlxOng==} @@ -6545,7 +6581,6 @@ packages: /@emotion/unitless@0.8.1: resolution: {integrity: sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ==} - dev: false /@emotion/use-insertion-effect-with-fallbacks@1.0.1(react@18.2.0): resolution: {integrity: sha512-jT/qyKZ9rzLErtrjGgdkMBn2OP8wl0G3sQlBb3YPryvKHsjvINUhVaPFfP+fpBcOkmrVOVEEHQFJ7nbj2TH2gw==} @@ -6556,11 +6591,9 @@ packages: /@emotion/utils@1.2.1: resolution: {integrity: sha512-Y2tGf3I+XVnajdItskUCn6LX+VUDmP6lTL4fcqsXAv43dnlbZiuW4MWQW38rW/BVWSE7Q/7+XQocmpnRYILUmg==} - dev: false /@emotion/weak-memoize@0.3.1: resolution: {integrity: sha512-EsBwpc7hBUJWAsNPBmJy4hxWx12v6bshQsldrVmjxJoc3isbxhOrF2IcCpaXxfvq03NwkI7sbsOLXbYuqF/8Ww==} - dev: false /@esbuild/android-arm64@0.18.20: resolution: {integrity: sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==} @@ -11565,7 +11598,6 @@ packages: '@babel/runtime': 7.23.5 cosmiconfig: 7.1.0 resolve: 1.22.8 - dev: false /babel-plugin-polyfill-corejs2@0.4.6(@babel/core@7.23.5): resolution: {integrity: sha512-jhHiWVZIlnPbEUKSSNb9YoWcQGdlTLq7z1GHL4AjFxaoOUMuuEVJ+Y4pAaQUGOGk93YsVCKPbqbfw3m0SM6H8Q==} @@ -12371,7 +12403,6 @@ packages: /convert-source-map@1.9.0: resolution: {integrity: sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==} - dev: false /convert-source-map@2.0.0: resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} @@ -14279,7 +14310,6 @@ packages: /find-root@1.1.0: resolution: {integrity: sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==} - dev: false /find-up@3.0.0: resolution: {integrity: sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==} @@ -19835,7 +19865,6 @@ packages: /source-map@0.5.7: resolution: {integrity: sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==} engines: {node: '>=0.10.0'} - dev: false /source-map@0.6.1: resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} @@ -20280,7 +20309,6 @@ packages: /stylis@4.2.0: resolution: {integrity: sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==} - dev: false /sumchecker@3.0.1: resolution: {integrity: sha512-MvjXzkz/BOfyVDkG0oFOtBxHX2u3gKbMHIF/dXblZsgD3BWOFLmHovIpZY7BykJdAjcqRCBi1WYBNdEC9yI7vg==}