mirror of
https://github.com/reduxjs/redux-devtools.git
synced 2024-11-21 17:16:42 +03:00
[rtk-query-monitor] Replace jss with Emotion (#1568)
* Add Emotion to RTK Query monitor * Add other Emotion setup * Start transition * Convert more styling to Emotion * Convert more styling to Emotion * Finish convert styling to Emotion * import type * Fix test * Remove unused styling * Remove more unused styling * Remove more unused styling * Remove jss * Cleanup * Create perfect-otters-help.md * Update perfect-otters-help.md
This commit is contained in:
parent
178002de65
commit
6954eb9580
5
.changeset/perfect-otters-help.md
Normal file
5
.changeset/perfect-otters-help.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
'@redux-devtools/rtk-query-monitor': major
|
||||
---
|
||||
|
||||
Replace jss with Emotion in inspector-monitor. `@emotion/react` is now a required peer dependency.
|
|
@ -8,6 +8,9 @@ module.exports = {
|
|||
tsconfigRootDir: __dirname,
|
||||
project: true,
|
||||
},
|
||||
rules: {
|
||||
'react/no-unknown-property': ['error', { ignore: ['css'] }],
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ['test/**/*.ts', 'test/**/*.tsx'],
|
||||
|
|
|
@ -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"]
|
||||
}
|
||||
|
|
|
@ -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"]
|
||||
}
|
||||
|
|
|
@ -3,5 +3,5 @@
|
|||
"compilerOptions": {
|
||||
"resolveJsonModule": true
|
||||
},
|
||||
"include": ["../src", "src"]
|
||||
"include": ["src"]
|
||||
}
|
||||
|
|
|
@ -50,8 +50,6 @@
|
|||
"@types/redux-devtools-themes": "^1.0.3",
|
||||
"hex-rgba": "^1.0.2",
|
||||
"immutable": "^4.3.4",
|
||||
"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",
|
||||
|
@ -65,6 +63,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",
|
||||
"@reduxjs/toolkit": "^1.9.7",
|
||||
"@testing-library/jest-dom": "^6.1.5",
|
||||
|
@ -91,6 +91,7 @@
|
|||
"typescript": "~5.3.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@emotion/react": "^11.0.0",
|
||||
"@redux-devtools/core": "^3.0.0",
|
||||
"@reduxjs/toolkit": "^1.0.0 || ^2.0.0",
|
||||
"@types/react": "^16.3.0 || ^17.0.0 || ^18.0.0",
|
||||
|
|
|
@ -1,24 +1,31 @@
|
|||
import React from 'react';
|
||||
import { StyleUtilsContext } from '../styles/createStylingFromTheme';
|
||||
|
||||
export function NoRtkQueryApi(): JSX.Element {
|
||||
return (
|
||||
<StyleUtilsContext.Consumer>
|
||||
{({ styling }) => (
|
||||
<div {...styling('noApiFound')}>
|
||||
No rtk-query api found.
|
||||
<br />
|
||||
Make sure to follow{' '}
|
||||
<a
|
||||
href="https://redux-toolkit.js.org/rtk-query/overview#basic-usage"
|
||||
target="_blank"
|
||||
rel="noreferrer noopener"
|
||||
>
|
||||
the instructions
|
||||
</a>
|
||||
.
|
||||
</div>
|
||||
)}
|
||||
</StyleUtilsContext.Consumer>
|
||||
<div
|
||||
css={(theme) => ({
|
||||
width: '100%',
|
||||
textAlign: 'center',
|
||||
color: theme.TEXT_COLOR,
|
||||
padding: '1.4em',
|
||||
'& a': {
|
||||
fontSize: 'inherit',
|
||||
color: theme.TEXT_COLOR,
|
||||
textDecoration: 'underline',
|
||||
},
|
||||
})}
|
||||
>
|
||||
No rtk-query api found.
|
||||
<br />
|
||||
Make sure to follow{' '}
|
||||
<a
|
||||
href="https://redux-toolkit.js.org/rtk-query/overview#basic-usage"
|
||||
target="_blank"
|
||||
rel="noreferrer noopener"
|
||||
>
|
||||
the instructions
|
||||
</a>
|
||||
.
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
import React, { ReactNode, FormEvent, MouseEvent, ChangeEvent } from 'react';
|
||||
import type { DebouncedFunc } from 'lodash';
|
||||
import { css } from '@emotion/react';
|
||||
import { Select } from '@redux-devtools/ui';
|
||||
import { QueryFormValues } from '../types';
|
||||
import { StyleUtilsContext } from '../styles/createStylingFromTheme';
|
||||
import { StyleUtilsContext } from '../styles/themes';
|
||||
import { SelectOption } from '../types';
|
||||
import debounce from 'lodash.debounce';
|
||||
import { sortQueryOptions, QueryComparators } from '../utils/comparators';
|
||||
|
@ -10,6 +11,17 @@ import { QueryFilters, filterQueryOptions } from '../utils/filters';
|
|||
import { SortOrderButton } from './SortOrderButton';
|
||||
import { RegexIcon } from './RegexIcon';
|
||||
|
||||
const srOnlyCss = css({
|
||||
position: 'absolute',
|
||||
width: 1,
|
||||
height: 1,
|
||||
padding: 0,
|
||||
margin: '-1px',
|
||||
overflow: 'hidden',
|
||||
clip: 'rect(0,0,0,0)',
|
||||
border: 0,
|
||||
});
|
||||
|
||||
export interface QueryFormProps {
|
||||
values: QueryFormValues;
|
||||
searchQueryRegex: RegExp | null;
|
||||
|
@ -125,19 +137,68 @@ export class QueryForm extends React.PureComponent<
|
|||
|
||||
return (
|
||||
<StyleUtilsContext.Consumer>
|
||||
{({ styling, base16Theme }) => {
|
||||
{({ base16Theme }) => {
|
||||
return (
|
||||
<form
|
||||
id="rtk-query-monitor-query-selection-form"
|
||||
action="#"
|
||||
onSubmit={this.handleSubmit}
|
||||
{...styling('queryForm')}
|
||||
css={{
|
||||
display: 'flex',
|
||||
flexFlow: 'column nowrap',
|
||||
}}
|
||||
>
|
||||
<div {...styling('queryListHeader')}>
|
||||
<label htmlFor={searchId} {...styling('srOnly')}>
|
||||
<div
|
||||
css={(theme) => ({
|
||||
display: 'flex',
|
||||
padding: 4,
|
||||
flex: '0 0 auto',
|
||||
alignItems: 'center',
|
||||
borderBottomWidth: '1px',
|
||||
borderBottomStyle: 'solid',
|
||||
|
||||
borderColor: theme.LIST_BORDER_COLOR,
|
||||
})}
|
||||
>
|
||||
<label htmlFor={searchId} css={srOnlyCss}>
|
||||
filter query
|
||||
</label>
|
||||
<div {...styling('querySearch')}>
|
||||
<div
|
||||
css={(theme) => ({
|
||||
maxWidth: '65%',
|
||||
backgroundColor: theme.BACKGROUND_COLOR,
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
flexFlow: 'row nowrap',
|
||||
flex: '1 1 auto',
|
||||
paddingRight: 6,
|
||||
'& input': {
|
||||
outline: 'none',
|
||||
border: 'none',
|
||||
width: '100%',
|
||||
flex: '1 1 auto',
|
||||
padding: '5px 10px',
|
||||
fontSize: '1em',
|
||||
position: 'relative',
|
||||
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,
|
||||
},
|
||||
'&::-webkit-search-cancel-button': {
|
||||
WebkitAppearance: 'none',
|
||||
},
|
||||
},
|
||||
})}
|
||||
>
|
||||
<input
|
||||
ref={this.inputSearchRef}
|
||||
type="search"
|
||||
|
@ -152,7 +213,32 @@ export class QueryForm extends React.PureComponent<
|
|||
+(this.state.searchValue.length === 0) || undefined
|
||||
}
|
||||
onClick={this.handleClearSearchClick}
|
||||
{...styling('closeButton')}
|
||||
css={(theme) => ({
|
||||
WebkitAppearance: 'none',
|
||||
border: 'none',
|
||||
outline: 'none',
|
||||
boxShadow: 'none',
|
||||
display: 'block',
|
||||
flex: '0 0 auto',
|
||||
cursor: 'pointer',
|
||||
background: 'transparent',
|
||||
position: 'relative',
|
||||
fontSize: 'inherit',
|
||||
'&[data-invisible="1"]': {
|
||||
visibility: 'hidden !important' as 'hidden',
|
||||
},
|
||||
'&::after': {
|
||||
content: '"\u00d7"',
|
||||
display: 'block',
|
||||
padding: 4,
|
||||
fontSize: '1.2em',
|
||||
color: theme.TEXT_PLACEHOLDER_COLOR,
|
||||
background: 'transparent',
|
||||
},
|
||||
'&:hover::after': {
|
||||
color: theme.TEXT_COLOR,
|
||||
},
|
||||
})}
|
||||
/>
|
||||
<button
|
||||
type="button"
|
||||
|
@ -161,12 +247,41 @@ export class QueryForm extends React.PureComponent<
|
|||
data-type={regexToggleType}
|
||||
aria-pressed={isRegexSearch}
|
||||
onClick={this.handleRegexSearchClick}
|
||||
{...styling('toggleButton')}
|
||||
css={(theme) => ({
|
||||
width: '24px',
|
||||
height: '24px',
|
||||
display: 'inline-block',
|
||||
flex: '0 0 auto',
|
||||
color: theme.TEXT_PLACEHOLDER_COLOR,
|
||||
cursor: 'pointer',
|
||||
padding: 0,
|
||||
fontSize: '0.7em',
|
||||
letterSpacing: '-0.7px',
|
||||
outline: 'none',
|
||||
boxShadow: 'none',
|
||||
fontWeight: '700',
|
||||
border: 'none',
|
||||
|
||||
'&:hover': {
|
||||
color: theme.TEXT_COLOR,
|
||||
},
|
||||
|
||||
backgroundColor: 'transparent',
|
||||
'&[aria-pressed="true"]': {
|
||||
color: theme.BACKGROUND_COLOR,
|
||||
backgroundColor: theme.TEXT_COLOR,
|
||||
},
|
||||
|
||||
'&[data-type="error"]': {
|
||||
color: theme.TEXT_COLOR,
|
||||
backgroundColor: theme.TOGGLE_BUTTON_ERROR,
|
||||
},
|
||||
})}
|
||||
>
|
||||
<RegexIcon />
|
||||
</button>
|
||||
</div>
|
||||
<label htmlFor={selectId} {...styling('srOnly')}>
|
||||
<label htmlFor={selectId} css={srOnlyCss}>
|
||||
filter by
|
||||
</label>
|
||||
<Select<SelectOption<QueryFilters>>
|
||||
|
@ -180,7 +295,24 @@ export class QueryForm extends React.PureComponent<
|
|||
onChange={this.handleSelectFilterChange}
|
||||
/>
|
||||
</div>
|
||||
<div {...styling('sortBySection')}>
|
||||
<div
|
||||
css={{
|
||||
display: 'flex',
|
||||
padding: '0.4em',
|
||||
'& label': {
|
||||
display: 'flex',
|
||||
flex: '0 0 auto',
|
||||
whiteSpace: 'nowrap',
|
||||
alignItems: 'center',
|
||||
paddingRight: '0.4em',
|
||||
},
|
||||
|
||||
'& > :last-child': {
|
||||
flex: '0 0 auto',
|
||||
marginLeft: '0.4em',
|
||||
},
|
||||
}}
|
||||
>
|
||||
<label htmlFor={selectId}>Sort by</label>
|
||||
<Select<SelectOption<QueryComparators>>
|
||||
id={selectId}
|
||||
|
|
|
@ -1,8 +1,23 @@
|
|||
import React, { PureComponent, ReactNode } from 'react';
|
||||
import { StyleUtilsContext } from '../styles/createStylingFromTheme';
|
||||
import type { Interpolation, Theme } from '@emotion/react';
|
||||
import { RtkResourceInfo, RtkQueryMonitorState } from '../types';
|
||||
import { isQuerySelected } from '../utils/rtk-query';
|
||||
|
||||
const queryStatusCss: Interpolation<Theme> = (theme) => ({
|
||||
display: 'inline-flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
height: 22,
|
||||
padding: '0 6px',
|
||||
borderRadius: '3px',
|
||||
fontSize: '0.7em',
|
||||
lineHeight: '1em',
|
||||
flexShrink: 0,
|
||||
fontWeight: 700,
|
||||
backgroundColor: theme.ACTION_TIME_BACK_COLOR,
|
||||
color: theme.ACTION_TIME_COLOR,
|
||||
});
|
||||
|
||||
export interface QueryListProps {
|
||||
resInfos: RtkResourceInfo[];
|
||||
selectedQueryKey: RtkQueryMonitorState['selectedQueryKey'];
|
||||
|
@ -34,36 +49,71 @@ export class QueryList extends PureComponent<QueryListProps> {
|
|||
const { resInfos, selectedQueryKey, onSelectQuery } = this.props;
|
||||
|
||||
return (
|
||||
<StyleUtilsContext.Consumer>
|
||||
{({ styling }) => (
|
||||
<ul {...styling('queryList')}>
|
||||
{resInfos.map((resInfo) => {
|
||||
const isSelected = isQuerySelected(selectedQueryKey, resInfo);
|
||||
<ul css={{ listStyle: 'none', margin: '0', padding: '0' }}>
|
||||
{resInfos.map((resInfo) => {
|
||||
const isSelected = isQuerySelected(selectedQueryKey, resInfo);
|
||||
|
||||
return (
|
||||
<li
|
||||
key={resInfo.queryKey}
|
||||
onClick={() => onSelectQuery(resInfo)}
|
||||
{...styling(
|
||||
['queryListItem', isSelected && 'queryListItemSelected'],
|
||||
isSelected,
|
||||
)}
|
||||
>
|
||||
<p {...styling('queryListItemKey')}>
|
||||
{QueryList.formatQuery(resInfo)}
|
||||
</p>
|
||||
<div {...styling('queryStatusWrapper')}>
|
||||
<strong {...styling(['queryStatus', 'queryType'])}>
|
||||
{resInfo.type === 'query' ? 'Q' : 'M'}
|
||||
</strong>
|
||||
<p {...styling('queryStatus')}>{resInfo.state.status}</p>
|
||||
</div>
|
||||
</li>
|
||||
);
|
||||
})}
|
||||
</ul>
|
||||
)}
|
||||
</StyleUtilsContext.Consumer>
|
||||
return (
|
||||
<li
|
||||
key={resInfo.queryKey}
|
||||
onClick={() => onSelectQuery(resInfo)}
|
||||
css={[
|
||||
(theme) => ({
|
||||
borderBottomWidth: '1px',
|
||||
borderBottomStyle: 'solid',
|
||||
display: 'flex',
|
||||
justifyContent: 'space-between',
|
||||
padding: '5px 10px',
|
||||
cursor: 'pointer',
|
||||
userSelect: 'none',
|
||||
'&:last-child': {
|
||||
borderBottomWidth: 0,
|
||||
},
|
||||
overflow: 'hidden',
|
||||
maxHeight: 47,
|
||||
borderBottomColor: theme.BORDER_COLOR,
|
||||
}),
|
||||
isSelected &&
|
||||
((theme) => ({
|
||||
backgroundColor: theme.SELECTED_BACKGROUND_COLOR,
|
||||
})),
|
||||
]}
|
||||
>
|
||||
<p
|
||||
css={{
|
||||
display: '-webkit-box',
|
||||
WebkitBoxOrient: 'vertical',
|
||||
WebkitLineClamp: 2,
|
||||
whiteSpace: 'normal',
|
||||
overflow: 'hidden',
|
||||
width: '100%',
|
||||
maxWidth: 'calc(100% - 70px)',
|
||||
wordBreak: 'break-all',
|
||||
margin: 0,
|
||||
}}
|
||||
>
|
||||
{QueryList.formatQuery(resInfo)}
|
||||
</p>
|
||||
<div
|
||||
css={{
|
||||
display: 'flex',
|
||||
width: 'auto',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
margin: 0,
|
||||
flex: '0 0 auto',
|
||||
overflow: 'hidden',
|
||||
}}
|
||||
>
|
||||
<strong css={[queryStatusCss, { marginRight: 4 }]}>
|
||||
{resInfo.type === 'query' ? 'Q' : 'M'}
|
||||
</strong>
|
||||
<p css={queryStatusCss}>{resInfo.state.status}</p>
|
||||
</div>
|
||||
</li>
|
||||
);
|
||||
})}
|
||||
</ul>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import React, { ReactNode, PureComponent } from 'react';
|
||||
import type { ShouldExpandNodeInitially } from 'react-json-tree';
|
||||
import { ApiStats, QueryPreviewTabs, RtkQueryApiState } from '../types';
|
||||
import { StyleUtilsContext } from '../styles/createStylingFromTheme';
|
||||
import { TreeView, TreeViewProps } from './TreeView';
|
||||
import { renderTabPanelId, renderTabPanelButtonId } from '../utils/a11y';
|
||||
|
||||
|
@ -39,42 +38,54 @@ export class QueryPreviewApi extends PureComponent<QueryPreviewApiProps> {
|
|||
const hasQueries = Object.keys(apiState.queries).length > 0;
|
||||
|
||||
return (
|
||||
<StyleUtilsContext.Consumer>
|
||||
{({ styling }) => (
|
||||
<article {...rootProps} {...styling('tabContent')}>
|
||||
<h2>{apiState.config.reducerPath}</h2>
|
||||
<article
|
||||
{...rootProps}
|
||||
css={(theme) => ({
|
||||
display: 'block',
|
||||
overflowY: 'auto',
|
||||
padding: '0.5em 0',
|
||||
color: theme.TAB_CONTENT_COLOR,
|
||||
'& h2': {
|
||||
color: theme.ULIST_STRONG_COLOR,
|
||||
padding: '0.5em 1em',
|
||||
fontWeight: 700,
|
||||
},
|
||||
'& h3': {
|
||||
color: theme.ULIST_STRONG_COLOR,
|
||||
},
|
||||
})}
|
||||
>
|
||||
<h2>{apiState.config.reducerPath}</h2>
|
||||
<TreeView
|
||||
before={<h3>State</h3>}
|
||||
data={apiState}
|
||||
shouldExpandNodeInitially={this.shouldExpandApiStateNode}
|
||||
isWideLayout={isWideLayout}
|
||||
/>
|
||||
{apiStats && (
|
||||
<>
|
||||
<TreeView
|
||||
before={<h3>State</h3>}
|
||||
data={apiState}
|
||||
shouldExpandNodeInitially={this.shouldExpandApiStateNode}
|
||||
before={<h3>Tally</h3>}
|
||||
data={apiStats.tally}
|
||||
isWideLayout={isWideLayout}
|
||||
/>
|
||||
{apiStats && (
|
||||
<>
|
||||
<TreeView
|
||||
before={<h3>Tally</h3>}
|
||||
data={apiStats.tally}
|
||||
isWideLayout={isWideLayout}
|
||||
/>
|
||||
{hasQueries && (
|
||||
<TreeView
|
||||
before={<h3>Queries Timings</h3>}
|
||||
data={apiStats.timings.queries}
|
||||
isWideLayout={isWideLayout}
|
||||
/>
|
||||
)}
|
||||
{hasMutations && (
|
||||
<TreeView
|
||||
before={<h3>Mutations Timings</h3>}
|
||||
data={apiStats.timings.mutations}
|
||||
isWideLayout={isWideLayout}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
{hasQueries && (
|
||||
<TreeView
|
||||
before={<h3>Queries Timings</h3>}
|
||||
data={apiStats.timings.queries}
|
||||
isWideLayout={isWideLayout}
|
||||
/>
|
||||
)}
|
||||
</article>
|
||||
{hasMutations && (
|
||||
<TreeView
|
||||
before={<h3>Mutations Timings</h3>}
|
||||
data={apiStats.timings.mutations}
|
||||
isWideLayout={isWideLayout}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</StyleUtilsContext.Consumer>
|
||||
</article>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import React, { ReactNode } from 'react';
|
||||
import { StyleUtilsContext } from '../styles/createStylingFromTheme';
|
||||
import { QueryPreviewTabs, TabOption } from '../types';
|
||||
import { renderTabPanelButtonId } from '../utils/a11y';
|
||||
import { emptyArray } from '../utils/object';
|
||||
|
@ -24,35 +23,92 @@ export class QueryPreviewHeader extends React.Component<QueryPreviewHeaderProps>
|
|||
const { tabs, selectedTab, renderTabLabel } = this.props;
|
||||
|
||||
return (
|
||||
<StyleUtilsContext.Consumer>
|
||||
{({ styling }) => (
|
||||
<div {...styling('previewHeader')}>
|
||||
<div {...styling('tabSelector')}>
|
||||
{tabs.map((tab) => (
|
||||
<button
|
||||
type="button"
|
||||
id={renderTabPanelButtonId(tab.value)}
|
||||
aria-selected={tab.value === selectedTab}
|
||||
role={'tab'}
|
||||
onClick={() => this.handleTabClick(tab)}
|
||||
key={tab.value}
|
||||
{...styling(
|
||||
[
|
||||
'selectorButton',
|
||||
tab.value === selectedTab && 'selectorButtonSelected',
|
||||
],
|
||||
tab.value === selectedTab,
|
||||
)}
|
||||
>
|
||||
<span>
|
||||
{renderTabLabel ? renderTabLabel(tab) : tab.label}
|
||||
</span>
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</StyleUtilsContext.Consumer>
|
||||
<div
|
||||
css={(theme) => ({
|
||||
flex: '0 0 30px',
|
||||
padding: '5px 4px',
|
||||
alignItems: 'center',
|
||||
borderBottomWidth: '1px',
|
||||
borderBottomStyle: 'solid',
|
||||
|
||||
backgroundColor: theme.HEADER_BACKGROUND_COLOR,
|
||||
borderBottomColor: theme.HEADER_BORDER_COLOR,
|
||||
})}
|
||||
>
|
||||
<div
|
||||
css={{
|
||||
display: 'flex',
|
||||
width: '100%',
|
||||
justifyContent: 'flex-end',
|
||||
overflow: 'hidden',
|
||||
'& > *': {
|
||||
flex: '0 1 auto',
|
||||
},
|
||||
}}
|
||||
>
|
||||
{tabs.map((tab) => (
|
||||
<button
|
||||
type="button"
|
||||
id={renderTabPanelButtonId(tab.value)}
|
||||
aria-selected={tab.value === selectedTab}
|
||||
role={'tab'}
|
||||
onClick={() => this.handleTabClick(tab)}
|
||||
key={tab.value}
|
||||
css={[
|
||||
(theme) => ({
|
||||
cursor: 'pointer',
|
||||
position: 'relative',
|
||||
height: '33px',
|
||||
padding: '0 8px',
|
||||
display: 'inline-flex',
|
||||
alignItems: 'center',
|
||||
boxShadow: 'none',
|
||||
outline: 'none',
|
||||
color: theme.TEXT_COLOR,
|
||||
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,
|
||||
|
||||
'& > *': {
|
||||
display: '-webkit-box',
|
||||
boxOrient: 'vertical',
|
||||
WebkitLineClamp: 1,
|
||||
overflow: 'hidden',
|
||||
wordBreak: 'break-all',
|
||||
WebkitBoxPack: 'end',
|
||||
paddingBottom: 0,
|
||||
},
|
||||
}),
|
||||
tab.value === selectedTab &&
|
||||
((theme) => ({
|
||||
backgroundColor: theme.TAB_BACK_SELECTED_COLOR,
|
||||
})),
|
||||
]}
|
||||
>
|
||||
<span>{renderTabLabel ? renderTabLabel(tab) : tab.label}</span>
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import React, { CSSProperties } from 'react';
|
||||
import { ArrowUpIcon } from './ArrowUpIcon';
|
||||
import { StyleUtilsContext } from '../styles/createStylingFromTheme';
|
||||
|
||||
export interface SortOrderButtonProps {
|
||||
readonly isAsc?: boolean;
|
||||
|
@ -28,19 +27,36 @@ export function SortOrderButton({
|
|||
};
|
||||
|
||||
return (
|
||||
<StyleUtilsContext.Consumer>
|
||||
{({ styling }) => (
|
||||
<button
|
||||
type="button"
|
||||
id={id}
|
||||
onClick={handleButtonClick}
|
||||
aria-pressed={isAsc}
|
||||
{...styling(['sortButton'])}
|
||||
>
|
||||
<ArrowUpIcon style={arrowStyles} />
|
||||
{buttonLabel}
|
||||
</button>
|
||||
)}
|
||||
</StyleUtilsContext.Consumer>
|
||||
<button
|
||||
type="button"
|
||||
id={id}
|
||||
onClick={handleButtonClick}
|
||||
aria-pressed={isAsc}
|
||||
css={(theme) => ({
|
||||
display: 'flex',
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'center',
|
||||
flexFlow: 'row nowrap',
|
||||
cursor: 'pointer',
|
||||
position: 'relative',
|
||||
padding: '0 8px',
|
||||
color: theme.TEXT_COLOR,
|
||||
borderStyle: 'solid',
|
||||
borderWidth: '1px',
|
||||
borderRadius: '3px',
|
||||
backgroundColor: theme.TAB_BACK_COLOR,
|
||||
borderColor: theme.TAB_BORDER_COLOR,
|
||||
height: 30,
|
||||
fontSize: 12,
|
||||
width: 64,
|
||||
|
||||
'&:active': {
|
||||
backgroundColor: theme.TAB_BACK_SELECTED_COLOR,
|
||||
},
|
||||
})}
|
||||
>
|
||||
<ArrowUpIcon style={arrowStyles} />
|
||||
{buttonLabel}
|
||||
</button>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,13 +1,9 @@
|
|||
import { createSelector, Selector } from '@reduxjs/toolkit';
|
||||
import React, { ComponentProps, ReactNode } from 'react';
|
||||
import { JSONTree } from 'react-json-tree';
|
||||
import { Base16Theme, StylingFunction } from 'react-base16-styling';
|
||||
import { DATA_TYPE_KEY } from '../monitor-config';
|
||||
import {
|
||||
getJsonTreeTheme,
|
||||
StyleUtilsContext,
|
||||
} from '../styles/createStylingFromTheme';
|
||||
import { createTreeItemLabelRenderer, getItemString } from '../styles/tree';
|
||||
import { Base16Theme } from 'react-base16-styling';
|
||||
import { getJsonTreeTheme, StyleUtilsContext } from '../styles/themes';
|
||||
import { getItemString, labelRenderer } from '../styles/tree';
|
||||
import { identity } from '../utils/object';
|
||||
|
||||
export interface TreeViewProps
|
||||
|
@ -39,28 +35,6 @@ export class TreeView extends React.PureComponent<TreeViewProps> {
|
|||
},
|
||||
};
|
||||
|
||||
readonly selectLabelRenderer: Selector<
|
||||
StylingFunction,
|
||||
ReturnType<typeof createTreeItemLabelRenderer>,
|
||||
never
|
||||
> = createSelector<
|
||||
[(stylingFunction: StylingFunction) => StylingFunction],
|
||||
ReturnType<typeof createTreeItemLabelRenderer>
|
||||
>(identity, createTreeItemLabelRenderer);
|
||||
|
||||
readonly selectGetItemString: Selector<
|
||||
StylingFunction,
|
||||
(type: string, data: unknown) => ReactNode,
|
||||
never
|
||||
> = createSelector<
|
||||
[(stylingFunction: StylingFunction) => StylingFunction],
|
||||
(type: string, data: unknown) => ReactNode
|
||||
>(
|
||||
identity,
|
||||
(styling) => (type, data) =>
|
||||
getItemString(styling, type, data, DATA_TYPE_KEY, false),
|
||||
);
|
||||
|
||||
readonly selectTheme: Selector<
|
||||
Base16Theme,
|
||||
ReturnType<typeof getJsonTreeTheme>,
|
||||
|
@ -88,18 +62,25 @@ export class TreeView extends React.PureComponent<TreeViewProps> {
|
|||
|
||||
return (
|
||||
<StyleUtilsContext.Consumer>
|
||||
{({ styling, invertTheme, base16Theme }) => {
|
||||
{({ invertTheme, base16Theme }) => {
|
||||
return (
|
||||
<div {...rootProps} {...styling('treeWrapper')}>
|
||||
<div
|
||||
{...rootProps}
|
||||
css={{
|
||||
overflowX: 'auto',
|
||||
overflowY: 'auto',
|
||||
padding: '0.5em 1em',
|
||||
}}
|
||||
>
|
||||
{before}
|
||||
<JSONTree
|
||||
keyPath={keyPath}
|
||||
shouldExpandNodeInitially={shouldExpandNodeInitially}
|
||||
data={data}
|
||||
labelRenderer={this.selectLabelRenderer(styling)}
|
||||
labelRenderer={labelRenderer}
|
||||
theme={this.selectTheme(base16Theme)}
|
||||
invertTheme={invertTheme}
|
||||
getItemString={this.selectGetItemString(styling)}
|
||||
getItemString={getItemString}
|
||||
hideRoot={hideRoot}
|
||||
/>
|
||||
{after}
|
||||
|
|
|
@ -1,12 +1,30 @@
|
|||
import * as React from 'react';
|
||||
import { StyleUtilsContext } from '../styles/createStylingFromTheme';
|
||||
|
||||
export type UListProps = React.HTMLAttributes<HTMLUListElement>;
|
||||
|
||||
export function UList(props: UListProps): JSX.Element {
|
||||
return (
|
||||
<StyleUtilsContext.Consumer>
|
||||
{({ styling }) => <ul {...props} {...styling('uList')} />}
|
||||
</StyleUtilsContext.Consumer>
|
||||
<ul
|
||||
{...props}
|
||||
css={(theme) => ({
|
||||
listStyle: 'none',
|
||||
padding: '0 0 0 1em',
|
||||
color: theme.ULIST_COLOR,
|
||||
'& > li': {
|
||||
listStyle: 'none',
|
||||
},
|
||||
'& > li::before': {
|
||||
content: '"\\2022"',
|
||||
display: 'inline-block',
|
||||
paddingRight: '0.5em',
|
||||
color: theme.ULIST_DISC_COLOR,
|
||||
fontSize: '0.8em',
|
||||
},
|
||||
|
||||
'& strong': {
|
||||
color: theme.ULIST_STRONG_COLOR,
|
||||
},
|
||||
})}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import React, { ReactNode } from 'react';
|
||||
import { StyleUtilsContext } from '../styles/createStylingFromTheme';
|
||||
import { createTreeItemLabelRenderer } from '../styles/tree';
|
||||
import type { Interpolation, Theme } from '@emotion/react';
|
||||
import {
|
||||
QueryPreviewTabs,
|
||||
RtkResourceInfo,
|
||||
|
@ -26,7 +25,6 @@ import {
|
|||
} from '../components/QueryPreviewTags';
|
||||
import { NoRtkQueryApi } from '../components/NoRtkQueryApi';
|
||||
import { InspectorSelectors } from '../selectors';
|
||||
import { StylingFunction } from 'react-base16-styling';
|
||||
import { mapProps } from './mapProps';
|
||||
import {
|
||||
QueryPreviewActions,
|
||||
|
@ -38,12 +36,28 @@ import {
|
|||
QueryPreviewDataProps,
|
||||
} from '../components/QueryPreviewData';
|
||||
|
||||
const queryPreviewCss: Interpolation<Theme> = (theme) => ({
|
||||
flex: '1 1 50%',
|
||||
overflowX: 'hidden',
|
||||
oveflowY: 'auto',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
overflowY: 'hidden',
|
||||
'& pre': {
|
||||
border: 'inherit',
|
||||
borderRadius: '3px',
|
||||
lineHeight: 'inherit',
|
||||
color: 'inherit',
|
||||
},
|
||||
|
||||
backgroundColor: theme.BACKGROUND_COLOR,
|
||||
});
|
||||
|
||||
export interface QueryPreviewProps<S = unknown> {
|
||||
readonly selectedTab: QueryPreviewTabs;
|
||||
readonly hasNoApis: boolean;
|
||||
readonly onTabChange: (tab: QueryPreviewTabs) => void;
|
||||
readonly resInfo: RtkResourceInfo | null;
|
||||
readonly styling: StylingFunction;
|
||||
readonly isWideLayout: boolean;
|
||||
readonly selectorsSource: SelectorsSource<S>;
|
||||
readonly selectors: InspectorSelectors<S>;
|
||||
|
@ -163,14 +177,6 @@ const tabs: ReadonlyArray<
|
|||
];
|
||||
|
||||
export class QueryPreview<S> extends React.PureComponent<QueryPreviewProps<S>> {
|
||||
readonly labelRenderer: ReturnType<typeof createTreeItemLabelRenderer>;
|
||||
|
||||
constructor(props: QueryPreviewProps<S>) {
|
||||
super(props);
|
||||
|
||||
this.labelRenderer = createTreeItemLabelRenderer(this.props.styling);
|
||||
}
|
||||
|
||||
renderLabelWithCounter = (
|
||||
label: React.ReactText,
|
||||
counter: number,
|
||||
|
@ -211,58 +217,40 @@ export class QueryPreview<S> extends React.PureComponent<QueryPreviewProps<S>> {
|
|||
|
||||
if (!resInfo) {
|
||||
return (
|
||||
<StyleUtilsContext.Consumer>
|
||||
{({ styling }) => (
|
||||
<div {...styling('queryPreview')}>
|
||||
<QueryPreviewHeader
|
||||
selectedTab={selectedTab}
|
||||
onTabChange={onTabChange}
|
||||
tabs={
|
||||
tabs.filter((tab) =>
|
||||
isTabVisible(tab, 'default'),
|
||||
) as ReadonlyArray<
|
||||
TabOption<
|
||||
QueryPreviewTabs,
|
||||
unknown,
|
||||
RtkResourceInfo['type']
|
||||
>
|
||||
>
|
||||
}
|
||||
renderTabLabel={this.renderTabLabel}
|
||||
/>
|
||||
{hasNoApis && <NoRtkQueryApi />}
|
||||
</div>
|
||||
)}
|
||||
</StyleUtilsContext.Consumer>
|
||||
<div css={queryPreviewCss}>
|
||||
<QueryPreviewHeader
|
||||
selectedTab={selectedTab}
|
||||
onTabChange={onTabChange}
|
||||
tabs={
|
||||
tabs.filter((tab) =>
|
||||
isTabVisible(tab, 'default'),
|
||||
) as ReadonlyArray<
|
||||
TabOption<QueryPreviewTabs, unknown, RtkResourceInfo['type']>
|
||||
>
|
||||
}
|
||||
renderTabLabel={this.renderTabLabel}
|
||||
/>
|
||||
{hasNoApis && <NoRtkQueryApi />}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<StyleUtilsContext.Consumer>
|
||||
{({ styling }) => {
|
||||
return (
|
||||
<div {...styling('queryPreview')}>
|
||||
<QueryPreviewHeader
|
||||
selectedTab={selectedTab}
|
||||
onTabChange={onTabChange}
|
||||
tabs={
|
||||
tabs.filter((tab) =>
|
||||
isTabVisible(tab, resInfo.type),
|
||||
) as ReadonlyArray<
|
||||
TabOption<
|
||||
QueryPreviewTabs,
|
||||
unknown,
|
||||
RtkResourceInfo['type']
|
||||
>
|
||||
>
|
||||
}
|
||||
renderTabLabel={this.renderTabLabel}
|
||||
/>
|
||||
<TabComponent {...(this.props as QueryPreviewTabProps)} />
|
||||
</div>
|
||||
);
|
||||
}}
|
||||
</StyleUtilsContext.Consumer>
|
||||
<div css={queryPreviewCss}>
|
||||
<QueryPreviewHeader
|
||||
selectedTab={selectedTab}
|
||||
onTabChange={onTabChange}
|
||||
tabs={
|
||||
tabs.filter((tab) =>
|
||||
isTabVisible(tab, resInfo.type),
|
||||
) as ReadonlyArray<
|
||||
TabOption<QueryPreviewTabs, unknown, RtkResourceInfo['type']>
|
||||
>
|
||||
}
|
||||
renderTabLabel={this.renderTabLabel}
|
||||
/>
|
||||
<TabComponent {...(this.props as QueryPreviewTabProps)} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,6 @@ import {
|
|||
QueryFormValues,
|
||||
QueryPreviewTabs,
|
||||
RtkQueryMonitorState,
|
||||
StyleUtils,
|
||||
SelectorsSource,
|
||||
RtkResourceInfo,
|
||||
} from '../types';
|
||||
|
@ -27,7 +26,6 @@ type ForwardedMonitorProps<S, A extends Action<string>> = Pick<
|
|||
export interface RtkQueryInspectorProps<S, A extends Action<string>>
|
||||
extends ForwardedMonitorProps<S, A> {
|
||||
dispatch: Dispatch<LiftedAction<S, A, RtkQueryMonitorState>>;
|
||||
styleUtils: StyleUtils;
|
||||
}
|
||||
|
||||
type RtkQueryInspectorState<S> = {
|
||||
|
@ -111,9 +109,6 @@ class RtkQueryInspector<S, A extends Action<string>> extends PureComponent<
|
|||
|
||||
render(): ReactNode {
|
||||
const { selectorsSource, isWideLayout } = this.state;
|
||||
const {
|
||||
styleUtils: { styling },
|
||||
} = this.props;
|
||||
const allVisibleRtkResourceInfos =
|
||||
this.selectors.selectAllVisbileQueries(selectorsSource);
|
||||
|
||||
|
@ -131,10 +126,58 @@ class RtkQueryInspector<S, A extends Action<string>> extends PureComponent<
|
|||
<div
|
||||
ref={this.inspectorRef}
|
||||
data-wide-layout={+this.state.isWideLayout}
|
||||
{...styling('inspector')}
|
||||
css={(theme) => ({
|
||||
display: 'flex',
|
||||
flexFlow: 'column nowrap',
|
||||
overflow: 'hidden',
|
||||
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,
|
||||
|
||||
'&[data-wide-layout="1"]': {
|
||||
flexFlow: 'row nowrap',
|
||||
},
|
||||
})}
|
||||
>
|
||||
<div
|
||||
{...styling('querySectionWrapper')}
|
||||
css={(theme) => ({
|
||||
display: 'flex',
|
||||
flex: '0 0 auto',
|
||||
height: '50%',
|
||||
width: '100%',
|
||||
borderColor: theme.TAB_BORDER_COLOR,
|
||||
|
||||
'&[data-wide-layout="0"]': {
|
||||
borderBottomWidth: 1,
|
||||
borderStyle: 'solid',
|
||||
},
|
||||
|
||||
'&[data-wide-layout="1"]': {
|
||||
height: '100%',
|
||||
width: '44%',
|
||||
borderRightWidth: 1,
|
||||
borderStyle: 'solid',
|
||||
},
|
||||
flexFlow: 'column nowrap',
|
||||
'& > form': {
|
||||
flex: '0 0 auto',
|
||||
borderBottomWidth: '1px',
|
||||
borderBottomStyle: 'solid',
|
||||
borderColor: theme.LIST_BORDER_COLOR,
|
||||
},
|
||||
'& > ul': {
|
||||
flex: '1 1 auto',
|
||||
overflowX: 'hidden',
|
||||
overflowY: 'auto',
|
||||
maxHeight: 'calc(100% - 70px)',
|
||||
},
|
||||
})}
|
||||
data-wide-layout={+this.state.isWideLayout}
|
||||
>
|
||||
<QueryForm
|
||||
|
@ -154,7 +197,6 @@ class RtkQueryInspector<S, A extends Action<string>> extends PureComponent<
|
|||
resInfo={currentResInfo}
|
||||
selectedTab={selectorsSource.monitorState.selectedPreviewTab}
|
||||
onTabChange={this.handleTabChange}
|
||||
styling={styling}
|
||||
isWideLayout={isWideLayout}
|
||||
hasNoApis={hasNoApi}
|
||||
/>
|
||||
|
|
|
@ -1,30 +1,26 @@
|
|||
import React, { Component } from 'react';
|
||||
import { Action, AnyAction } from 'redux';
|
||||
import { ThemeProvider } from '@emotion/react';
|
||||
import RtkQueryInspector from './RtkQueryInspector';
|
||||
import { reducer } from '../reducers';
|
||||
import {
|
||||
ExternalProps,
|
||||
RtkQueryMonitorProps,
|
||||
RtkQueryMonitorState,
|
||||
StyleUtils,
|
||||
} from '../types';
|
||||
import {
|
||||
createThemeState,
|
||||
createRtkQueryMonitorThemeFromBase16Theme,
|
||||
resolveBase16Theme,
|
||||
StyleUtilsContext,
|
||||
} from '../styles/createStylingFromTheme';
|
||||
} from '../styles/themes';
|
||||
|
||||
interface DefaultProps {
|
||||
theme: string;
|
||||
invertTheme: boolean;
|
||||
}
|
||||
|
||||
export interface RtkQueryComponentState {
|
||||
readonly styleUtils: StyleUtils;
|
||||
}
|
||||
|
||||
class RtkQueryMonitor<S, A extends Action<string>> extends Component<
|
||||
RtkQueryMonitorProps<S, A>,
|
||||
RtkQueryComponentState
|
||||
RtkQueryMonitorProps<S, A>
|
||||
> {
|
||||
static update = reducer;
|
||||
|
||||
|
@ -33,14 +29,6 @@ class RtkQueryMonitor<S, A extends Action<string>> extends Component<
|
|||
invertTheme: false,
|
||||
};
|
||||
|
||||
constructor(props: RtkQueryMonitorProps<S, A>) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
styleUtils: createThemeState<S, A>(props),
|
||||
};
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
currentStateIndex,
|
||||
|
@ -48,18 +36,28 @@ class RtkQueryMonitor<S, A extends Action<string>> extends Component<
|
|||
monitorState,
|
||||
dispatch,
|
||||
actionsById,
|
||||
theme,
|
||||
invertTheme,
|
||||
} = this.props;
|
||||
|
||||
const base16Theme = resolveBase16Theme(theme);
|
||||
const styleUtils = { base16Theme, invertTheme };
|
||||
const rtkQueryMonitorTheme = createRtkQueryMonitorThemeFromBase16Theme(
|
||||
base16Theme,
|
||||
invertTheme,
|
||||
);
|
||||
|
||||
return (
|
||||
<StyleUtilsContext.Provider value={this.state.styleUtils}>
|
||||
<RtkQueryInspector<S, AnyAction>
|
||||
computedStates={computedStates}
|
||||
currentStateIndex={currentStateIndex}
|
||||
monitorState={monitorState}
|
||||
dispatch={dispatch}
|
||||
styleUtils={this.state.styleUtils}
|
||||
actionsById={actionsById}
|
||||
/>
|
||||
<StyleUtilsContext.Provider value={styleUtils}>
|
||||
<ThemeProvider theme={rtkQueryMonitorTheme}>
|
||||
<RtkQueryInspector<S, AnyAction>
|
||||
computedStates={computedStates}
|
||||
currentStateIndex={currentStateIndex}
|
||||
monitorState={monitorState}
|
||||
dispatch={dispatch}
|
||||
actionsById={actionsById}
|
||||
/>
|
||||
</ThemeProvider>
|
||||
</StyleUtilsContext.Provider>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,567 +0,0 @@
|
|||
import jss, { StyleSheet } from 'jss';
|
||||
import preset from 'jss-preset-default';
|
||||
import {
|
||||
createStyling,
|
||||
getBase16Theme,
|
||||
invertTheme,
|
||||
StylingConfig,
|
||||
StylingFunction,
|
||||
Theme,
|
||||
} from 'react-base16-styling';
|
||||
import rgba from 'hex-rgba';
|
||||
import * as reduxThemes from 'redux-devtools-themes';
|
||||
import { Action } from 'redux';
|
||||
import { createContext } from 'react';
|
||||
import type { CurriedFunction1 } from 'lodash';
|
||||
import { RtkQueryMonitorProps, StyleUtils } from '../types';
|
||||
|
||||
jss.setup(preset());
|
||||
|
||||
export const colorMap = (theme: reduxThemes.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,
|
||||
ULIST_DISC_COLOR: theme.base0D,
|
||||
ULIST_COLOR: rgba(theme.base06, 60),
|
||||
ULIST_STRONG_COLOR: theme.base0B,
|
||||
TAB_CONTENT_COLOR: rgba(theme.base06, 60),
|
||||
TOGGLE_BUTTON_BACKGROUND: rgba(theme.base00, 70),
|
||||
TOGGLE_BUTTON_SELECTED_BACKGROUND: theme.base04,
|
||||
TOGGLE_BUTTON_ERROR: rgba(theme.base08, 40),
|
||||
}) as const;
|
||||
|
||||
type Color = keyof ReturnType<typeof colorMap>;
|
||||
type ColorMap = {
|
||||
[color in Color]: string;
|
||||
};
|
||||
|
||||
const getSheetFromColorMap = (map: ColorMap) => {
|
||||
const appearanceNone = {
|
||||
'-webkit-appearance': 'none',
|
||||
};
|
||||
|
||||
return {
|
||||
inspector: {
|
||||
display: 'flex',
|
||||
flexFlow: 'column nowrap',
|
||||
overflow: 'hidden',
|
||||
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,
|
||||
|
||||
'&[data-wide-layout="1"]': {
|
||||
flexFlow: 'row nowrap',
|
||||
},
|
||||
},
|
||||
|
||||
querySectionWrapper: {
|
||||
display: 'flex',
|
||||
flex: '0 0 auto',
|
||||
height: '50%',
|
||||
width: '100%',
|
||||
borderColor: map.TAB_BORDER_COLOR,
|
||||
|
||||
'&[data-wide-layout="0"]': {
|
||||
borderBottomWidth: 1,
|
||||
borderStyle: 'solid',
|
||||
},
|
||||
|
||||
'&[data-wide-layout="1"]': {
|
||||
height: '100%',
|
||||
width: '44%',
|
||||
borderRightWidth: 1,
|
||||
borderStyle: 'solid',
|
||||
},
|
||||
flexFlow: 'column nowrap',
|
||||
'& > :first-child': {
|
||||
flex: '0 0 auto',
|
||||
'border-bottom-width': '1px',
|
||||
'border-bottom-style': 'solid',
|
||||
'border-color': map.LIST_BORDER_COLOR,
|
||||
},
|
||||
'& > :nth-child(n + 2)': {
|
||||
flex: '1 1 auto',
|
||||
overflowX: 'hidden',
|
||||
overflowY: 'auto',
|
||||
maxHeight: 'calc(100% - 70px)',
|
||||
},
|
||||
},
|
||||
|
||||
queryList: {
|
||||
listStyle: 'none',
|
||||
margin: '0',
|
||||
padding: '0',
|
||||
},
|
||||
|
||||
queryListItem: {
|
||||
'border-bottom-width': '1px',
|
||||
'border-bottom-style': 'solid',
|
||||
display: 'flex',
|
||||
'justify-content': 'space-between',
|
||||
padding: '5px 10px',
|
||||
cursor: 'pointer',
|
||||
'user-select': 'none',
|
||||
'&:last-child': {
|
||||
'border-bottom-width': 0,
|
||||
},
|
||||
overflow: 'hidden',
|
||||
maxHeight: 47,
|
||||
'border-bottom-color': map.BORDER_COLOR,
|
||||
},
|
||||
|
||||
queryListItemKey: {
|
||||
display: '-webkit-box',
|
||||
boxOrient: 'vertical',
|
||||
'-webkit-line-clamp': 2,
|
||||
whiteSpace: 'normal',
|
||||
overflow: 'hidden',
|
||||
width: '100%',
|
||||
maxWidth: 'calc(100% - 70px)',
|
||||
wordBreak: 'break-all',
|
||||
margin: 0,
|
||||
},
|
||||
|
||||
queryListHeader: {
|
||||
display: 'flex',
|
||||
padding: 4,
|
||||
flex: '0 0 auto',
|
||||
'align-items': 'center',
|
||||
'border-bottom-width': '1px',
|
||||
'border-bottom-style': 'solid',
|
||||
|
||||
'border-color': map.LIST_BORDER_COLOR,
|
||||
},
|
||||
|
||||
queryStatusWrapper: {
|
||||
display: 'flex',
|
||||
width: 'auto',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
margin: 0,
|
||||
flex: '0 0 auto',
|
||||
overflow: 'hidden',
|
||||
},
|
||||
|
||||
queryType: {
|
||||
marginRight: 4,
|
||||
},
|
||||
|
||||
queryStatus: {
|
||||
display: 'inline-flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
height: 22,
|
||||
padding: '0 6px',
|
||||
'border-radius': '3px',
|
||||
'font-size': '0.7em',
|
||||
'line-height': '1em',
|
||||
'flex-shrink': 0,
|
||||
fontWeight: 700,
|
||||
'background-color': map.ACTION_TIME_BACK_COLOR,
|
||||
color: map.ACTION_TIME_COLOR,
|
||||
},
|
||||
|
||||
queryListItemSelected: {
|
||||
'background-color': map.SELECTED_BACKGROUND_COLOR,
|
||||
},
|
||||
|
||||
tabSelector: {
|
||||
display: 'flex',
|
||||
width: '100%',
|
||||
justifyContent: 'flex-end',
|
||||
overflow: 'hidden',
|
||||
'& > *': {
|
||||
flex: '0 1 auto',
|
||||
},
|
||||
},
|
||||
|
||||
srOnly: {
|
||||
position: 'absolute',
|
||||
width: 1,
|
||||
height: 1,
|
||||
padding: 0,
|
||||
margin: '-1px',
|
||||
overflow: 'hidden',
|
||||
clip: 'rect(0,0,0,0)',
|
||||
border: 0,
|
||||
},
|
||||
|
||||
selectorButton: {
|
||||
cursor: 'pointer',
|
||||
position: 'relative',
|
||||
height: '33px',
|
||||
padding: '0 8px',
|
||||
display: 'inline-flex',
|
||||
alignItems: 'center',
|
||||
boxShadow: 'none',
|
||||
outline: 'none',
|
||||
color: map.TEXT_COLOR,
|
||||
'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,
|
||||
|
||||
'& > *': {
|
||||
display: '-webkit-box',
|
||||
boxOrient: 'vertical',
|
||||
'-webkit-line-clamp': 1,
|
||||
overflow: 'hidden',
|
||||
wordBreak: 'break-all',
|
||||
'-webkit-box-pack': 'end',
|
||||
paddingBottom: 0,
|
||||
},
|
||||
},
|
||||
|
||||
selectorButtonSmall: {
|
||||
padding: '0px 8px',
|
||||
'font-size': '0.8em',
|
||||
},
|
||||
|
||||
selectorButtonSelected: {
|
||||
'background-color': map.TAB_BACK_SELECTED_COLOR,
|
||||
},
|
||||
|
||||
sortButton: {
|
||||
display: 'flex',
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'center',
|
||||
flexFlow: 'row nowrap',
|
||||
cursor: 'pointer',
|
||||
position: 'relative',
|
||||
padding: '0 8px',
|
||||
color: map.TEXT_COLOR,
|
||||
borderStyle: 'solid',
|
||||
borderWidth: '1px',
|
||||
borderRadius: '3px',
|
||||
backgroundColor: map.TAB_BACK_COLOR,
|
||||
borderColor: map.TAB_BORDER_COLOR,
|
||||
height: 30,
|
||||
fontSize: 12,
|
||||
width: 64,
|
||||
|
||||
'&:active': {
|
||||
backgroundColor: map.TAB_BACK_SELECTED_COLOR,
|
||||
},
|
||||
},
|
||||
|
||||
toggleButton: {
|
||||
width: '24px',
|
||||
height: '24px',
|
||||
display: 'inline-block',
|
||||
flex: '0 0 auto',
|
||||
color: map.TEXT_PLACEHOLDER_COLOR,
|
||||
cursor: 'pointer',
|
||||
padding: 0,
|
||||
fontSize: '0.7em',
|
||||
letterSpacing: '-0.7px',
|
||||
outline: 'none',
|
||||
boxShadow: 'none',
|
||||
fontWeight: '700',
|
||||
border: 'none',
|
||||
|
||||
'&:hover': {
|
||||
color: map.TEXT_COLOR,
|
||||
},
|
||||
|
||||
backgroundColor: 'transparent',
|
||||
'&[aria-pressed="true"]': {
|
||||
color: map.BACKGROUND_COLOR,
|
||||
backgroundColor: map.TEXT_COLOR,
|
||||
},
|
||||
|
||||
'&[data-type="error"]': {
|
||||
color: map.TEXT_COLOR,
|
||||
backgroundColor: map.TOGGLE_BUTTON_ERROR,
|
||||
},
|
||||
},
|
||||
|
||||
queryForm: {
|
||||
display: 'flex',
|
||||
flexFlow: 'column nowrap',
|
||||
},
|
||||
sortBySection: {
|
||||
display: 'flex',
|
||||
padding: '0.4em',
|
||||
'& label': {
|
||||
display: 'flex',
|
||||
flex: '0 0 auto',
|
||||
whiteSpace: 'noWrap',
|
||||
alignItems: 'center',
|
||||
paddingRight: '0.4em',
|
||||
},
|
||||
|
||||
'& > :last-child': {
|
||||
flex: '0 0 auto',
|
||||
marginLeft: '0.4em',
|
||||
},
|
||||
},
|
||||
|
||||
querySearch: {
|
||||
maxWidth: '65%',
|
||||
'background-color': map.BACKGROUND_COLOR,
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
flexFlow: 'row nowrap',
|
||||
flex: '1 1 auto',
|
||||
paddingRight: 6,
|
||||
'& input': {
|
||||
outline: 'none',
|
||||
border: 'none',
|
||||
width: '100%',
|
||||
flex: '1 1 auto',
|
||||
padding: '5px 10px',
|
||||
'font-size': '1em',
|
||||
position: 'relative',
|
||||
fontFamily: '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,
|
||||
},
|
||||
'&::-webkit-search-cancel-button': appearanceNone,
|
||||
},
|
||||
},
|
||||
|
||||
closeButton: {
|
||||
...appearanceNone,
|
||||
border: 'none',
|
||||
outline: 'none',
|
||||
boxShadow: 'none',
|
||||
display: 'block',
|
||||
flex: '0 0 auto',
|
||||
cursor: 'pointer',
|
||||
background: 'transparent',
|
||||
position: 'relative',
|
||||
fontSize: 'inherit',
|
||||
'&[data-invisible="1"]': {
|
||||
visibility: 'hidden !important',
|
||||
},
|
||||
'&::after': {
|
||||
content: '"\u00d7"',
|
||||
display: 'block',
|
||||
padding: 4,
|
||||
fontSize: '1.2em',
|
||||
color: map.TEXT_PLACEHOLDER_COLOR,
|
||||
background: 'transparent',
|
||||
},
|
||||
'&:hover::after': {
|
||||
color: map.TEXT_COLOR,
|
||||
},
|
||||
},
|
||||
|
||||
noApiFound: {
|
||||
width: '100%',
|
||||
textAlign: 'center',
|
||||
color: map.TEXT_COLOR,
|
||||
padding: '1.4em',
|
||||
'& a': {
|
||||
fontSize: 'inherit',
|
||||
color: map.TEXT_COLOR,
|
||||
textDecoration: 'underline',
|
||||
},
|
||||
},
|
||||
|
||||
searchSelectLabel: {
|
||||
display: 'inline-block',
|
||||
padding: 4,
|
||||
borderLeft: '1px solid currentColor',
|
||||
},
|
||||
|
||||
queryPreview: {
|
||||
flex: '1 1 50%',
|
||||
overflowX: 'hidden',
|
||||
oveflowY: 'auto',
|
||||
display: 'flex',
|
||||
'flex-direction': 'column',
|
||||
'overflow-y': 'hidden',
|
||||
'& pre': {
|
||||
border: 'inherit',
|
||||
'border-radius': '3px',
|
||||
'line-height': 'inherit',
|
||||
color: 'inherit',
|
||||
},
|
||||
|
||||
'background-color': map.BACKGROUND_COLOR,
|
||||
},
|
||||
|
||||
previewHeader: {
|
||||
flex: '0 0 30px',
|
||||
padding: '5px 4px',
|
||||
'align-items': 'center',
|
||||
'border-bottom-width': '1px',
|
||||
'border-bottom-style': 'solid',
|
||||
|
||||
'background-color': map.HEADER_BACKGROUND_COLOR,
|
||||
'border-bottom-color': map.HEADER_BORDER_COLOR,
|
||||
},
|
||||
|
||||
treeItemPin: {
|
||||
'font-size': '0.7em',
|
||||
'padding-left': '5px',
|
||||
cursor: 'pointer',
|
||||
'&:hover': {
|
||||
'text-decoration': 'underline',
|
||||
},
|
||||
|
||||
color: map.PIN_COLOR,
|
||||
},
|
||||
|
||||
treeItemKey: {
|
||||
color: map.TEXT_PLACEHOLDER_COLOR,
|
||||
},
|
||||
|
||||
treeWrapper: {
|
||||
overflowX: 'auto',
|
||||
overflowY: 'auto',
|
||||
padding: '0.5em 1em',
|
||||
},
|
||||
|
||||
tabContent: {
|
||||
display: 'block',
|
||||
overflowY: 'auto',
|
||||
padding: '0.5em 0',
|
||||
color: map.TAB_CONTENT_COLOR,
|
||||
'& h2': {
|
||||
color: map.ULIST_STRONG_COLOR,
|
||||
padding: '0.5em 1em',
|
||||
fontWeight: 700,
|
||||
},
|
||||
'& h3': {
|
||||
color: map.ULIST_STRONG_COLOR,
|
||||
},
|
||||
},
|
||||
|
||||
uList: {
|
||||
listStyle: 'none',
|
||||
padding: '0 0 0 1em',
|
||||
color: map.ULIST_COLOR,
|
||||
'& > li': {
|
||||
listStyle: 'none',
|
||||
},
|
||||
'& > li::before': {
|
||||
content: '"\\2022"',
|
||||
display: 'inline-block',
|
||||
paddingRight: '0.5em',
|
||||
color: map.ULIST_DISC_COLOR,
|
||||
fontSize: '0.8em',
|
||||
},
|
||||
|
||||
'& strong': {
|
||||
color: map.ULIST_STRONG_COLOR,
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
let themeSheet: StyleSheet;
|
||||
|
||||
const getDefaultThemeStyling = (theme: reduxThemes.Base16Theme) => {
|
||||
if (themeSheet) {
|
||||
themeSheet.detach();
|
||||
}
|
||||
|
||||
themeSheet = jss
|
||||
.createStyleSheet(getSheetFromColorMap(colorMap(theme)))
|
||||
.attach();
|
||||
|
||||
return themeSheet.classes;
|
||||
};
|
||||
|
||||
export const createStylingFromTheme: CurriedFunction1<
|
||||
Theme | undefined,
|
||||
StylingFunction
|
||||
> = createStyling(getDefaultThemeStyling, {
|
||||
defaultBase16: reduxThemes.nicinabox,
|
||||
base16Themes: { ...reduxThemes },
|
||||
});
|
||||
|
||||
export function createThemeState<S, A extends Action<string>>(
|
||||
props: RtkQueryMonitorProps<S, A>,
|
||||
): StyleUtils {
|
||||
const base16Theme =
|
||||
getBase16Theme(props.theme, { ...reduxThemes }) ?? reduxThemes.nicinabox;
|
||||
|
||||
const theme = props.invertTheme ? invertTheme(props.theme) : props.theme;
|
||||
const styling = createStylingFromTheme(theme);
|
||||
|
||||
return { base16Theme, styling, invertTheme: !!props.invertTheme };
|
||||
}
|
||||
|
||||
const mockStyling = () => ({ className: '', style: {} });
|
||||
|
||||
export const StyleUtilsContext = createContext<StyleUtils>({
|
||||
base16Theme: reduxThemes.nicinabox,
|
||||
invertTheme: false,
|
||||
styling: mockStyling,
|
||||
});
|
||||
|
||||
export function getJsonTreeTheme(
|
||||
base16Theme: reduxThemes.Base16Theme,
|
||||
): StylingConfig {
|
||||
return {
|
||||
extend: base16Theme,
|
||||
nestedNode: ({ style }, keyPath, nodeType, expanded) => ({
|
||||
style: {
|
||||
...style,
|
||||
whiteSpace: expanded ? 'inherit' : 'nowrap',
|
||||
},
|
||||
}),
|
||||
nestedNodeItemString: ({ style }, keyPath, nodeType, expanded) => ({
|
||||
style: {
|
||||
...style,
|
||||
display: expanded ? 'none' : 'inline',
|
||||
},
|
||||
}),
|
||||
};
|
||||
}
|
116
packages/redux-devtools-rtk-query-monitor/src/styles/themes.ts
Normal file
116
packages/redux-devtools-rtk-query-monitor/src/styles/themes.ts
Normal file
|
@ -0,0 +1,116 @@
|
|||
import { getBase16Theme, invertBase16Theme } from 'react-base16-styling';
|
||||
import type { Base16Theme, StylingConfig } from 'react-base16-styling';
|
||||
import rgba from 'hex-rgba';
|
||||
import * as reduxThemes from 'redux-devtools-themes';
|
||||
import { createContext } from 'react';
|
||||
import { StyleUtils } from '../types';
|
||||
|
||||
export function resolveBase16Theme(
|
||||
theme: keyof typeof reduxThemes | Base16Theme,
|
||||
) {
|
||||
return getBase16Theme(theme, reduxThemes) ?? reduxThemes.nicinabox;
|
||||
}
|
||||
|
||||
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;
|
||||
ULIST_DISC_COLOR: string;
|
||||
ULIST_COLOR: string;
|
||||
ULIST_STRONG_COLOR: string;
|
||||
TAB_CONTENT_COLOR: string;
|
||||
TOGGLE_BUTTON_BACKGROUND: string;
|
||||
TOGGLE_BUTTON_SELECTED_BACKGROUND: string;
|
||||
TOGGLE_BUTTON_ERROR: string;
|
||||
}
|
||||
}
|
||||
|
||||
export const colorMap = (theme: reduxThemes.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,
|
||||
ULIST_DISC_COLOR: theme.base0D,
|
||||
ULIST_COLOR: rgba(theme.base06, 60),
|
||||
ULIST_STRONG_COLOR: theme.base0B,
|
||||
TAB_CONTENT_COLOR: rgba(theme.base06, 60),
|
||||
TOGGLE_BUTTON_BACKGROUND: rgba(theme.base00, 70),
|
||||
TOGGLE_BUTTON_SELECTED_BACKGROUND: theme.base04,
|
||||
TOGGLE_BUTTON_ERROR: rgba(theme.base08, 40),
|
||||
}) as const;
|
||||
|
||||
export function createRtkQueryMonitorThemeFromBase16Theme(
|
||||
base16Theme: Base16Theme,
|
||||
invertTheme: boolean,
|
||||
) {
|
||||
const finalBase16Theme = invertTheme
|
||||
? invertBase16Theme(base16Theme)
|
||||
: base16Theme;
|
||||
return colorMap(finalBase16Theme);
|
||||
}
|
||||
|
||||
export const StyleUtilsContext = createContext<StyleUtils>({
|
||||
base16Theme: reduxThemes.nicinabox,
|
||||
invertTheme: false,
|
||||
});
|
||||
|
||||
export function getJsonTreeTheme(
|
||||
base16Theme: reduxThemes.Base16Theme,
|
||||
): StylingConfig {
|
||||
return {
|
||||
extend: base16Theme,
|
||||
nestedNode: ({ style }, keyPath, nodeType, expanded) => ({
|
||||
style: {
|
||||
...style,
|
||||
whiteSpace: expanded ? 'inherit' : 'nowrap',
|
||||
},
|
||||
}),
|
||||
nestedNodeItemString: ({ style }, keyPath, nodeType, expanded) => ({
|
||||
style: {
|
||||
...style,
|
||||
display: expanded ? 'none' : 'inline',
|
||||
},
|
||||
}),
|
||||
};
|
||||
}
|
|
@ -1,8 +1,8 @@
|
|||
import React, { ReactNode } from 'react';
|
||||
import { StylingFunction } from 'react-base16-styling';
|
||||
import type { LabelRenderer } from 'react-json-tree';
|
||||
import React from 'react';
|
||||
import type { GetItemString, LabelRenderer } from 'react-json-tree';
|
||||
import { isCollection, isIndexed, isKeyed } from 'immutable';
|
||||
import isIterable from '../utils/isIterable';
|
||||
import { DATA_TYPE_KEY } from '../monitor-config';
|
||||
|
||||
const IS_IMMUTABLE_KEY = '@@__IS_IMMUTABLE__@@';
|
||||
|
||||
|
@ -73,34 +73,21 @@ function getText(
|
|||
}
|
||||
}
|
||||
|
||||
export function getItemString(
|
||||
styling: StylingFunction,
|
||||
type: string,
|
||||
data: any,
|
||||
dataTypeKey: string | symbol | undefined,
|
||||
previewContent: boolean,
|
||||
isDiff?: boolean,
|
||||
): ReactNode {
|
||||
return (
|
||||
<span {...styling('treeItemHint')}>
|
||||
{data[IS_IMMUTABLE_KEY] ? 'Immutable' : ''}
|
||||
{dataTypeKey && data[dataTypeKey]
|
||||
? `${data[dataTypeKey] as string} `
|
||||
: ''}
|
||||
{getText(type, data, previewContent, isDiff)}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
export const getItemString: GetItemString = (type: string, data: any) => (
|
||||
<span>
|
||||
{data[IS_IMMUTABLE_KEY] ? 'Immutable' : ''}
|
||||
{DATA_TYPE_KEY && data[DATA_TYPE_KEY]
|
||||
? `${data[DATA_TYPE_KEY] as string} `
|
||||
: ''}
|
||||
{getText(type, data, false, undefined)}
|
||||
</span>
|
||||
);
|
||||
|
||||
export function createTreeItemLabelRenderer(
|
||||
styling: StylingFunction,
|
||||
): LabelRenderer {
|
||||
return function labelRenderer([key], nodeType, expanded) {
|
||||
return (
|
||||
<span>
|
||||
<span {...styling('treeItemKey')}>{key}</span>
|
||||
{!expanded && ': '}
|
||||
</span>
|
||||
);
|
||||
};
|
||||
}
|
||||
export const labelRenderer: LabelRenderer = ([key], nodeType, expanded) => (
|
||||
<span>
|
||||
<span css={(theme) => ({ color: theme.TEXT_PLACEHOLDER_COLOR })}>
|
||||
{key}
|
||||
</span>
|
||||
{!expanded && ': '}
|
||||
</span>
|
||||
);
|
||||
|
|
|
@ -35,7 +35,7 @@ export interface RtkQueryMonitorProps<S, A extends Action<string>>
|
|||
extends LiftedState<S, A, RtkQueryMonitorState> {
|
||||
dispatch: Dispatch<Action | LiftedAction<S, A, RtkQueryMonitorState>>;
|
||||
theme: keyof typeof themes | Base16Theme;
|
||||
invertTheme?: boolean;
|
||||
invertTheme: boolean;
|
||||
}
|
||||
|
||||
export type RtkQueryApiState = ReturnType<
|
||||
|
@ -100,7 +100,6 @@ export interface SelectorsSource<S> {
|
|||
|
||||
export interface StyleUtils {
|
||||
readonly base16Theme: Base16Theme;
|
||||
readonly styling: StylingFunction;
|
||||
readonly invertTheme: boolean;
|
||||
}
|
||||
|
||||
|
|
|
@ -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"]
|
||||
}
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
{
|
||||
"extends": "../../tsconfig.react.base.json",
|
||||
"compilerOptions": {
|
||||
"types": ["jest"]
|
||||
"types": ["jest"],
|
||||
"jsx": "react-jsx",
|
||||
"jsxImportSource": "@emotion/react"
|
||||
},
|
||||
"include": ["src", "test"],
|
||||
"exclude": ["dist"]
|
||||
|
|
156
pnpm-lock.yaml
156
pnpm-lock.yaml
|
@ -2474,12 +2474,6 @@ importers:
|
|||
immutable:
|
||||
specifier: ^4.3.4
|
||||
version: 4.3.4
|
||||
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
|
||||
|
@ -2517,6 +2511,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
|
||||
|
@ -12612,13 +12612,6 @@ packages:
|
|||
source-map-js: 1.0.2
|
||||
dev: true
|
||||
|
||||
/css-vendor@2.0.8:
|
||||
resolution: {integrity: sha512-x9Aq0XTInxrkuFeHKbYC7zWY8ai7qJ04Kxd9MnvbC1uO5DagxoHQjm4JvG+vCdXOoFtCjbL2XSZfxmoYa9uQVQ==}
|
||||
dependencies:
|
||||
'@babel/runtime': 7.23.5
|
||||
is-in-browser: 1.1.3
|
||||
dev: false
|
||||
|
||||
/css-what@6.1.0:
|
||||
resolution: {integrity: sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==}
|
||||
engines: {node: '>= 6'}
|
||||
|
@ -15220,10 +15213,6 @@ packages:
|
|||
dev: false
|
||||
optional: true
|
||||
|
||||
/hyphenate-style-name@1.0.4:
|
||||
resolution: {integrity: sha512-ygGZLjmXfPHj+ZWh6LwbC37l43MhfztxetbFCoYTM2VjkIUpeHgSNn7QIyVFj7YQ1Wl9Cbw5sholVJPzWvC2MQ==}
|
||||
dev: false
|
||||
|
||||
/iconv-lite@0.4.24:
|
||||
resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
@ -15529,10 +15518,6 @@ packages:
|
|||
engines: {node: '>=0.10.0'}
|
||||
dev: true
|
||||
|
||||
/is-in-browser@1.1.3:
|
||||
resolution: {integrity: sha512-FeXIBgG/CPGd/WUxuEyvgGTEfwiG9Z4EKGxjNMRqviiIIfsmgrpnHLffEDdwUHqNva1VEW91o3xBT/m8Elgl9g==}
|
||||
dev: false
|
||||
|
||||
/is-inside-container@1.0.0:
|
||||
resolution: {integrity: sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==}
|
||||
engines: {node: '>=14.16'}
|
||||
|
@ -16506,126 +16491,6 @@ packages:
|
|||
semver: 7.5.4
|
||||
dev: false
|
||||
|
||||
/jss-plugin-camel-case@10.10.0:
|
||||
resolution: {integrity: sha512-z+HETfj5IYgFxh1wJnUAU8jByI48ED+v0fuTuhKrPR+pRBYS2EDwbusU8aFOpCdYhtRc9zhN+PJ7iNE8pAWyPw==}
|
||||
dependencies:
|
||||
'@babel/runtime': 7.23.5
|
||||
hyphenate-style-name: 1.0.4
|
||||
jss: 10.10.0
|
||||
dev: false
|
||||
|
||||
/jss-plugin-compose@10.10.0:
|
||||
resolution: {integrity: sha512-F5kgtWpI2XfZ3Z8eP78tZEYFdgTIbpA/TMuX3a8vwrNolYtN1N4qJR/Ob0LAsqIwCMLojtxN7c7Oo/+Vz6THow==}
|
||||
dependencies:
|
||||
'@babel/runtime': 7.23.5
|
||||
jss: 10.10.0
|
||||
tiny-warning: 1.0.3
|
||||
dev: false
|
||||
|
||||
/jss-plugin-default-unit@10.10.0:
|
||||
resolution: {integrity: sha512-SvpajxIECi4JDUbGLefvNckmI+c2VWmP43qnEy/0eiwzRUsafg5DVSIWSzZe4d2vFX1u9nRDP46WCFV/PXVBGQ==}
|
||||
dependencies:
|
||||
'@babel/runtime': 7.23.5
|
||||
jss: 10.10.0
|
||||
dev: false
|
||||
|
||||
/jss-plugin-expand@10.10.0:
|
||||
resolution: {integrity: sha512-ymT62W2OyDxBxr7A6JR87vVX9vTq2ep5jZLIdUSusfBIEENLdkkc0lL/Xaq8W9s3opUq7R0sZQpzRWELrfVYzA==}
|
||||
dependencies:
|
||||
'@babel/runtime': 7.23.5
|
||||
jss: 10.10.0
|
||||
dev: false
|
||||
|
||||
/jss-plugin-extend@10.10.0:
|
||||
resolution: {integrity: sha512-sKYrcMfr4xxigmIwqTjxNcHwXJIfvhvjTNxF+Tbc1NmNdyspGW47Ey6sGH8BcQ4FFQhLXctpWCQSpDwdNmXSwg==}
|
||||
dependencies:
|
||||
'@babel/runtime': 7.23.5
|
||||
jss: 10.10.0
|
||||
tiny-warning: 1.0.3
|
||||
dev: false
|
||||
|
||||
/jss-plugin-global@10.10.0:
|
||||
resolution: {integrity: sha512-icXEYbMufiNuWfuazLeN+BNJO16Ge88OcXU5ZDC2vLqElmMybA31Wi7lZ3lf+vgufRocvPj8443irhYRgWxP+A==}
|
||||
dependencies:
|
||||
'@babel/runtime': 7.23.5
|
||||
jss: 10.10.0
|
||||
dev: false
|
||||
|
||||
/jss-plugin-nested@10.10.0:
|
||||
resolution: {integrity: sha512-9R4JHxxGgiZhurDo3q7LdIiDEgtA1bTGzAbhSPyIOWb7ZubrjQe8acwhEQ6OEKydzpl8XHMtTnEwHXCARLYqYA==}
|
||||
dependencies:
|
||||
'@babel/runtime': 7.23.5
|
||||
jss: 10.10.0
|
||||
tiny-warning: 1.0.3
|
||||
dev: false
|
||||
|
||||
/jss-plugin-props-sort@10.10.0:
|
||||
resolution: {integrity: sha512-5VNJvQJbnq/vRfje6uZLe/FyaOpzP/IH1LP+0fr88QamVrGJa0hpRRyAa0ea4U/3LcorJfBFVyC4yN2QC73lJg==}
|
||||
dependencies:
|
||||
'@babel/runtime': 7.23.5
|
||||
jss: 10.10.0
|
||||
dev: false
|
||||
|
||||
/jss-plugin-rule-value-function@10.10.0:
|
||||
resolution: {integrity: sha512-uEFJFgaCtkXeIPgki8ICw3Y7VMkL9GEan6SqmT9tqpwM+/t+hxfMUdU4wQ0MtOiMNWhwnckBV0IebrKcZM9C0g==}
|
||||
dependencies:
|
||||
'@babel/runtime': 7.23.5
|
||||
jss: 10.10.0
|
||||
tiny-warning: 1.0.3
|
||||
dev: false
|
||||
|
||||
/jss-plugin-rule-value-observable@10.10.0:
|
||||
resolution: {integrity: sha512-ZLMaYrR3QE+vD7nl3oNXuj79VZl9Kp8/u6A1IbTPDcuOu8b56cFdWRZNZ0vNr8jHewooEeq2doy8Oxtymr2ZPA==}
|
||||
dependencies:
|
||||
'@babel/runtime': 7.23.5
|
||||
jss: 10.10.0
|
||||
symbol-observable: 1.2.0
|
||||
dev: false
|
||||
|
||||
/jss-plugin-template@10.10.0:
|
||||
resolution: {integrity: sha512-ocXZBIOJOA+jISPdsgkTs8wwpK6UbsvtZK5JI7VUggTD6LWKbtoxUzadd2TpfF+lEtlhUmMsCkTRNkITdPKa6w==}
|
||||
dependencies:
|
||||
'@babel/runtime': 7.23.5
|
||||
jss: 10.10.0
|
||||
tiny-warning: 1.0.3
|
||||
dev: false
|
||||
|
||||
/jss-plugin-vendor-prefixer@10.10.0:
|
||||
resolution: {integrity: sha512-UY/41WumgjW8r1qMCO8l1ARg7NHnfRVWRhZ2E2m0DMYsr2DD91qIXLyNhiX83hHswR7Wm4D+oDYNC1zWCJWtqg==}
|
||||
dependencies:
|
||||
'@babel/runtime': 7.23.5
|
||||
css-vendor: 2.0.8
|
||||
jss: 10.10.0
|
||||
dev: false
|
||||
|
||||
/jss-preset-default@10.10.0:
|
||||
resolution: {integrity: sha512-GL175Wt2FGhjE+f+Y3aWh+JioL06/QWFgZp53CbNNq6ZkVU0TDplD8Bxm9KnkotAYn3FlplNqoW5CjyLXcoJ7Q==}
|
||||
dependencies:
|
||||
'@babel/runtime': 7.23.5
|
||||
jss: 10.10.0
|
||||
jss-plugin-camel-case: 10.10.0
|
||||
jss-plugin-compose: 10.10.0
|
||||
jss-plugin-default-unit: 10.10.0
|
||||
jss-plugin-expand: 10.10.0
|
||||
jss-plugin-extend: 10.10.0
|
||||
jss-plugin-global: 10.10.0
|
||||
jss-plugin-nested: 10.10.0
|
||||
jss-plugin-props-sort: 10.10.0
|
||||
jss-plugin-rule-value-function: 10.10.0
|
||||
jss-plugin-rule-value-observable: 10.10.0
|
||||
jss-plugin-template: 10.10.0
|
||||
jss-plugin-vendor-prefixer: 10.10.0
|
||||
dev: false
|
||||
|
||||
/jss@10.10.0:
|
||||
resolution: {integrity: sha512-cqsOTS7jqPsPMjtKYDUpdFC0AbhYFLTcuGRqymgmdJIeQ8cH7+AgX7YSgQy79wXloZq2VvATYxUOUQEvS1V/Zw==}
|
||||
dependencies:
|
||||
'@babel/runtime': 7.23.5
|
||||
csstype: 3.1.2
|
||||
is-in-browser: 1.1.3
|
||||
tiny-warning: 1.0.3
|
||||
dev: false
|
||||
|
||||
/jstransformer@1.0.0:
|
||||
resolution: {integrity: sha512-C9YK3Rf8q6VAPDCCU9fnqo3mAfOH6vUGnMcP4AQAYIEpWtfGLpwOTmZ+igtdK5y+VvI2n3CyYSzy4Qh34eq24A==}
|
||||
dependencies:
|
||||
|
@ -20394,11 +20259,6 @@ packages:
|
|||
webpack: 5.89.0(@swc/core@1.3.100)(esbuild@0.18.20)
|
||||
dev: true
|
||||
|
||||
/symbol-observable@1.2.0:
|
||||
resolution: {integrity: sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
dev: false
|
||||
|
||||
/symbol-tree@3.2.4:
|
||||
resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==}
|
||||
dev: true
|
||||
|
@ -20634,10 +20494,6 @@ packages:
|
|||
/tiny-invariant@1.3.1:
|
||||
resolution: {integrity: sha512-AD5ih2NlSssTCwsMznbvwMZpJ1cbhkGd2uueNxzv2jDlEeZdU04JQfRnggJQ8DrcVBGjAsCKwFBbDlVNtEMlzw==}
|
||||
|
||||
/tiny-warning@1.0.3:
|
||||
resolution: {integrity: sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==}
|
||||
dev: false
|
||||
|
||||
/titleize@3.0.0:
|
||||
resolution: {integrity: sha512-KxVu8EYHDPBdUYdKZdKtU2aj2XfEx9AfjXxE/Aj0vT06w2icA09Vus1rh6eSu1y01akYg6BjIK/hxyLJINoMLQ==}
|
||||
engines: {node: '>=12'}
|
||||
|
|
Loading…
Reference in New Issue
Block a user