Inline CSS

This commit is contained in:
Nathan Bierema 2023-12-11 22:32:12 -05:00
parent fa5036a7a5
commit d0eaf738f0
13 changed files with 388 additions and 471 deletions

View File

@ -20,11 +20,6 @@ import {
import { CSS } from '@dnd-kit/utilities'; import { CSS } from '@dnd-kit/utilities';
import ActionListRow from './ActionListRow'; import ActionListRow from './ActionListRow';
import ActionListHeader from './ActionListHeader'; import ActionListHeader from './ActionListHeader';
import {
actionListCss,
actionListRowsCss,
actionListWideCss,
} from './utils/createStylingFromTheme';
function getTimestamps<A extends Action<string>>( function getTimestamps<A extends Action<string>>(
actions: { [actionId: number]: PerformAction<A> }, actions: { [actionId: number]: PerformAction<A> },
@ -152,7 +147,27 @@ export default function ActionList<A extends Action<string>>({
<div <div
key="actionList" key="actionList"
data-testid="actionList" data-testid="actionList"
css={[actionListCss, isWideLayout && actionListWideCss]} css={[
(theme) => ({
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',
},
]}
> >
<ActionListHeader <ActionListHeader
onSearch={onSearch} onSearch={onSearch}
@ -165,7 +180,7 @@ export default function ActionList<A extends Action<string>>({
/> />
<div <div
data-testid="actionListRows" data-testid="actionListRows"
css={actionListRowsCss} css={{ overflow: 'auto' }}
ref={setNodeRef} ref={setNodeRef}
> >
<DndContext <DndContext

View File

@ -1,13 +1,9 @@
import React, { FunctionComponent } from 'react'; import React, { FunctionComponent } from 'react';
import RightSlider from './RightSlider'; import RightSlider from './RightSlider';
import { import {
actionListHeaderCss,
actionListHeaderSearchCss,
actionListHeaderSelectorCss,
actionListHeaderWrapperCss,
selectorButtonCss, selectorButtonCss,
selectorButtonSmallCss, selectorButtonSmallCss,
} from './utils/createStylingFromTheme'; } from './utils/selectorButtonStyles';
const getActiveButtons = (hasSkippedActions: boolean): ('Sweep' | 'Commit')[] => const getActiveButtons = (hasSkippedActions: boolean): ('Sweep' | 'Commit')[] =>
[hasSkippedActions && 'Sweep', 'Commit'].filter( [hasSkippedActions && 'Sweep', 'Commit'].filter(
@ -33,17 +29,45 @@ const ActionListHeader: FunctionComponent<Props> = ({
hideMainButtons, hideMainButtons,
searchValue, searchValue,
}) => ( }) => (
<div css={actionListHeaderCss}> <div
css={(theme) => ({
display: 'flex',
flex: '0 0 auto',
alignItems: 'center',
borderBottomWidth: '1px',
borderBottomStyle: 'solid',
borderColor: theme.LIST_BORDER_COLOR,
})}
>
<input <input
css={actionListHeaderSearchCss} css={(theme) => ({
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)} onChange={(e) => onSearch(e.target.value)}
placeholder="filter..." placeholder="filter..."
value={searchValue} value={searchValue}
/> />
{!hideMainButtons && ( {!hideMainButtons && (
<div css={actionListHeaderWrapperCss}> <div css={{ position: 'relative', height: '20px' }}>
<RightSlider shown={hasStagedActions}> <RightSlider shown={hasStagedActions}>
<div css={actionListHeaderSelectorCss}> <div css={{ display: 'inline-flex', marginRight: '10px' }}>
{getActiveButtons(hasSkippedActions).map((btn) => ( {getActiveButtons(hasSkippedActions).map((btn) => (
<div <div
key={btn} key={btn}

View File

@ -3,27 +3,31 @@ import dateformat from 'dateformat';
import type { DebouncedFunc } from 'lodash'; import type { DebouncedFunc } from 'lodash';
import debounce from 'lodash.debounce'; import debounce from 'lodash.debounce';
import { Action } from 'redux'; import { Action } from 'redux';
import type { Interpolation, Theme } from '@emotion/react';
import RightSlider from './RightSlider'; import RightSlider from './RightSlider';
import { import {
actionListFromFutureCss,
actionListItemButtonsCss,
actionListItemCss,
actionListItemNameCss,
actionListItemNameSkippedCss,
actionListItemSelectedCss,
actionListItemSelectorCss,
actionListItemSkippedCss,
actionListItemTimeCss,
selectorButtonCss, selectorButtonCss,
selectorButtonSelectedCss, selectorButtonSelectedCss,
selectorButtonSmallCss, selectorButtonSmallCss,
} from './utils/createStylingFromTheme'; } from './utils/selectorButtonStyles';
const BUTTON_SKIP = 'Skip'; const BUTTON_SKIP = 'Skip';
const BUTTON_JUMP = 'Jump'; const BUTTON_JUMP = 'Jump';
type Button = typeof BUTTON_SKIP | typeof BUTTON_JUMP; type Button = typeof BUTTON_SKIP | typeof BUTTON_JUMP;
const actionListItemTimeCss: Interpolation<Theme> = (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<A extends Action<string>> { interface Props<A extends Action<string>> {
actionId: number; actionId: number;
isInitAction: boolean; isInitAction: boolean;
@ -86,16 +90,36 @@ export default class ActionListRow<
onMouseUp={this.handleMouseEnter} onMouseUp={this.handleMouseEnter}
data-id={actionId} data-id={actionId}
css={[ css={[
actionListItemCss, (theme) => ({
isSelected && actionListItemSelectedCss, borderBottomWidth: '1px',
isSkipped && actionListItemSkippedCss, borderBottomStyle: 'solid',
isInFuture && actionListFromFutureCss, 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' },
]} ]}
> >
<div <div
css={[ css={[
actionListItemNameCss, {
isSkipped && actionListItemNameSkippedCss, overflow: 'hidden',
textOverflow: 'ellipsis',
lineHeight: '20px',
},
isSkipped && { textDecoration: 'line-through', opacity: 0.3 },
]} ]}
> >
{actionType} {actionType}
@ -112,7 +136,7 @@ export default class ActionListRow<
</div> </div>
</RightSlider> </RightSlider>
) : ( ) : (
<div css={actionListItemButtonsCss}> <div css={{ position: 'relative', height: '20px', display: 'flex' }}>
<RightSlider shown={!showButtons} rotate> <RightSlider shown={!showButtons} rotate>
<div css={actionListItemTimeCss}> <div css={actionListItemTimeCss}>
{timeDelta === 0 {timeDelta === 0
@ -124,7 +148,7 @@ export default class ActionListRow<
</div> </div>
</RightSlider> </RightSlider>
<RightSlider shown={showButtons} rotate> <RightSlider shown={showButtons} rotate>
<div css={actionListItemSelectorCss}> <div css={{ display: 'inline-flex' }}>
{([BUTTON_JUMP, BUTTON_SKIP] as const).map( {([BUTTON_JUMP, BUTTON_SKIP] as const).map(
(btn) => (btn) =>
(!isInitAction || btn !== BUTTON_SKIP) && ( (!isInitAction || btn !== BUTTON_SKIP) && (

View File

@ -9,12 +9,6 @@ import ActionPreviewHeader from './ActionPreviewHeader';
import DiffTab from './tabs/DiffTab'; import DiffTab from './tabs/DiffTab';
import StateTab from './tabs/StateTab'; import StateTab from './tabs/StateTab';
import ActionTab from './tabs/ActionTab'; import ActionTab from './tabs/ActionTab';
import {
actionPreviewContentCss,
actionPreviewCss,
stateErrorCss,
treeItemPinCss,
} from './utils/createStylingFromTheme';
export interface TabComponentProps<S, A extends Action<string>> { export interface TabComponentProps<S, A extends Action<string>> {
labelRenderer: LabelRenderer; labelRenderer: LabelRenderer;
@ -123,13 +117,31 @@ class ActionPreview<S, A extends Action<string>> extends Component<
renderedTabs.find((tab) => tab.name === DEFAULT_STATE.tabName)!; renderedTabs.find((tab) => tab.name === DEFAULT_STATE.tabName)!;
return ( return (
<div key="actionPreview" css={actionPreviewCss}> <div
key="actionPreview"
css={(theme) => ({
flex: 1,
display: 'flex',
flexDirection: 'column',
flexGrow: 1,
overflowY: 'hidden',
'& pre': {
border: 'inherit',
borderRadius: '3px',
lineHeight: 'inherit',
color: 'inherit',
},
backgroundColor: theme.BACKGROUND_COLOR,
})}
>
<ActionPreviewHeader <ActionPreviewHeader
tabs={renderedTabs as unknown as Tab<unknown, Action<string>>[]} tabs={renderedTabs as unknown as Tab<unknown, Action<string>>[]}
{...{ inspectedPath, onInspectPath, tabName, onSelectTab }} {...{ inspectedPath, onInspectPath, tabName, onSelectTab }}
/> />
{!error && ( {!error && (
<div key="actionPreviewContent" css={actionPreviewContentCss}> <div key="actionPreviewContent" css={{ flex: 1, overflowY: 'auto' }}>
<TabComponent <TabComponent
labelRenderer={this.labelRenderer} labelRenderer={this.labelRenderer}
{...{ {...{
@ -152,7 +164,19 @@ class ActionPreview<S, A extends Action<string>> extends Component<
/> />
</div> </div>
)} )}
{error && <div css={stateErrorCss}>{error}</div>} {error && (
<div
css={(theme) => ({
padding: '10px',
marginLeft: '14px',
fontWeight: 'bold',
color: theme.ERROR_COLOR,
})}
>
{error}
</div>
)}
</div> </div>
); );
} }
@ -164,7 +188,16 @@ class ActionPreview<S, A extends Action<string>> extends Component<
<span> <span>
<span>{key}</span> <span>{key}</span>
<span <span
css={treeItemPinCss} css={(theme) => ({
fontSize: '0.7em',
paddingLeft: '5px',
cursor: 'pointer',
'&:hover': {
textDecoration: 'underline',
},
color: theme.PIN_COLOR,
})}
onClick={() => onClick={() =>
onInspectPath([ onInspectPath([
...inspectedPath.slice(0, inspectedPath.length - 1), ...inspectedPath.slice(0, inspectedPath.length - 1),

View File

@ -1,15 +1,27 @@
import React, { FunctionComponent } from 'react'; import React, { FunctionComponent } from 'react';
import { Action } from 'redux'; import { Action } from 'redux';
import { css } from '@emotion/react';
import type { Interpolation, Theme } from '@emotion/react';
import { Tab } from './ActionPreview'; import { Tab } from './ActionPreview';
import { import {
inspectedPathCss,
inspectedPathKeyCss,
inspectedPathKeyLinkCss,
previewHeaderCss,
selectorButtonCss, selectorButtonCss,
selectorButtonSelectedCss, selectorButtonSelectedCss,
tabSelectorCss, } from './utils/selectorButtonStyles';
} from './utils/createStylingFromTheme';
const inspectedPathKeyCss = css({
'&:not(:last-child):after': {
content: '" > "',
},
});
const inspectedPathKeyLinkCss: Interpolation<Theme> = (theme) => ({
cursor: 'pointer',
color: theme.LINK_COLOR,
'&:hover': {
textDecoration: 'underline',
color: theme.LINK_HOVER_COLOR,
},
});
interface Props<S, A extends Action<string>> { interface Props<S, A extends Action<string>> {
tabs: Tab<S, A>[]; tabs: Tab<S, A>[];
@ -22,8 +34,20 @@ interface Props<S, A extends Action<string>> {
const ActionPreviewHeader: FunctionComponent< const ActionPreviewHeader: FunctionComponent<
Props<unknown, Action<string>> Props<unknown, Action<string>>
> = ({ inspectedPath, onInspectPath, tabName, onSelectTab, tabs }) => ( > = ({ inspectedPath, onInspectPath, tabName, onSelectTab, tabs }) => (
<div key="previewHeader" css={previewHeaderCss}> <div
<div css={tabSelectorCss}> key="previewHeader"
css={(theme) => ({
flex: '0 0 30px',
padding: '5px 10px',
alignItems: 'center',
borderBottomWidth: '1px',
borderBottomStyle: 'solid',
backgroundColor: theme.HEADER_BACKGROUND_COLOR,
borderBottomColor: theme.HEADER_BORDER_COLOR,
})}
>
<div css={{ position: 'relative', display: 'inline-flex', float: 'right' }}>
{tabs.map((tab) => ( {tabs.map((tab) => (
<div <div
onClick={() => onSelectTab(tab.name)} onClick={() => onSelectTab(tab.name)}
@ -37,7 +61,7 @@ const ActionPreviewHeader: FunctionComponent<
</div> </div>
))} ))}
</div> </div>
<div css={inspectedPathCss}> <div css={{ padding: '6px 0' }}>
{inspectedPath.length ? ( {inspectedPath.length ? (
<span css={inspectedPathKeyCss}> <span css={inspectedPathKeyCss}>
<a onClick={() => onInspectPath([])} css={inspectedPathKeyLinkCss}> <a onClick={() => onInspectPath([])} css={inspectedPathKeyLinkCss}>

View File

@ -8,12 +8,10 @@ import {
import { Action, Dispatch } from 'redux'; import { Action, Dispatch } from 'redux';
import { Delta, DiffContext } from 'jsondiffpatch'; import { Delta, DiffContext } from 'jsondiffpatch';
import { import {
Base16ThemeName,
createInspectorMonitorThemeFromBase16Theme, createInspectorMonitorThemeFromBase16Theme,
inspectorCss,
inspectorWideCss,
resolveBase16Theme, resolveBase16Theme,
} from './utils/createStylingFromTheme'; } from './utils/themes';
import type { Base16ThemeName } from './utils/themes';
import ActionList from './ActionList'; import ActionList from './ActionList';
import ActionPreview, { Tab } from './ActionPreview'; import ActionPreview, { Tab } from './ActionPreview';
import getInspectedState from './utils/getInspectedState'; import getInspectedState from './utils/getInspectedState';
@ -284,7 +282,22 @@ class DevtoolsInspector<S, A extends Action<string>> extends PureComponent<
key="inspector" key="inspector"
data-testid="inspector" data-testid="inspector"
ref={this.inspectorCreateRef} ref={this.inspectorCreateRef}
css={[inspectorCss, isWideLayout && inspectorWideCss]} css={[
(theme) => ({
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' },
]}
> >
<ActionList <ActionList
{...{ {...{

View File

@ -1,10 +1,4 @@
import React, { FunctionComponent } from 'react'; import React, { FunctionComponent } from 'react';
import {
rightSliderCss,
rightSliderRotateCss,
rightSliderRotateShownCss,
rightSliderShownCss,
} from './utils/createStylingFromTheme';
interface Props { interface Props {
shown?: boolean; shown?: boolean;
@ -15,10 +9,26 @@ interface Props {
const RightSlider: FunctionComponent<Props> = ({ shown, children, rotate }) => ( const RightSlider: FunctionComponent<Props> = ({ shown, children, rotate }) => (
<div <div
css={[ css={[
rightSliderCss, {
shown && rightSliderShownCss, WebkitFontSmoothing: 'subpixel-antialiased', // http://stackoverflow.com/a/21136111/4218591
rotate && rightSliderRotateCss, position: 'absolute',
rotate && shown && rightSliderRotateShownCss, right: 0,
transform: 'translateX(150%)',
transition: 'transform 0.2s ease-in-out',
},
shown && {
position: 'static',
transform: 'translateX(0)',
},
rotate && {
transform: 'rotateX(90deg)',
transition: 'transform 0.2s ease-in-out 0.08s',
},
rotate &&
shown && {
transform: 'rotateX(0)',
transition: 'transform 0.2s ease-in-out 0.18s',
},
]} ]}
> >
{children} {children}

View File

@ -3,7 +3,7 @@ export type { LabelRenderer } from 'react-json-tree';
export { default as InspectorMonitor } from './DevtoolsInspector'; export { default as InspectorMonitor } from './DevtoolsInspector';
export type { Tab, TabComponentProps } from './ActionPreview'; export type { Tab, TabComponentProps } from './ActionPreview';
export type { DevtoolsInspectorState } from './redux'; export type { DevtoolsInspectorState } from './redux';
export type { Base16ThemeName } from './utils/createStylingFromTheme'; export type { Base16ThemeName } from './utils/themes';
export * as inspectorThemes from './themes/index'; export * as inspectorThemes from './themes/index';
export { default as ActionTab } from './tabs/ActionTab'; export { default as ActionTab } from './tabs/ActionTab';
export { default as DiffTab } from './tabs/DiffTab'; export { default as DiffTab } from './tabs/DiffTab';

View File

@ -4,18 +4,10 @@ import type { LabelRenderer, ShouldExpandNodeInitially } from 'react-json-tree';
import { stringify } from 'javascript-stringify'; import { stringify } from 'javascript-stringify';
import { Delta } from 'jsondiffpatch'; import { Delta } from 'jsondiffpatch';
import { Base16Theme } from 'redux-devtools-themes'; import { Base16Theme } from 'redux-devtools-themes';
import { css } from '@emotion/react';
import type { Interpolation, Theme } from '@emotion/react';
import getItemString from './getItemString'; import getItemString from './getItemString';
import getJsonTreeTheme from './getJsonTreeTheme'; import getJsonTreeTheme from './getJsonTreeTheme';
import {
diffAddCss,
diffCss,
diffRemoveCss,
diffUpdateArrowCss,
diffUpdateFromCss,
diffUpdateToCss,
diffWrapCss,
stateDiffEmptyCss,
} from '../utils/createStylingFromTheme';
function stringifyAndShrink(val: any, isWideLayout?: boolean) { function stringifyAndShrink(val: any, isWideLayout?: boolean) {
if (val === null) { if (val === null) {
@ -55,6 +47,16 @@ function prepareDelta(value: any) {
return value; return value;
} }
const diffCss: Interpolation<Theme> = (theme) => ({
padding: '2px 3px',
borderRadius: '3px',
position: 'relative',
color: theme.TEXT_COLOR,
});
const diffWrapCss = css({ position: 'relative', zIndex: 1 });
interface Props { interface Props {
delta: Delta | null | undefined | false; delta: Delta | null | undefined | false;
base16Theme: Base16Theme; base16Theme: Base16Theme;
@ -93,7 +95,16 @@ export default class JSONDiff extends Component<Props, State> {
const { base16Theme, ...props } = this.props; const { base16Theme, ...props } = this.props;
if (!this.state.data) { if (!this.state.data) {
return <div css={stateDiffEmptyCss}>(states are equal)</div>; return (
<div
css={(theme) => ({
padding: '10px',
color: theme.TEXT_PLACEHOLDER_COLOR,
})}
>
(states are equal)
</div>
);
} }
return ( return (
@ -128,7 +139,13 @@ export default class JSONDiff extends Component<Props, State> {
case 1: case 1:
return ( return (
<span css={diffWrapCss}> <span css={diffWrapCss}>
<span key="diffAdd" css={[diffCss, diffAddCss]}> <span
key="diffAdd"
css={[
diffCss,
(theme) => ({ backgroundColor: theme.DIFF_ADD_COLOR }),
]}
>
{stringifyAndShrink(value[0], isWideLayout)} {stringifyAndShrink(value[0], isWideLayout)}
</span> </span>
</span> </span>
@ -136,13 +153,31 @@ export default class JSONDiff extends Component<Props, State> {
case 2: case 2:
return ( return (
<span css={diffWrapCss}> <span css={diffWrapCss}>
<span key="diffUpdateFrom" css={[diffCss, diffUpdateFromCss]}> <span
key="diffUpdateFrom"
css={[
diffCss,
(theme) => ({
textDecoration: 'line-through',
backgroundColor: theme.DIFF_REMOVE_COLOR,
}),
]}
>
{stringifyAndShrink(value[0], isWideLayout)} {stringifyAndShrink(value[0], isWideLayout)}
</span> </span>
<span key="diffUpdateArrow" css={[diffCss, diffUpdateArrowCss]}> <span
key="diffUpdateArrow"
css={[diffCss, (theme) => ({ color: theme.DIFF_ARROW_COLOR })]}
>
{' => '} {' => '}
</span> </span>
<span key="diffUpdateTo" css={[diffCss, diffUpdateToCss]}> <span
key="diffUpdateTo"
css={[
diffCss,
(theme) => ({ backgroundColor: theme.DIFF_ADD_COLOR }),
]}
>
{stringifyAndShrink(value[1], isWideLayout)} {stringifyAndShrink(value[1], isWideLayout)}
</span> </span>
</span> </span>
@ -150,7 +185,16 @@ export default class JSONDiff extends Component<Props, State> {
case 3: case 3:
return ( return (
<span css={diffWrapCss}> <span css={diffWrapCss}>
<span key="diffRemove" css={[diffCss, diffRemoveCss]}> <span
key="diffRemove"
css={[
diffCss,
(theme) => ({
textDecoration: 'line-through',
backgroundColor: theme.DIFF_REMOVE_COLOR,
}),
]}
>
{stringifyAndShrink(value[0])} {stringifyAndShrink(value[0])}
</span> </span>
</span> </span>

View File

@ -1,7 +1,6 @@
import React from 'react'; import React from 'react';
import { isCollection, isIndexed, isKeyed } from 'immutable'; import { isCollection, isIndexed, isKeyed } from 'immutable';
import isIterable from '../utils/isIterable'; import isIterable from '../utils/isIterable';
import { treeItemHintCss } from '../utils/createStylingFromTheme';
const IS_IMMUTABLE_KEY = '@@__IS_IMMUTABLE__@@'; const IS_IMMUTABLE_KEY = '@@__IS_IMMUTABLE__@@';
@ -78,7 +77,7 @@ const getItemString = (
isWideLayout: boolean, isWideLayout: boolean,
isDiff?: boolean, isDiff?: boolean,
) => ( ) => (
<span css={treeItemHintCss}> <span css={(theme) => ({ color: theme.ITEM_HINT_COLOR })}>
{data[IS_IMMUTABLE_KEY] ? 'Immutable' : ''} {data[IS_IMMUTABLE_KEY] ? 'Immutable' : ''}
{dataTypeKey && data[dataTypeKey] ? `${data[dataTypeKey] as string} ` : ''} {dataTypeKey && data[dataTypeKey] ? `${data[dataTypeKey] as string} ` : ''}
{getText(type, data, isWideLayout, isDiff)} {getText(type, data, isWideLayout, isDiff)}

View File

@ -1,384 +0,0 @@
import { css } from '@emotion/react';
import type { Interpolation, Theme } from '@emotion/react';
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';
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;
}
}
export 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 const inspectorCss: Interpolation<Theme> = (theme) => ({
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,
});
export const inspectorWideCss = css({ flexDirection: 'row' });
export const actionListCss: Interpolation<Theme> = (theme) => ({
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,
});
export const actionListWideCss = css({
flexBasis: '40%',
borderBottom: 'none',
borderRightWidth: '3px',
borderRightStyle: 'double',
});
export const actionListHeaderCss: Interpolation<Theme> = (theme) => ({
display: 'flex',
flex: '0 0 auto',
alignItems: 'center',
borderBottomWidth: '1px',
borderBottomStyle: 'solid',
borderColor: theme.LIST_BORDER_COLOR,
});
export const actionListRowsCss = css({ overflow: 'auto' });
export const actionListHeaderSelectorCss = css({
display: 'inline-flex',
marginRight: '10px',
});
export const actionListItemCss: Interpolation<Theme> = (theme) => ({
borderBottomWidth: '1px',
borderBottomStyle: 'solid',
display: 'flex',
justifyContent: 'space-between',
padding: '5px 10px',
cursor: 'pointer',
userSelect: 'none',
borderBottomColor: theme.BORDER_COLOR,
});
export const actionListItemSelectedCss: Interpolation<Theme> = (theme) => ({
backgroundColor: theme.SELECTED_BACKGROUND_COLOR,
});
export const actionListItemSkippedCss: Interpolation<Theme> = (theme) => ({
backgroundColor: theme.SKIPPED_BACKGROUND_COLOR,
});
export const actionListFromFutureCss = css({ opacity: '0.6' });
export const actionListItemButtonsCss = css({
position: 'relative',
height: '20px',
display: 'flex',
});
export const actionListItemTimeCss: Interpolation<Theme> = (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,
});
export const actionListItemSelectorCss = css({ display: 'inline-flex' });
export const actionListItemNameCss = css({
overflow: 'hidden',
textOverflow: 'ellipsis',
lineHeight: '20px',
});
export const actionListItemNameSkippedCss = css({
textDecoration: 'line-through',
opacity: 0.3,
});
export const actionListHeaderSearchCss: Interpolation<Theme> = (theme) => ({
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,
},
});
export const actionListHeaderWrapperCss = css({
position: 'relative',
height: '20px',
});
export const actionPreviewCss: Interpolation<Theme> = (theme) => ({
flex: 1,
display: 'flex',
flexDirection: 'column',
flexGrow: 1,
overflowY: 'hidden',
'& pre': {
border: 'inherit',
borderRadius: '3px',
lineHeight: 'inherit',
color: 'inherit',
},
backgroundColor: theme.BACKGROUND_COLOR,
});
export const actionPreviewContentCss = css({ flex: 1, overflowY: 'auto' });
export const stateDiffEmptyCss: Interpolation<Theme> = (theme) => ({
padding: '10px',
color: theme.TEXT_PLACEHOLDER_COLOR,
});
export const stateErrorCss: Interpolation<Theme> = (theme) => ({
padding: '10px',
marginLeft: '14px',
fontWeight: 'bold',
color: theme.ERROR_COLOR,
});
export const inspectedPathCss = css({ padding: '6px 0' });
export const inspectedPathKeyCss = css({
'&:not(:last-child):after': {
content: '" > "',
},
});
export const inspectedPathKeyLinkCss: Interpolation<Theme> = (theme) => ({
cursor: 'pointer',
color: theme.LINK_COLOR,
'&:hover': {
textDecoration: 'underline',
color: theme.LINK_HOVER_COLOR,
},
});
export const treeItemPinCss: Interpolation<Theme> = (theme) => ({
fontSize: '0.7em',
paddingLeft: '5px',
cursor: 'pointer',
'&:hover': {
textDecoration: 'underline',
},
color: theme.PIN_COLOR,
});
export const treeItemHintCss: Interpolation<Theme> = (theme) => ({
color: theme.ITEM_HINT_COLOR,
});
export const previewHeaderCss: Interpolation<Theme> = (theme) => ({
flex: '0 0 30px',
padding: '5px 10px',
alignItems: 'center',
borderBottomWidth: '1px',
borderBottomStyle: 'solid',
backgroundColor: theme.HEADER_BACKGROUND_COLOR,
borderBottomColor: theme.HEADER_BORDER_COLOR,
});
export const tabSelectorCss = css({
position: 'relative',
display: 'inline-flex',
float: 'right',
});
export const selectorButtonCss: Interpolation<Theme> = (theme) => ({
cursor: 'pointer',
position: 'relative',
padding: '5px 10px',
borderStyle: 'solid',
borderWidth: '1px',
borderLeftWidth: 0,
'&:first-child': {
borderLeftWidth: '1px',
borderTopLeftRadius: '3px',
borderBottomLeftRadius: '3px',
},
'&:last-child': {
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> = (theme) => ({
backgroundColor: theme.TAB_BACK_SELECTED_COLOR,
});
export const diffCss: Interpolation<Theme> = (theme) => ({
padding: '2px 3px',
borderRadius: '3px',
position: 'relative',
color: theme.TEXT_COLOR,
});
export const diffWrapCss = css({ position: 'relative', zIndex: 1 });
export const diffAddCss: Interpolation<Theme> = (theme) => ({
backgroundColor: theme.DIFF_ADD_COLOR,
});
export const diffRemoveCss: Interpolation<Theme> = (theme) => ({
textDecoration: 'line-through',
backgroundColor: theme.DIFF_REMOVE_COLOR,
});
export const diffUpdateFromCss: Interpolation<Theme> = (theme) => ({
textDecoration: 'line-through',
backgroundColor: theme.DIFF_REMOVE_COLOR,
});
export const diffUpdateToCss: Interpolation<Theme> = (theme) => ({
backgroundColor: theme.DIFF_ADD_COLOR,
});
export const diffUpdateArrowCss: Interpolation<Theme> = (theme) => ({
color: theme.DIFF_ARROW_COLOR,
});
export const rightSliderCss = css({
WebkitFontSmoothing: 'subpixel-antialiased', // http://stackoverflow.com/a/21136111/4218591
position: 'absolute',
right: 0,
transform: 'translateX(150%)',
transition: 'transform 0.2s ease-in-out',
});
export const rightSliderRotateCss = css({
transform: 'rotateX(90deg)',
transition: 'transform 0.2s ease-in-out 0.08s',
});
export const rightSliderShownCss = css({
position: 'static',
transform: 'translateX(0)',
});
export const rightSliderRotateShownCss = css({
transform: 'rotateX(0)',
transition: 'transform 0.2s ease-in-out 0.18s',
});
const base16Themes = { ...reduxThemes, ...inspectorThemes };
export type Base16ThemeName = keyof typeof base16Themes;
export function resolveBase16Theme(theme: Base16ThemeName | Base16Theme) {
return getBase16Theme(theme, base16Themes);
}
export function createInspectorMonitorThemeFromBase16Theme(
base16Theme: Base16Theme,
invertTheme: boolean,
) {
const finalBase16Theme = invertTheme
? invertBase16Theme(base16Theme)
: base16Theme;
return colorMap(finalBase16Theme);
}

View File

@ -0,0 +1,39 @@
import { css } from '@emotion/react';
import type { Interpolation, Theme } from '@emotion/react';
export const selectorButtonCss: Interpolation<Theme> = (theme) => ({
cursor: 'pointer',
position: 'relative',
padding: '5px 10px',
borderStyle: 'solid',
borderWidth: '1px',
borderLeftWidth: 0,
'&:first-child': {
borderLeftWidth: '1px',
borderTopLeftRadius: '3px',
borderBottomLeftRadius: '3px',
},
'&:last-child': {
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> = (theme) => ({
backgroundColor: theme.TAB_BACK_SELECTED_COLOR,
});

View File

@ -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);
}