mirror of
https://github.com/EnixCoda/Gitako.git
synced 2026-03-11 08:54:44 +00:00
Merge branch 'develop' into feature/safari
This commit is contained in:
commit
6706ddd4dc
83 changed files with 3855 additions and 3518 deletions
12
.github/FUNDING.yml
vendored
Normal file
12
.github/FUNDING.yml
vendored
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
# These are supported funding model platforms
|
||||
|
||||
github: enixcoda
|
||||
patreon: enixcoda
|
||||
open_collective: enixcoda
|
||||
ko_fi: # Replace with a single Ko-fi username
|
||||
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
|
||||
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
|
||||
liberapay: # Replace with a single Liberapay username
|
||||
issuehunt: # Replace with a single IssueHunt username
|
||||
otechie: # Replace with a single Otechie username
|
||||
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
|
||||
|
|
@ -4,6 +4,6 @@ describe(`in GitHub homepage`, () => {
|
|||
beforeAll(() => page.goto('https://github.com'))
|
||||
|
||||
it('should not render Gitako', async () => {
|
||||
await expectToNotFind('.gitako-side-bar .gitako-position-wrapper')
|
||||
await expectToNotFind('.gitako-side-bar .gitako-side-bar-body-wrapper')
|
||||
})
|
||||
})
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ describe(`in Gitako project page`, () => {
|
|||
beforeAll(() => page.goto('https://github.com/EnixCoda/Gitako/pull/71'))
|
||||
|
||||
it('should render Gitako', async () => {
|
||||
await expectToFind('.gitako-side-bar .gitako-position-wrapper')
|
||||
await expectToFind('.gitako-side-bar .gitako-side-bar-body-wrapper')
|
||||
})
|
||||
|
||||
it('should render file list', async () => {
|
||||
|
|
|
|||
|
|
@ -4,8 +4,6 @@ describe(`in Gitako project page`, () => {
|
|||
beforeAll(() => page.goto('https://github.com/EnixCoda/Gitako/commits/develop'))
|
||||
|
||||
it('should not break go back in history', async () => {
|
||||
// temporarily skip this test as GitHub has unexpected PJAX behaviors
|
||||
return
|
||||
for (let i = 0; i < 3; i++) {
|
||||
const commitLinks = await page.$$(
|
||||
`#js-repo-pjax-container .TimelineItem-body ol li > div:nth-child(1) a[href*="/commit/"]`,
|
||||
|
|
@ -1,18 +1,27 @@
|
|||
import { patientClick, selectFileTreeItem, sleep, waitForLegacyPJAXRedirect } from '../utils'
|
||||
import {
|
||||
collapseFloatModeSidebar,
|
||||
expandFloatModeSidebar,
|
||||
patientClick,
|
||||
selectFileTreeItem,
|
||||
sleep,
|
||||
waitForLegacyPJAXRedirect,
|
||||
} from '../utils'
|
||||
|
||||
describe(`in Gitako project page`, () => {
|
||||
beforeAll(() => page.goto('https://github.com/EnixCoda/Gitako/src'))
|
||||
beforeAll(() => page.goto('https://github.com/EnixCoda/Gitako/tree/develop/src'))
|
||||
|
||||
it('should work with PJAX', async () => {
|
||||
await sleep(3000)
|
||||
|
||||
await patientClick(page, selectFileTreeItem('src/analytics.ts'))
|
||||
await expandFloatModeSidebar()
|
||||
await patientClick(selectFileTreeItem('src/analytics.ts'))
|
||||
await waitForLegacyPJAXRedirect()
|
||||
await collapseFloatModeSidebar()
|
||||
|
||||
await page.click('a[data-selected-links^="repo_issues "]')
|
||||
await waitForLegacyPJAXRedirect()
|
||||
|
||||
await page.click('a[data-tab-item="issues-tab"]')
|
||||
await waitForLegacyPJAXRedirect()
|
||||
|
||||
await page.click('a[data-tab-item="pull-requests-tab"]')
|
||||
await page.click('a[data-selected-links^="repo_pulls "]')
|
||||
await waitForLegacyPJAXRedirect()
|
||||
|
||||
page.goBack()
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
import {
|
||||
expandFloatModeSidebar,
|
||||
expectToFind,
|
||||
expectToNotFind,
|
||||
patientClick,
|
||||
|
|
@ -12,7 +13,9 @@ describe(`in Gitako project page`, () => {
|
|||
|
||||
it('should work with PJAX', async () => {
|
||||
await sleep(3000)
|
||||
await patientClick(page, selectFileTreeItem('.babelrc'))
|
||||
|
||||
await expandFloatModeSidebar()
|
||||
await patientClick(selectFileTreeItem('.babelrc'))
|
||||
await waitForPJAXAPIRedirect()
|
||||
|
||||
// The selector for file content
|
||||
|
|
@ -1,10 +1,16 @@
|
|||
import { expectToFind, expectToNotFind, scroll, selectFileTreeItem } from '../utils'
|
||||
import {
|
||||
expandFloatModeSidebar,
|
||||
expectToFind,
|
||||
expectToNotFind,
|
||||
scroll,
|
||||
selectFileTreeItem,
|
||||
} from '../utils'
|
||||
|
||||
describe(`in Gitako project page`, () => {
|
||||
beforeAll(() => page.goto('https://github.com/EnixCoda/Gitako'))
|
||||
|
||||
it('should render Gitako', async () => {
|
||||
await expectToFind('.gitako-side-bar .gitako-position-wrapper')
|
||||
await expectToFind('.gitako-side-bar .gitako-side-bar-body-wrapper')
|
||||
})
|
||||
|
||||
it('should render file list', async () => {
|
||||
|
|
@ -12,6 +18,8 @@ describe(`in Gitako project page`, () => {
|
|||
})
|
||||
|
||||
it('should render while scroll', async () => {
|
||||
await expandFloatModeSidebar()
|
||||
|
||||
const filesEle = await page.waitForSelector('.gitako-side-bar .files')
|
||||
// node of tsconfig.json should NOT be rendered before scroll down
|
||||
await expectToNotFind(selectFileTreeItem('tsconfig.json'))
|
||||
|
|
@ -1,5 +1,3 @@
|
|||
import { Page } from 'puppeteer'
|
||||
|
||||
export async function expectToFind(selector: string) {
|
||||
await expect(page.waitForSelector(selector)).resolves.not.toBeNull()
|
||||
}
|
||||
|
|
@ -82,7 +80,26 @@ export function selectFileTreeItem(path: string): string {
|
|||
return `.gitako-side-bar .files a[title="${path}"]`
|
||||
}
|
||||
|
||||
export async function patientClick(page: Page, selector: string) {
|
||||
export async function patientClick(selector: string) {
|
||||
await page.waitForSelector(selector)
|
||||
await page.click(selector)
|
||||
}
|
||||
|
||||
export async function expandFloatModeSidebar() {
|
||||
const rect = await (await page.$('.gitako-toggle-show-button'))?.evaluate(button => {
|
||||
const { x, y, width, height } = button.getBoundingClientRect()
|
||||
// pass required properties to avoid serialization issues
|
||||
return { x, y, width, height }
|
||||
})
|
||||
if (rect) {
|
||||
await page.mouse.move(rect.x + rect.width / 2, rect.y + rect.height / 2)
|
||||
await sleep(500)
|
||||
}
|
||||
}
|
||||
|
||||
export async function collapseFloatModeSidebar() {
|
||||
await page.mouse.move(600, 600, {
|
||||
steps: 100,
|
||||
})
|
||||
await sleep(500)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ module.exports = {
|
|||
// globals: {},
|
||||
|
||||
// The maximum amount of workers used to run your tests. Can be specified as % or a number. E.g. maxWorkers: 10% will use 10% of your CPU amount + 1 as the maximum worker number. maxWorkers: 2 will use a maximum of 2 workers.
|
||||
maxWorkers: 1, // more than 1 workers may make tabs in background and never renders Gitako's file items.
|
||||
maxWorkers: 8,
|
||||
|
||||
// An array of directory names to be searched recursively up from the requiring module's location
|
||||
// moduleDirectories: [
|
||||
|
|
|
|||
7
jest.non.parallel.config.js
Normal file
7
jest.non.parallel.config.js
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
const baseConfig = require('./jest.config')
|
||||
|
||||
module.exports = {
|
||||
...baseConfig,
|
||||
maxWorkers: 1,
|
||||
testMatch: ['**/__tests__/non-parallel-cases/*.ts?(x)'],
|
||||
}
|
||||
16
package.json
16
package.json
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "gitako",
|
||||
"version": "2.7.1",
|
||||
"version": "3.1.0",
|
||||
"description": "File tree for GitHub, and more than that.",
|
||||
"repository": "https://github.com/EnixCoda/Gitako",
|
||||
"author": "EnixCoda",
|
||||
|
|
@ -14,13 +14,15 @@
|
|||
"postinstall": "rm -rf node_modules/@types/react-native && node scripts/fix-pjax-api",
|
||||
"build": "VERSION=v$(node scripts/get-version.js) NODE_ENV=production webpack",
|
||||
"roll": "make release",
|
||||
"test": "NODE_ENV=test jest"
|
||||
"test": "yarn run test:parallel && yarn run test:non-parallel",
|
||||
"test:parallel": "NODE_ENV=test jest",
|
||||
"test:non-parallel": "NODE_ENV=test jest --config jest.non.parallel.config.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@primer/components": "^22.0.2",
|
||||
"@primer/css": "^15.2.0",
|
||||
"@primer/octicons-react": "^10.0.0",
|
||||
"@sentry/browser": "^5.12.1",
|
||||
"@sentry/browser": "^6.3.6",
|
||||
"@types/history": "^4.7.5",
|
||||
"@types/ini": "^1.3.30",
|
||||
"@types/js-base64": "^2.3.1",
|
||||
|
|
@ -35,8 +37,8 @@
|
|||
"nprogress": "^0.2.0",
|
||||
"pjax-api": "^3.33.0",
|
||||
"react": "^17.0.1",
|
||||
"react-dom": "^17.0.1",
|
||||
"react-use": "^13.8.0",
|
||||
"react-dom": "^17.0.2",
|
||||
"react-use": "^15.3.0",
|
||||
"react-window": "^1.8.5",
|
||||
"styled-components": "^5.2.0",
|
||||
"webext-domain-permission-toggle": "^1.0.0",
|
||||
|
|
@ -51,7 +53,7 @@
|
|||
"@babel/preset-env": "^7.3.4",
|
||||
"@babel/preset-react": "^7.0.0",
|
||||
"@babel/preset-typescript": "^7.3.3",
|
||||
"@sentry/cli": "^1.51.0",
|
||||
"@sentry/cli": "^1.64.2",
|
||||
"@types/firefox-webext-browser": "^70.0.1",
|
||||
"@types/jest": "^24.0.25",
|
||||
"@types/node": "^11.10.4",
|
||||
|
|
@ -71,7 +73,7 @@
|
|||
"raw-loader": "^4.0.0",
|
||||
"sass": "^1.26.2",
|
||||
"sass-loader": "^8.0.2",
|
||||
"typescript": "^4.0.3",
|
||||
"typescript": "^4.2.4",
|
||||
"uglifyjs-webpack-plugin": "^2.1.2",
|
||||
"url-loader": "^1.1.2",
|
||||
"web-ext": "^4.2.0",
|
||||
|
|
|
|||
|
|
@ -52,6 +52,7 @@ const sentryOptions: Sentry.BrowserOptions = {
|
|||
}
|
||||
return breadcrumb
|
||||
},
|
||||
autoSessionTracking: false, // this avoids the request when calling `init`
|
||||
}
|
||||
Sentry.init(sentryOptions)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,12 +1,16 @@
|
|||
import { useConfigs } from 'containers/ConfigsContext'
|
||||
import { GITHUB_OAUTH } from 'env'
|
||||
import { platform } from 'platforms'
|
||||
import { GitHub } from 'platforms/GitHub'
|
||||
import * as React from 'react'
|
||||
|
||||
export function AccessDeniedDescription({ hasToken }: { hasToken: boolean }) {
|
||||
export function AccessDeniedDescription() {
|
||||
const configContext = useConfigs()
|
||||
const hasToken = Boolean(configContext.value.accessToken)
|
||||
|
||||
return (
|
||||
<div className={'description'}>
|
||||
<h5>Access Denied</h5>
|
||||
<div className={'description-area'}>
|
||||
<h2>Access Denied</h2>
|
||||
{hasToken ? (
|
||||
<>
|
||||
<p>
|
||||
|
|
|
|||
|
|
@ -10,13 +10,13 @@ const className = 'clippy-wrapper'
|
|||
export const ClippyClassName = className
|
||||
|
||||
export function Clippy({ codeSnippetElement }: Props) {
|
||||
const [status, setStatus] = React.useState<'normal' | 'success' | 'fail'>('normal')
|
||||
const [state, setState] = React.useState<'normal' | 'success' | 'fail'>('normal')
|
||||
React.useEffect(() => {
|
||||
const timer = window.setTimeout(() => {
|
||||
setStatus('normal')
|
||||
setState('normal')
|
||||
}, 1000)
|
||||
return () => window.clearTimeout(timer)
|
||||
}, [status])
|
||||
}, [state])
|
||||
|
||||
// Temporary fix:
|
||||
// React moved root node of event delegation since v17
|
||||
|
|
@ -26,7 +26,7 @@ export function Clippy({ codeSnippetElement }: Props) {
|
|||
const element = elementRef.current
|
||||
if (element) {
|
||||
function onClippyClick() {
|
||||
setStatus(copyElementContent(codeSnippetElement) ? 'success' : 'fail')
|
||||
setState(copyElementContent(codeSnippetElement) ? 'success' : 'fail')
|
||||
}
|
||||
element.addEventListener('click', onClippyClick)
|
||||
return () => element.removeEventListener('click', onClippyClick)
|
||||
|
|
@ -36,7 +36,7 @@ export function Clippy({ codeSnippetElement }: Props) {
|
|||
return (
|
||||
<div className={className}>
|
||||
<button className="clippy" ref={elementRef}>
|
||||
<i className={cx('icon', status)} />
|
||||
<i className={cx('icon', state)} />
|
||||
</button>
|
||||
</div>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Text } from '@primer/components'
|
||||
import { Label, Text } from '@primer/components'
|
||||
import { LoadingIndicator } from 'components/LoadingIndicator'
|
||||
import { Node } from 'components/Node'
|
||||
import { SearchBar } from 'components/SearchBar'
|
||||
|
|
@ -11,9 +11,12 @@ import * as React from 'react'
|
|||
import { FixedSizeList, ListChildComponentProps } from 'react-window'
|
||||
import { cx } from 'utils/cx'
|
||||
import { focusFileExplorer } from 'utils/DOMHelper'
|
||||
import { run } from 'utils/general'
|
||||
import { useLoadedContext } from 'utils/hooks/useLoadedContext'
|
||||
import { useOnLocationChange } from 'utils/hooks/useOnLocationChange'
|
||||
import { useOnPJAXDone } from 'utils/hooks/usePJAX'
|
||||
import { VisibleNodes } from 'utils/VisibleNodesGenerator'
|
||||
import { SideBarStateContext } from '../containers/SideBarState'
|
||||
import { Icon } from './Icon'
|
||||
import { SearchMode, searchModes } from './searchModes'
|
||||
import { SizeObserver } from './SizeObserver'
|
||||
|
|
@ -27,7 +30,6 @@ type renderNodeContext = {
|
|||
|
||||
const RawFileExplorer: React.FC<Props & ConnectorState> = function RawFileExplorer(props) {
|
||||
const {
|
||||
state,
|
||||
visibleNodes,
|
||||
visibleNodesGenerator,
|
||||
freeze,
|
||||
|
|
@ -37,16 +39,14 @@ const RawFileExplorer: React.FC<Props & ConnectorState> = function RawFileExplor
|
|||
onFocusSearchBar,
|
||||
goTo,
|
||||
handleKeyDown,
|
||||
toggleShowSettings,
|
||||
metaData,
|
||||
expandTo,
|
||||
setUpTree,
|
||||
treeRoot,
|
||||
defer,
|
||||
searched,
|
||||
} = props
|
||||
const {
|
||||
value: { accessToken, compressSingletonFolder, searchMode },
|
||||
value: { accessToken, compressSingletonFolder, searchMode, commentToggle },
|
||||
} = useConfigs()
|
||||
|
||||
const onSearch = React.useCallback(
|
||||
|
|
@ -59,18 +59,19 @@ const RawFileExplorer: React.FC<Props & ConnectorState> = function RawFileExplor
|
|||
[updateSearchKey, visibleNodesGenerator],
|
||||
)
|
||||
|
||||
const stateContext = useLoadedContext(SideBarStateContext)
|
||||
const state = stateContext.value
|
||||
|
||||
React.useEffect(() => {
|
||||
if (treeRoot) {
|
||||
setUpTree({
|
||||
treeRoot,
|
||||
metaData,
|
||||
config: {
|
||||
compressSingletonFolder,
|
||||
accessToken,
|
||||
},
|
||||
})
|
||||
}
|
||||
}, [setUpTree, treeRoot, metaData, compressSingletonFolder, accessToken])
|
||||
setUpTree({
|
||||
metaData,
|
||||
config: {
|
||||
compressSingletonFolder,
|
||||
accessToken,
|
||||
},
|
||||
stateContext,
|
||||
})
|
||||
}, [setUpTree, metaData, compressSingletonFolder, accessToken])
|
||||
|
||||
React.useEffect(() => {
|
||||
if (visibleNodes?.focusedNode) focusFileExplorer()
|
||||
|
|
@ -104,18 +105,26 @@ const RawFileExplorer: React.FC<Props & ConnectorState> = function RawFileExplor
|
|||
<Icon type="search" />
|
||||
</button>
|
||||
) : undefined
|
||||
const renderFileCommentAmounts = (node: TreeNode): React.ReactNode =>
|
||||
node.comments !== undefined &&
|
||||
node.comments > 0 && (
|
||||
<span className={'node-item-comment'}>
|
||||
<Icon type={'comment'} /> {node.comments > 9 ? '9+' : node.comments}
|
||||
</span>
|
||||
)
|
||||
|
||||
const renders: ((node: TreeNode) => React.ReactNode)[] = []
|
||||
if (commentToggle) renders.push(renderFileCommentAmounts)
|
||||
if (searchMode === 'fuzzy') renders.push(renderFindInFolderButton)
|
||||
if (searched) renders.push(renderGoToButton)
|
||||
|
||||
return renders.length
|
||||
? node => renders.map((render, i) => <React.Fragment key={i}>{render(node)}</React.Fragment>)
|
||||
: undefined
|
||||
}, [goTo, onSearch, searched, searchMode])
|
||||
}, [goTo, onSearch, searched, searchMode, commentToggle])
|
||||
|
||||
const renderLabelText = React.useCallback(
|
||||
node => searchModes[searchMode].renderNodeLabelText(node, searchKey),
|
||||
(node: TreeNode) => searchModes[searchMode].renderNodeLabelText(node, searchKey),
|
||||
[searchKey, searchMode],
|
||||
)
|
||||
|
||||
|
|
@ -131,59 +140,63 @@ const RawFileExplorer: React.FC<Props & ConnectorState> = function RawFileExplor
|
|||
)
|
||||
|
||||
return (
|
||||
<div
|
||||
className={cx(`file-explorer`, { freeze })}
|
||||
tabIndex={-1}
|
||||
onKeyDown={handleKeyDown}
|
||||
onClick={freeze ? toggleShowSettings : undefined}
|
||||
>
|
||||
{state !== 'done' ? (
|
||||
<LoadingIndicator
|
||||
text={
|
||||
{
|
||||
pulling: 'Fetching File List...',
|
||||
rendering: 'Rendering File List...',
|
||||
}[state]
|
||||
}
|
||||
/>
|
||||
) : (
|
||||
visibleNodes &&
|
||||
renderNodeContext && (
|
||||
<>
|
||||
<SearchBar value={searchKey} onSearch={onSearch} onFocus={onFocusSearchBar} />
|
||||
{searched && visibleNodes.nodes.length === 0 && (
|
||||
<>
|
||||
<Text marginTop={6} textAlign="center" color="text.gray">
|
||||
No results found.
|
||||
</Text>
|
||||
{defer && (
|
||||
<Text textAlign="center" color="gray.4" fontSize="12px">
|
||||
Lazy mode is ON. Search results are limited to loaded folders.
|
||||
</Text>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
<SizeObserver className={'files'}>
|
||||
{({ width = 0, height = 0 }) => (
|
||||
<ListView
|
||||
height={height}
|
||||
width={width}
|
||||
renderNodeContext={renderNodeContext}
|
||||
expandTo={expandTo}
|
||||
metaData={metaData}
|
||||
/>
|
||||
)}
|
||||
</SizeObserver>
|
||||
</>
|
||||
)
|
||||
)}
|
||||
<div className={cx(`file-explorer`, { freeze })} tabIndex={-1} onKeyDown={handleKeyDown}>
|
||||
{run(() => {
|
||||
switch (state) {
|
||||
case 'tree-loading':
|
||||
return <LoadingIndicator text={'Fetching File List...'} />
|
||||
case 'tree-rendering':
|
||||
return <LoadingIndicator text={'Rendering File List...'} />
|
||||
case 'tree-rendered':
|
||||
return (
|
||||
visibleNodes &&
|
||||
renderNodeContext && (
|
||||
<>
|
||||
<SearchBar value={searchKey} onSearch={onSearch} onFocus={onFocusSearchBar} />
|
||||
{searched && visibleNodes.nodes.length === 0 && (
|
||||
<>
|
||||
<Text marginTop={6} textAlign="center" color="text.gray">
|
||||
No results found.
|
||||
</Text>
|
||||
{defer && (
|
||||
<Text textAlign="center" color="gray.4" fontSize="12px">
|
||||
Lazy mode is ON. Search results are limited to loaded folders.
|
||||
</Text>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
<SizeObserver className={'files'}>
|
||||
{({ width = 0, height = 0 }) => (
|
||||
<ListView
|
||||
height={height}
|
||||
width={width}
|
||||
renderNodeContext={renderNodeContext}
|
||||
expandTo={expandTo}
|
||||
metaData={metaData}
|
||||
/>
|
||||
)}
|
||||
</SizeObserver>
|
||||
|
||||
{defer && (
|
||||
<Label
|
||||
title="File tree data is loaded on demand. And search results are limited."
|
||||
bg="yellow.5"
|
||||
color="gray.6"
|
||||
>
|
||||
Lazy Mode
|
||||
</Label>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
)
|
||||
}
|
||||
})}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
RawFileExplorer.defaultProps = {
|
||||
freeze: false,
|
||||
state: 'pulling',
|
||||
searchKey: '',
|
||||
visibleNodes: null,
|
||||
}
|
||||
|
|
@ -248,13 +261,15 @@ function ListView({ width, height, metaData, expandTo, renderNodeContext }: List
|
|||
useOnLocationChange(goToCurrentItem)
|
||||
useOnPJAXDone(goToCurrentItem)
|
||||
|
||||
const { compactFileTree } = useConfigs().value
|
||||
|
||||
return (
|
||||
<FixedSizeList
|
||||
ref={listRef}
|
||||
itemKey={(index, { visibleNodes }) => visibleNodes?.nodes[index]?.path}
|
||||
itemData={renderNodeContext}
|
||||
itemCount={visibleNodes.nodes.length}
|
||||
itemSize={37}
|
||||
itemSize={compactFileTree ? 24 : 37}
|
||||
height={height}
|
||||
width={width}
|
||||
>
|
||||
|
|
|
|||
|
|
@ -1,15 +1,25 @@
|
|||
import { SideBar } from 'components/SideBar'
|
||||
import { ConfigsContext, ConfigsContextWrapper } from 'containers/ConfigsContext'
|
||||
import { ConfigsContextWrapper } from 'containers/ConfigsContext'
|
||||
import * as React from 'react'
|
||||
import { ErrorBoundary } from './ErrorBoundary'
|
||||
import { ErrorBoundary } from '../containers/ErrorBoundary'
|
||||
import { StateBarErrorContextWrapper } from '../containers/ErrorContext'
|
||||
import { OAuthWrapper } from '../containers/OAuthWrapper'
|
||||
import { RepoContextWrapper } from '../containers/RepoContext'
|
||||
import { StateBarStateContextWrapper } from '../containers/SideBarState'
|
||||
|
||||
export function Gitako() {
|
||||
return (
|
||||
<ErrorBoundary>
|
||||
<ConfigsContextWrapper>
|
||||
<ConfigsContext.Consumer>
|
||||
{configContext => configContext && <SideBar configContext={configContext} />}
|
||||
</ConfigsContext.Consumer>
|
||||
<StateBarStateContextWrapper>
|
||||
<StateBarErrorContextWrapper>
|
||||
<OAuthWrapper>
|
||||
<RepoContextWrapper>
|
||||
<SideBar />
|
||||
</RepoContextWrapper>
|
||||
</OAuthWrapper>
|
||||
</StateBarErrorContextWrapper>
|
||||
</StateBarStateContextWrapper>
|
||||
</ConfigsContextWrapper>
|
||||
</ErrorBoundary>
|
||||
)
|
||||
|
|
|
|||
8
src/components/IIFC.tsx
Normal file
8
src/components/IIFC.tsx
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
import * as React from 'react'
|
||||
|
||||
// I tried to install `react-iifc` but that causes TS build errors for unknown reason
|
||||
// So here the duplicated code is
|
||||
|
||||
export function IIFC({ children }: { children(): React.ReactNode }) {
|
||||
return <>{children()}</>
|
||||
}
|
||||
|
|
@ -2,6 +2,7 @@ import {
|
|||
ChevronDownIcon as ChevronDown,
|
||||
ChevronRightIcon as ChevronRight,
|
||||
ClockIcon as Clock,
|
||||
CommentIcon as Comment,
|
||||
FileCodeIcon as FileCode,
|
||||
FileIcon as File,
|
||||
FileMediaIcon as FileMedia,
|
||||
|
|
@ -10,130 +11,76 @@ import {
|
|||
GearIcon as Gear,
|
||||
GrabberIcon as Grabber,
|
||||
HourglassIcon as Hourglass,
|
||||
Icon as OcticonIcon,
|
||||
IconProps,
|
||||
MarkdownIcon as Markdown,
|
||||
OctofaceIcon as Octoface,
|
||||
PinIcon as Pin,
|
||||
ReplyIcon as Reply,
|
||||
SearchIcon as Search,
|
||||
TabIcon as Tab,
|
||||
XIcon as X,
|
||||
} from '@primer/octicons-react'
|
||||
import * as React from 'react'
|
||||
import { cx } from 'utils/cx'
|
||||
|
||||
function getSVGIconComponent(
|
||||
type: string,
|
||||
): {
|
||||
IconComponent: OcticonIcon
|
||||
name: string
|
||||
} {
|
||||
switch (type) {
|
||||
case 'search':
|
||||
return {
|
||||
IconComponent: Search,
|
||||
name: 'Search',
|
||||
}
|
||||
case 'loading':
|
||||
return {
|
||||
IconComponent: Clock,
|
||||
name: 'Clock',
|
||||
}
|
||||
case 'hourglass':
|
||||
return {
|
||||
IconComponent: Hourglass,
|
||||
name: 'Hourglass',
|
||||
}
|
||||
case 'submodule':
|
||||
return {
|
||||
IconComponent: Submodule,
|
||||
name: 'Submodule',
|
||||
}
|
||||
case 'grabber':
|
||||
return {
|
||||
IconComponent: Grabber,
|
||||
name: 'Grabber',
|
||||
}
|
||||
case 'octoface':
|
||||
return {
|
||||
IconComponent: Octoface,
|
||||
name: 'Octoface',
|
||||
}
|
||||
case 'chevron-down':
|
||||
return {
|
||||
IconComponent: ChevronDown,
|
||||
name: 'ChevronDown',
|
||||
}
|
||||
case 'x':
|
||||
return {
|
||||
IconComponent: X,
|
||||
name: 'X',
|
||||
}
|
||||
case 'gear':
|
||||
return {
|
||||
IconComponent: Gear,
|
||||
name: 'Gear',
|
||||
}
|
||||
case 'folder':
|
||||
return {
|
||||
IconComponent: ChevronRight,
|
||||
name: 'ChevronRight',
|
||||
}
|
||||
case 'go-to':
|
||||
return {
|
||||
IconComponent: Reply,
|
||||
name: 'Reply',
|
||||
}
|
||||
// not supported in octicon v2 yet
|
||||
// case '.pdf':
|
||||
// return {
|
||||
// IconComponent: FilePdf,
|
||||
// name: 'FilePdf',
|
||||
// }
|
||||
case '.zip':
|
||||
case '.rar':
|
||||
case '.7z':
|
||||
return {
|
||||
IconComponent: FileZip,
|
||||
name: 'FileZip',
|
||||
}
|
||||
case '.md':
|
||||
return {
|
||||
IconComponent: Markdown,
|
||||
name: 'Markdown',
|
||||
}
|
||||
case '.png':
|
||||
case '.jpg':
|
||||
case '.gif':
|
||||
case '.bmp':
|
||||
return {
|
||||
IconComponent: FileMedia,
|
||||
name: 'FileMedia',
|
||||
}
|
||||
case '.js':
|
||||
case '.jsx':
|
||||
case '.ts':
|
||||
case '.tsx':
|
||||
case '.es6':
|
||||
case '.coffee':
|
||||
case '.css':
|
||||
case '.less':
|
||||
case '.scss':
|
||||
case '.sass':
|
||||
return {
|
||||
IconComponent: FileCode,
|
||||
name: 'FileCode',
|
||||
}
|
||||
// TODO: adapt to more file types
|
||||
// case '': return FileBinary
|
||||
// case '': return FileSubmodule
|
||||
// case '': return FileSymlinkDirectory
|
||||
// case '': return FileSymlinkFile
|
||||
default:
|
||||
return {
|
||||
IconComponent: File,
|
||||
name: 'File',
|
||||
}
|
||||
}
|
||||
const iconToComponentMap = {
|
||||
Search,
|
||||
Clock,
|
||||
Comment,
|
||||
Hourglass,
|
||||
Submodule,
|
||||
Grabber,
|
||||
Octoface,
|
||||
ChevronDown,
|
||||
X,
|
||||
Gear,
|
||||
ChevronRight,
|
||||
Reply,
|
||||
FileZip,
|
||||
Markdown,
|
||||
FileMedia,
|
||||
FileCode,
|
||||
File,
|
||||
Pin,
|
||||
Tab,
|
||||
}
|
||||
|
||||
const defaultIcon = 'File'
|
||||
const typeToIconComponentMap: {
|
||||
[type: string]: keyof typeof iconToComponentMap
|
||||
} = {
|
||||
search: 'Search',
|
||||
loading: 'Clock',
|
||||
hourglass: 'Hourglass',
|
||||
submodule: 'Submodule',
|
||||
grabber: 'Grabber',
|
||||
octoface: 'Octoface',
|
||||
comment: 'Comment',
|
||||
x: 'X',
|
||||
pin: 'Pin',
|
||||
tab: 'Tab',
|
||||
gear: 'Gear',
|
||||
folder: 'ChevronRight',
|
||||
'chevron-down': 'ChevronDown',
|
||||
'go-to': 'Reply',
|
||||
'.zip': 'FileZip',
|
||||
'.rar': 'FileZip',
|
||||
'.7z': 'FileZip',
|
||||
'.md': 'Markdown',
|
||||
'.png': 'FileMedia',
|
||||
'.jpg': 'FileMedia',
|
||||
'.gif': 'FileMedia',
|
||||
'.bmp': 'FileMedia',
|
||||
'.js': 'FileCode',
|
||||
'.jsx': 'FileCode',
|
||||
'.ts': 'FileCode',
|
||||
'.tsx': 'FileCode',
|
||||
'.es6': 'FileCode',
|
||||
'.coffee': 'FileCode',
|
||||
'.css': 'FileCode',
|
||||
'.less': 'FileCode',
|
||||
'.scss': 'FileCode',
|
||||
'.sass': 'FileCode',
|
||||
}
|
||||
|
||||
type Props = {
|
||||
|
|
@ -151,7 +98,8 @@ export const Icon = React.memo(function Icon({
|
|||
}: Props) {
|
||||
let children: React.ReactNode = null
|
||||
if (!placeholder) {
|
||||
const { name, IconComponent } = getSVGIconComponent(type)
|
||||
const name = typeToIconComponentMap[type] || defaultIcon
|
||||
const IconComponent = iconToComponentMap[name]
|
||||
children = <IconComponent className={cx('octicon', name)} {...otherProps} />
|
||||
}
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -11,14 +11,14 @@ export function MetaBar({ metaData }: Props) {
|
|||
const { userName, repoName, branchName } = metaData
|
||||
const { repoUrl, userUrl } = platform.resolveUrlFromMetaData(metaData)
|
||||
return (
|
||||
<Flex flexDirection="column" justifyContent="space-between" className={'meta-bar'}>
|
||||
<>
|
||||
<Breadcrumb className={'user-and-repo'}>
|
||||
<Breadcrumb.Item href={userUrl}>{userName}</Breadcrumb.Item>
|
||||
<Breadcrumb.Item href={repoUrl}>
|
||||
<Text fontWeight="bolder">{repoName}</Text>
|
||||
</Breadcrumb.Item>
|
||||
</Breadcrumb>
|
||||
<Flex flexWrap="nowrap">
|
||||
<Flex paddingTop={1} flexWrap="nowrap" alignItems="flex-start">
|
||||
<div className={'octicon-wrapper'}>
|
||||
<GitBranchIcon size="small" />
|
||||
</div>
|
||||
|
|
@ -26,6 +26,6 @@ export function MetaBar({ metaData }: Props) {
|
|||
{branchName || '...'}
|
||||
</BranchName>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import { useConfigs } from 'containers/ConfigsContext'
|
|||
import * as React from 'react'
|
||||
import { cx } from 'utils/cx'
|
||||
import { OperatingSystems, os } from 'utils/general'
|
||||
import { getFileIconSrc, getFolderIconSrc } from '../utils/parseIconMapCSV'
|
||||
import { getFileIconSrc, getFolderIconSrc } from 'utils/parseIconMapCSV'
|
||||
import { Icon } from './Icon'
|
||||
|
||||
function getIconType(node: TreeNode) {
|
||||
|
|
@ -38,6 +38,7 @@ export function Node({
|
|||
style,
|
||||
onClick,
|
||||
}: Props) {
|
||||
const { compactFileTree: compact } = useConfigs().value
|
||||
return (
|
||||
<a
|
||||
href={node.url}
|
||||
|
|
@ -53,15 +54,15 @@ export function Node({
|
|||
|
||||
onClick(event, node)
|
||||
}}
|
||||
className={cx(`node-item`, { focused, disabled: node.accessDenied, expanded })}
|
||||
style={{ ...style, paddingLeft: `${10 + 20 * depth}px` }}
|
||||
className={cx(`node-item`, { focused, disabled: node.accessDenied, expanded, compact })}
|
||||
style={{ ...style, paddingLeft: `${10 + (compact ? 10 : 20) * depth}px` }}
|
||||
title={node.path}
|
||||
>
|
||||
<div className={'node-item-label'}>
|
||||
<NodeItemIcon node={node} open={expanded} loading={loading} />
|
||||
{renderLabelText(node)}
|
||||
</div>
|
||||
{renderActions && <div>{renderActions(node)}</div>}
|
||||
{renderActions && <div className={'actions'}>{renderActions(node)}</div>}
|
||||
</a>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,14 +1,24 @@
|
|||
import { Icon } from 'components/Icon'
|
||||
import * as React from 'react'
|
||||
import { Size } from './Resizable'
|
||||
import { Size } from './SideBarBodyWrapper'
|
||||
|
||||
type Props = {
|
||||
size: Size
|
||||
onResize(size: Size): void
|
||||
onResetSize?(): void
|
||||
onResizeStateChange?(state: ResizeState): void
|
||||
style?: React.CSSProperties
|
||||
}
|
||||
|
||||
export function HorizontalResizeHandler({ onResize, size, style }: Props) {
|
||||
type ResizeState = 'idle' | 'resizing'
|
||||
|
||||
export function HorizontalResizeHandler({
|
||||
onResize,
|
||||
onResetSize,
|
||||
onResizeStateChange,
|
||||
size,
|
||||
style,
|
||||
}: Props) {
|
||||
const pointerDown = React.useRef(false)
|
||||
const startX = React.useRef(0)
|
||||
const baseSize = React.useRef(size)
|
||||
|
|
@ -22,6 +32,7 @@ export function HorizontalResizeHandler({ onResize, size, style }: Props) {
|
|||
startX.current = clientX
|
||||
pointerDown.current = true
|
||||
baseSize.current = latestPropSize.current
|
||||
onResizeStateChange?.('resizing')
|
||||
}, [])
|
||||
|
||||
React.useEffect(() => {
|
||||
|
|
@ -39,6 +50,7 @@ export function HorizontalResizeHandler({ onResize, size, style }: Props) {
|
|||
if (pointerDown.current) {
|
||||
pointerDown.current = false
|
||||
baseSize.current = latestPropSize.current
|
||||
onResizeStateChange?.('idle')
|
||||
}
|
||||
}
|
||||
window.addEventListener('mouseup', onPointerUp)
|
||||
|
|
@ -46,7 +58,12 @@ export function HorizontalResizeHandler({ onResize, size, style }: Props) {
|
|||
}, [])
|
||||
|
||||
return (
|
||||
<div className={'gitako-resize-handler'} onMouseDown={onPointerDown} style={style}>
|
||||
<div
|
||||
className={'gitako-resize-handler'}
|
||||
onMouseDown={onPointerDown}
|
||||
onDoubleClick={onResetSize}
|
||||
style={style}
|
||||
>
|
||||
<Icon type={'grabber'} className={'grabber-icon'} size={20} />
|
||||
</div>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ export function SearchBar({ onSearch, onFocus, value }: Props) {
|
|||
/>
|
||||
<div className={`actions`}>
|
||||
<button
|
||||
className={`toggle-mode`}
|
||||
className={`toggle-search-mode`}
|
||||
title="Toggle search mode"
|
||||
onClick={() => {
|
||||
const newMode = searchMode === 'regex' ? 'fuzzy' : 'regex'
|
||||
|
|
|
|||
|
|
@ -2,164 +2,213 @@ import { AccessDeniedDescription } from 'components/AccessDeniedDescription'
|
|||
import { FileExplorer } from 'components/FileExplorer'
|
||||
import { MetaBar } from 'components/MetaBar'
|
||||
import { Portal } from 'components/Portal'
|
||||
import { Resizable } from 'components/Resizable'
|
||||
import { SettingsBar } from 'components/settings/SettingsBar'
|
||||
import { SideBarBodyWrapper } from 'components/SideBarBodyWrapper'
|
||||
import { ToggleShowButton } from 'components/ToggleShowButton'
|
||||
import { connect } from 'driver/connect'
|
||||
import { SideBarCore } from 'driver/core'
|
||||
import { ConnectorState, Props } from 'driver/core/SideBar'
|
||||
import { useConfigs } from 'containers/ConfigsContext'
|
||||
import { platform } from 'platforms'
|
||||
import { useGitHubAttachCopyFileButton, useGitHubAttachCopySnippetButton } from 'platforms/GitHub'
|
||||
import * as React from 'react'
|
||||
import { cx } from 'utils/cx'
|
||||
import { parseURLSearch, run } from 'utils/general'
|
||||
import * as DOMHelper from 'utils/DOMHelper'
|
||||
import { run } from 'utils/general'
|
||||
import { useCatchNetworkError } from 'utils/hooks/useCatchNetworkError'
|
||||
import { useLoadedContext } from 'utils/hooks/useLoadedContext'
|
||||
import { loadWithPJAX, useOnPJAXDone, usePJAX } from 'utils/hooks/usePJAX'
|
||||
import { useProgressBar } from 'utils/hooks/useProgressBar'
|
||||
import * as keyHelper from 'utils/keyHelper'
|
||||
import { useStateIO } from 'utils/hooks/useStateIO'
|
||||
import { SideBarErrorContext } from '../containers/ErrorContext'
|
||||
import { RepoContext } from '../containers/RepoContext'
|
||||
import { SideBarStateContext } from '../containers/SideBarState'
|
||||
import { Theme } from '../containers/Theme'
|
||||
import { useToggleSideBarWithKeyboard } from '../utils/hooks/useToggleSideBarWithKeyboard'
|
||||
import { Icon } from './Icon'
|
||||
import { IIFC } from './IIFC'
|
||||
import { LoadingIndicator } from './LoadingIndicator'
|
||||
import { Theme } from './Theme'
|
||||
|
||||
const RawGitako: React.FC<Props & ConnectorState> = function RawGitako(props) {
|
||||
const {
|
||||
errorDueToAuth,
|
||||
metaData,
|
||||
treeData,
|
||||
defer,
|
||||
error,
|
||||
shouldShow,
|
||||
showSettings,
|
||||
logoContainerElement,
|
||||
toggleShowSideBar,
|
||||
toggleShowSettings,
|
||||
configContext,
|
||||
} = props
|
||||
export function SideBar() {
|
||||
const metaData = React.useContext(RepoContext)
|
||||
const state = useLoadedContext(SideBarStateContext).value
|
||||
const configContext = useConfigs()
|
||||
|
||||
const accessToken = configContext.value.accessToken || ''
|
||||
const [baseSize] = React.useState(() => configContext.value.sideBarWidth)
|
||||
|
||||
const $showSettings = useStateIO(false)
|
||||
const showSettings = $showSettings.value
|
||||
const toggleShowSettings = React.useCallback(() => $showSettings.onChange(show => !show), [])
|
||||
|
||||
const $logoContainerElement = useStateIO<HTMLElement | null>(null)
|
||||
|
||||
const hasMetaData = state !== 'disabled' // will be true since retrieving data, cannot use Boolean(metaData)
|
||||
React.useEffect(() => {
|
||||
run(async function () {
|
||||
if (!accessToken) {
|
||||
const accessToken = await trySetUpAccessTokenWithCode()
|
||||
if (accessToken) configContext.onChange({ accessToken })
|
||||
}
|
||||
})
|
||||
}, [])
|
||||
|
||||
React.useEffect(() => {
|
||||
props.init()
|
||||
}, [accessToken])
|
||||
|
||||
React.useEffect(
|
||||
function attachKeyDown() {
|
||||
if (props.disabled || !configContext.value.shortcut) return
|
||||
|
||||
function onKeyDown(e: KeyboardEvent) {
|
||||
const keys = keyHelper.parseEvent(e)
|
||||
if (keys === configContext.value.shortcut) {
|
||||
toggleShowSideBar()
|
||||
}
|
||||
}
|
||||
window.addEventListener('keydown', onKeyDown)
|
||||
return () => window.removeEventListener('keydown', onKeyDown)
|
||||
},
|
||||
[toggleShowSideBar, props.disabled, configContext.value.shortcut],
|
||||
)
|
||||
if (hasMetaData) {
|
||||
DOMHelper.markGitakoReadyState(true)
|
||||
$showSettings.onChange(false)
|
||||
$logoContainerElement.onChange(DOMHelper.insertLogoMountPoint())
|
||||
} else {
|
||||
DOMHelper.markGitakoReadyState(false)
|
||||
}
|
||||
}, [hasMetaData])
|
||||
|
||||
const sidebarToggleMode = configContext.value.sidebarToggleMode
|
||||
const intelligentToggle = configContext.value.intelligentToggle
|
||||
const $shouldShow = useStateIO(intelligentToggle === null ? false : intelligentToggle)
|
||||
const shouldShow = $shouldShow.value
|
||||
React.useEffect(() => {
|
||||
const shouldShow = intelligentToggle === null ? platform.shouldShow() : intelligentToggle
|
||||
props.setShouldShow(shouldShow)
|
||||
}, [intelligentToggle, props.metaData])
|
||||
if (sidebarToggleMode === 'persistent') {
|
||||
DOMHelper.setBodyIndent(shouldShow)
|
||||
} else {
|
||||
DOMHelper.setBodyIndent(false)
|
||||
}
|
||||
|
||||
const updateSideBarVisibility = React.useCallback(
|
||||
function updateSideBarVisibility() {
|
||||
if (intelligentToggle === null) {
|
||||
props.setShouldShow(platform.shouldShow())
|
||||
}
|
||||
if (shouldShow) {
|
||||
DOMHelper.focusFileExplorer() // TODO: verify if it works
|
||||
}
|
||||
}, [shouldShow, sidebarToggleMode])
|
||||
|
||||
// Save expand state on toggle if auto expand if not on
|
||||
React.useEffect(() => {
|
||||
if (intelligentToggle !== null) {
|
||||
configContext.onChange({ intelligentToggle: shouldShow })
|
||||
}
|
||||
}, [shouldShow, intelligentToggle])
|
||||
|
||||
const error = useLoadedContext(SideBarErrorContext).value
|
||||
// Lock shouldShow on error
|
||||
React.useEffect(() => {
|
||||
if (error && shouldShow) {
|
||||
$shouldShow.onChange(false)
|
||||
}
|
||||
}, [error])
|
||||
|
||||
const setShowSideBar = React.useCallback(
|
||||
(show: typeof $shouldShow.value) => {
|
||||
if (!error) $shouldShow.onChange(show)
|
||||
},
|
||||
[props.metaData?.branchName, intelligentToggle],
|
||||
[error],
|
||||
)
|
||||
useOnPJAXDone(updateSideBarVisibility)
|
||||
|
||||
useGitHubAttachCopyFileButton(configContext.value.copyFileButton)
|
||||
useGitHubAttachCopySnippetButton(configContext.value.copySnippetButton)
|
||||
const toggleShowSideBar = React.useCallback(() => {
|
||||
if (!error) $shouldShow.onChange(show => !show)
|
||||
}, [error])
|
||||
useToggleSideBarWithKeyboard(state, configContext, toggleShowSideBar)
|
||||
|
||||
useSetShouldShowOnPJAXDone(setShowSideBar)
|
||||
|
||||
platform.usePlatformHooks?.()
|
||||
|
||||
usePJAX()
|
||||
useProgressBar()
|
||||
|
||||
// Hide sidebar when error due to auth but token is set #128
|
||||
const hideSidebarOnInvalidToken: boolean =
|
||||
intelligentToggle === null && Boolean(state === 'error-due-to-auth' && accessToken)
|
||||
React.useEffect(() => {
|
||||
if (hideSidebarOnInvalidToken) {
|
||||
setShowSideBar(false)
|
||||
}
|
||||
}, [hideSidebarOnInvalidToken])
|
||||
|
||||
return (
|
||||
<Theme>
|
||||
<div className={'gitako-side-bar'}>
|
||||
<Portal into={logoContainerElement}>
|
||||
{!shouldShow && (
|
||||
<ToggleShowButton error={error} onClick={error ? undefined : toggleShowSideBar} />
|
||||
)}
|
||||
<Portal into={$logoContainerElement.value}>
|
||||
<ToggleShowButton
|
||||
error={error}
|
||||
className={cx({
|
||||
hidden: shouldShow,
|
||||
})}
|
||||
onHover={sidebarToggleMode === 'float' ? () => setShowSideBar(true) : undefined}
|
||||
onClick={toggleShowSideBar}
|
||||
/>
|
||||
</Portal>
|
||||
<Resizable className={cx({ hidden: error || !shouldShow })} baseSize={baseSize}>
|
||||
<SideBarBodyWrapper
|
||||
className={cx(`toggle-mode-${sidebarToggleMode}`, {
|
||||
collapsed: error || !shouldShow,
|
||||
})}
|
||||
baseSize={baseSize}
|
||||
onLeave={sidebarToggleMode === 'float' ? () => setShowSideBar(false) : undefined}
|
||||
>
|
||||
<div className={'gitako-side-bar-body'}>
|
||||
<div className={'close-side-bar-button-position'}>
|
||||
<button className={'close-side-bar-button'} onClick={toggleShowSideBar}>
|
||||
<Icon className={'action-icon'} type={'x'} />
|
||||
</button>
|
||||
</div>
|
||||
<div className={'gitako-side-bar-content'}>
|
||||
{metaData ? (
|
||||
<div className={'header'}>
|
||||
<MetaBar metaData={metaData} />
|
||||
<div
|
||||
className={'gitako-side-bar-content'}
|
||||
onClick={showSettings ? toggleShowSettings : undefined}
|
||||
>
|
||||
<div className={'header'}>
|
||||
<div className={'close-side-bar-button-position'}>
|
||||
{sidebarToggleMode === 'persistent' && (
|
||||
<button
|
||||
title={'Collapse sidebar'}
|
||||
className={'close-side-bar-button'}
|
||||
onClick={toggleShowSideBar}
|
||||
>
|
||||
<Icon className={'action-icon'} type={'tab'} />
|
||||
</button>
|
||||
)}
|
||||
<button
|
||||
title={'Toggle sidebar dock mode between float and persistent'}
|
||||
className={cx('close-side-bar-button', {
|
||||
active: sidebarToggleMode === 'persistent',
|
||||
})}
|
||||
onClick={() =>
|
||||
configContext.onChange({
|
||||
sidebarToggleMode: sidebarToggleMode === 'float' ? 'persistent' : 'float',
|
||||
})
|
||||
}
|
||||
>
|
||||
<Icon className={'action-icon'} type={'pin'} />
|
||||
</button>
|
||||
</div>
|
||||
) : (
|
||||
<LoadingIndicator text={'Fetching repo meta...'} />
|
||||
)}
|
||||
{errorDueToAuth ? (
|
||||
<AccessDeniedDescription hasToken={Boolean(accessToken)} />
|
||||
) : (
|
||||
metaData && (
|
||||
<FileExplorer
|
||||
toggleShowSettings={toggleShowSettings}
|
||||
metaData={metaData}
|
||||
treeRoot={treeData}
|
||||
freeze={showSettings}
|
||||
accessToken={accessToken}
|
||||
loadWithPJAX={loadWithPJAX}
|
||||
config={configContext.value}
|
||||
defer={defer}
|
||||
/>
|
||||
)
|
||||
)}
|
||||
{metaData && <MetaBar metaData={metaData} />}
|
||||
</div>
|
||||
{run(() => {
|
||||
switch (state) {
|
||||
case 'disabled':
|
||||
return null
|
||||
case 'getting-access-token':
|
||||
return <LoadingIndicator text={'Getting access token...'} />
|
||||
case 'after-getting-access-token':
|
||||
case 'meta-loading':
|
||||
return <LoadingIndicator text={'Fetching repo meta...'} />
|
||||
case 'error-due-to-auth':
|
||||
return <AccessDeniedDescription />
|
||||
default:
|
||||
return (
|
||||
metaData && (
|
||||
<IIFC>
|
||||
{() => (
|
||||
<FileExplorer
|
||||
metaData={metaData}
|
||||
freeze={showSettings}
|
||||
accessToken={accessToken}
|
||||
loadWithPJAX={loadWithPJAX}
|
||||
config={configContext.value}
|
||||
catchNetworkErrors={useCatchNetworkError()}
|
||||
/>
|
||||
)}
|
||||
</IIFC>
|
||||
)
|
||||
)
|
||||
}
|
||||
})}
|
||||
</div>
|
||||
<SettingsBar
|
||||
defer={defer}
|
||||
toggleShowSettings={toggleShowSettings}
|
||||
activated={showSettings}
|
||||
/>
|
||||
<SettingsBar toggleShowSettings={toggleShowSettings} activated={showSettings} />
|
||||
</div>
|
||||
</Resizable>
|
||||
</SideBarBodyWrapper>
|
||||
</div>
|
||||
</Theme>
|
||||
)
|
||||
}
|
||||
|
||||
RawGitako.defaultProps = {
|
||||
shouldShow: false,
|
||||
showSettings: false,
|
||||
errorDueToAuth: false,
|
||||
disabled: false,
|
||||
}
|
||||
|
||||
export const SideBar = connect(SideBarCore)(RawGitako)
|
||||
|
||||
async function trySetUpAccessTokenWithCode() {
|
||||
const search = parseURLSearch()
|
||||
if ('code' in search) {
|
||||
const accessToken = await platform.setOAuth(search.code)
|
||||
if (!accessToken) alert(`Gitako: The OAuth token has expired, please try again.`)
|
||||
window.history.replaceState(
|
||||
{},
|
||||
'removed search param',
|
||||
window.location.pathname.replace(window.location.search, ''),
|
||||
)
|
||||
return accessToken
|
||||
}
|
||||
function useSetShouldShowOnPJAXDone(setShouldShow: (value: boolean) => void) {
|
||||
const { intelligentToggle, sidebarToggleMode } = useConfigs().value
|
||||
const updateSideBarVisibility = React.useCallback(() => {
|
||||
if (intelligentToggle === null && sidebarToggleMode === 'persistent') {
|
||||
setShouldShow(platform.shouldShow())
|
||||
}
|
||||
}, [intelligentToggle, sidebarToggleMode])
|
||||
React.useEffect(() => {
|
||||
updateSideBarVisibility()
|
||||
}, [updateSideBarVisibility])
|
||||
useOnPJAXDone(updateSideBarVisibility)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,23 +2,31 @@ import { HorizontalResizeHandler } from 'components/ResizeHandler'
|
|||
import { useConfigs } from 'containers/ConfigsContext'
|
||||
import * as React from 'react'
|
||||
import { useDebounce, useWindowSize } from 'react-use'
|
||||
import { defaultConfigs } from 'utils/config/helper'
|
||||
import { cx } from 'utils/cx'
|
||||
import { setResizingState } from 'utils/DOMHelper'
|
||||
import * as features from 'utils/features'
|
||||
import { useCSSVariable } from './useCSSVariable'
|
||||
import { useCSSVariable } from 'utils/hooks/useCSSVariable'
|
||||
|
||||
export type Size = number
|
||||
type Props = {
|
||||
baseSize: Size
|
||||
className?: string
|
||||
onLeave?: React.HTMLAttributes<HTMLElement>['onMouseLeave']
|
||||
}
|
||||
|
||||
const MINIMAL_CONTENT_VIEWPORT_WIDTH = 100
|
||||
const MINIMAL_WIDTH = 240
|
||||
|
||||
export function Resizable({ baseSize, className, children }: React.PropsWithChildren<Props>) {
|
||||
export function SideBarBodyWrapper({
|
||||
baseSize,
|
||||
className,
|
||||
children,
|
||||
onLeave,
|
||||
}: React.PropsWithChildren<Props>) {
|
||||
const [size, setSize] = React.useState(baseSize)
|
||||
const configContext = useConfigs()
|
||||
const blockLeaveRef = React.useRef(false)
|
||||
|
||||
React.useEffect(() => {
|
||||
setSize(baseSize)
|
||||
|
|
@ -47,10 +55,28 @@ export function Resizable({ baseSize, className, children }: React.PropsWithChil
|
|||
else if (size < MINIMAL_WIDTH) setSize(MINIMAL_WIDTH)
|
||||
else setSize(size)
|
||||
}, [])
|
||||
|
||||
const onMouseLeave = React.useCallback(
|
||||
e => {
|
||||
if (blockLeaveRef.current) return
|
||||
onLeave?.(e)
|
||||
},
|
||||
[onLeave],
|
||||
)
|
||||
|
||||
return (
|
||||
<div className={cx('gitako-position-wrapper', className)}>
|
||||
<div className={'gitako-position-content'}>{children}</div>
|
||||
{features.resize && <HorizontalResizeHandler onResize={onResize} size={size} />}
|
||||
<div className={cx('gitako-side-bar-body-wrapper', className)} onMouseLeave={onMouseLeave}>
|
||||
<div className={'gitako-side-bar-body-wrapper-content'}>{children}</div>
|
||||
{features.resize && (
|
||||
<HorizontalResizeHandler
|
||||
onResize={onResize}
|
||||
onResetSize={() => setSize(defaultConfigs.sideBarWidth)}
|
||||
onResizeStateChange={state => {
|
||||
blockLeaveRef.current = state === 'resizing'
|
||||
}}
|
||||
size={size}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
@ -1,27 +1,28 @@
|
|||
import { useConfigs } from 'containers/ConfigsContext'
|
||||
import * as React from 'react'
|
||||
import { Config } from 'utils/configHelper'
|
||||
import { Config } from 'utils/config/helper'
|
||||
import { Field } from './settings/Field'
|
||||
|
||||
export type SimpleField = {
|
||||
key: keyof Config
|
||||
export type SimpleField<Key extends keyof Config> = {
|
||||
key: Key
|
||||
label: string
|
||||
wikiLink?: string
|
||||
tooltip?: string
|
||||
description?: string
|
||||
disabled?: boolean
|
||||
overwrite?: {
|
||||
value: <T>(value: T) => boolean
|
||||
onChange: (checked: boolean) => any
|
||||
value: (value: Config[Key]) => boolean
|
||||
onChange: (checked: boolean) => Config[Key]
|
||||
}
|
||||
}
|
||||
|
||||
type Props = {
|
||||
field: SimpleField
|
||||
type Props<Key extends keyof Config> = {
|
||||
field: SimpleField<Key>
|
||||
|
||||
onChange?(): void
|
||||
}
|
||||
|
||||
export function SimpleToggleField({ field, onChange }: Props) {
|
||||
export function SimpleToggleField<Key extends keyof Config>({ field, onChange }: Props<Key>) {
|
||||
const { overwrite } = field
|
||||
const configContext = useConfigs()
|
||||
const value = configContext.value[field.key]
|
||||
|
|
@ -54,6 +55,7 @@ export function SimpleToggleField({ field, onChange }: Props) {
|
|||
<input
|
||||
id={field.key}
|
||||
name={field.key}
|
||||
disabled={field.disabled}
|
||||
type={'checkbox'}
|
||||
onChange={async e => {
|
||||
const enabled = e.currentTarget.checked
|
||||
|
|
|
|||
|
|
@ -2,13 +2,16 @@ import iconSrc from 'assets/icons/Gitako.png'
|
|||
import { useConfigs } from 'containers/ConfigsContext'
|
||||
import * as React from 'react'
|
||||
import { useDebounce, useWindowSize } from 'react-use'
|
||||
import { cx } from 'utils/cx'
|
||||
import { Icon } from './Icon'
|
||||
|
||||
type Props = {
|
||||
error?: string
|
||||
error?: string | null
|
||||
className?: React.HTMLAttributes<HTMLButtonElement>['className']
|
||||
onHover?: React.HTMLAttributes<HTMLButtonElement>['onMouseEnter']
|
||||
} & Pick<React.HTMLAttributes<HTMLButtonElement>, 'onClick'>
|
||||
|
||||
export function ToggleShowButton({ error, onClick }: Props) {
|
||||
export function ToggleShowButton({ error, className, onClick, onHover }: Props) {
|
||||
const ref = React.useRef<HTMLDivElement>(null)
|
||||
const config = useConfigs()
|
||||
const [distance, setDistance] = React.useState(config.value.toggleButtonVerticalDistance)
|
||||
|
|
@ -35,10 +38,13 @@ export function ToggleShowButton({ error, onClick }: Props) {
|
|||
|
||||
const toggleIconMode = config.value.toggleButtonContent
|
||||
return (
|
||||
<div ref={ref} className={'gitako-toggle-show-button-wrapper'}>
|
||||
<div ref={ref} className={cx('gitako-toggle-show-button-wrapper', className)}>
|
||||
<button
|
||||
className={'gitako-toggle-show-button'}
|
||||
className={cx('gitako-toggle-show-button', {
|
||||
error,
|
||||
})}
|
||||
onClick={onClick}
|
||||
onMouseEnter={onHover}
|
||||
draggable
|
||||
onDragStart={event => {
|
||||
hideDragPreview(event)
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import * as React from 'react'
|
|||
import { useStateIO } from 'utils/hooks/useStateIO'
|
||||
import { SettingsSection } from './SettingsSection'
|
||||
|
||||
const ACCESS_TOKEN_REGEXP = /^[0-9a-f]+$/
|
||||
const ACCESS_TOKEN_REGEXP = /^([0-9a-fA-F]+|gh[pousr]_[A-Za-z0-9_]+)$/
|
||||
|
||||
type Props = {}
|
||||
|
||||
|
|
@ -37,30 +37,33 @@ export function AccessTokenSettings(props: React.PropsWithChildren<Props>) {
|
|||
[],
|
||||
)
|
||||
|
||||
const onPressAccessToken = React.useCallback(({ key }: React.KeyboardEvent) => {
|
||||
if (key === 'Enter') saveToken()
|
||||
}, [])
|
||||
|
||||
const saveToken = React.useCallback(
|
||||
async (hint?: typeof useAccessTokenHint.value) => {
|
||||
async (
|
||||
hint: typeof useAccessTokenHint.value = (
|
||||
<span>
|
||||
<a href="#" onClick={() => window.location.reload()}>
|
||||
Reload
|
||||
</a>{' '}
|
||||
to activate!
|
||||
</span>
|
||||
),
|
||||
) => {
|
||||
if (accessToken) {
|
||||
configContext.onChange({ accessToken })
|
||||
useAccessToken.onChange('')
|
||||
useAccessTokenHint.onChange(
|
||||
hint || (
|
||||
<span>
|
||||
<a href="#" onClick={() => window.location.reload()}>
|
||||
Reload
|
||||
</a>{' '}
|
||||
to activate!
|
||||
</span>
|
||||
),
|
||||
)
|
||||
useAccessTokenHint.onChange(hint)
|
||||
}
|
||||
},
|
||||
[accessToken],
|
||||
)
|
||||
|
||||
const onPressAccessToken = React.useCallback(
|
||||
({ key }: React.KeyboardEvent) => {
|
||||
if (key === 'Enter') saveToken()
|
||||
},
|
||||
[saveToken],
|
||||
)
|
||||
|
||||
return (
|
||||
<SettingsSection
|
||||
title={
|
||||
|
|
@ -121,7 +124,7 @@ export function AccessTokenSettings(props: React.PropsWithChildren<Props>) {
|
|||
</div>
|
||||
</div>
|
||||
)}
|
||||
{accessTokenHint && !focusInput.value && <span className={'hint'}>{accessTokenHint}</span>}
|
||||
{accessTokenHint && <span className={'hint'}>{accessTokenHint}</span>}
|
||||
</SettingsSection>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import { wikiLinks } from 'components/settings/SettingsBar'
|
|||
import { SimpleToggleField } from 'components/SimpleToggleField'
|
||||
import { useConfigs } from 'containers/ConfigsContext'
|
||||
import * as React from 'react'
|
||||
import { Config } from 'utils/configHelper'
|
||||
import { Config } from 'utils/config/helper'
|
||||
import { Option, SelectInput } from '../SelectInput'
|
||||
import { Field } from './Field'
|
||||
import { SettingsSection } from './SettingsSection'
|
||||
|
|
@ -54,7 +54,7 @@ export function FileTreeSettings(props: React.PropsWithChildren<Props>) {
|
|||
})
|
||||
}}
|
||||
value={configContext.value.recursiveToggleFolder}
|
||||
></SelectInput>
|
||||
/>
|
||||
</Field>
|
||||
<Field title="Icons" id="file-tree-icons">
|
||||
<SelectInput<Config['icons']>
|
||||
|
|
@ -76,6 +76,20 @@ export function FileTreeSettings(props: React.PropsWithChildren<Props>) {
|
|||
tooltip: 'Merge folders and their only child folder to make UI more compact.',
|
||||
}}
|
||||
/>
|
||||
<SimpleToggleField
|
||||
field={{
|
||||
key: 'commentToggle',
|
||||
label: 'Show PR file comments',
|
||||
tooltip: 'Show number of comments next to file names in Pull Requests.',
|
||||
}}
|
||||
/>
|
||||
<SimpleToggleField
|
||||
field={{
|
||||
key: 'compactFileTree',
|
||||
label: 'Compact file tree layout',
|
||||
tooltip: 'View file tree structures more effectively.',
|
||||
}}
|
||||
/>
|
||||
</SettingsSection>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Label, Link } from '@primer/components'
|
||||
import { Link } from '@primer/components'
|
||||
import { Icon } from 'components/Icon'
|
||||
import { VERSION } from 'env'
|
||||
import { platform } from 'platforms'
|
||||
|
|
@ -15,13 +15,13 @@ const WIKI_HOME_LINK = 'https://github.com/EnixCoda/Gitako/wiki'
|
|||
export const wikiLinks = {
|
||||
compressSingletonFolder: `${WIKI_HOME_LINK}/Compress-Singleton-Folder`,
|
||||
changeLog: `${WIKI_HOME_LINK}/Change-Log`,
|
||||
codeFolding: `${WIKI_HOME_LINK}/Code-folding`,
|
||||
copyFileButton: `${WIKI_HOME_LINK}/Copy-file-and-snippet`,
|
||||
copySnippet: `${WIKI_HOME_LINK}/Copy-file-and-snippet`,
|
||||
createAccessToken: `${WIKI_HOME_LINK}/Access-token-for-Gitako`,
|
||||
}
|
||||
|
||||
type Props = {
|
||||
defer?: boolean
|
||||
activated: boolean
|
||||
toggleShowSettings: () => void
|
||||
}
|
||||
|
|
@ -30,18 +30,24 @@ function SettingsBarContent() {
|
|||
const useReloadHint = useStateIO<React.ReactNode>('')
|
||||
const { value: reloadHint } = useReloadHint
|
||||
|
||||
const moreFields: SimpleField[] =
|
||||
const moreFields: SimpleField<'copyFileButton' | 'copySnippetButton'|'codeFolding'>[] =
|
||||
platform === GitHub
|
||||
? [
|
||||
{
|
||||
key: 'codeFolding',
|
||||
label: 'Fold source code button',
|
||||
wikiLink: wikiLinks.codeFolding,
|
||||
tooltip: `Read more in Gitako's Wiki`,
|
||||
},
|
||||
{
|
||||
key: 'copyFileButton',
|
||||
label: 'Copy file shortcut',
|
||||
label: 'Copy file button',
|
||||
wikiLink: wikiLinks.copyFileButton,
|
||||
tooltip: `Read more in Gitako's Wiki`,
|
||||
},
|
||||
{
|
||||
key: 'copySnippetButton',
|
||||
label: 'Copy snippet shortcut',
|
||||
label: 'Copy snippet button',
|
||||
wikiLink: wikiLinks.copySnippet,
|
||||
tooltip: `Read more in Gitako's Wiki`,
|
||||
},
|
||||
|
|
@ -78,7 +84,7 @@ function SettingsBarContent() {
|
|||
}
|
||||
|
||||
export function SettingsBar(props: Props) {
|
||||
const { defer, toggleShowSettings, activated } = props
|
||||
const { toggleShowSettings, activated } = props
|
||||
return (
|
||||
<div className={'gitako-settings-bar'}>
|
||||
{activated && <SettingsBarContent />}
|
||||
|
|
@ -93,15 +99,6 @@ export function SettingsBar(props: Props) {
|
|||
{VERSION}
|
||||
</Link>
|
||||
<div className={'header-right'}>
|
||||
{defer && (
|
||||
<Label
|
||||
title="File tree data is loaded on demand. And search results are limited."
|
||||
bg="yellow.5"
|
||||
color="gray.6"
|
||||
>
|
||||
Lazy Mode
|
||||
</Label>
|
||||
)}
|
||||
<button className={'settings-button'} onClick={toggleShowSettings}>
|
||||
{activated ? (
|
||||
<Icon type={'chevron-down'} className={'hide-settings-icon'} />
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import { Option, SelectInput } from 'components/SelectInput'
|
|||
import { SimpleToggleField } from 'components/SimpleToggleField'
|
||||
import { useConfigs } from 'containers/ConfigsContext'
|
||||
import * as React from 'react'
|
||||
import { Config } from 'utils/configHelper'
|
||||
import { Config } from 'utils/config/helper'
|
||||
import { friendlyFormatShortcut } from 'utils/general'
|
||||
import { useStateIO } from 'utils/hooks/useStateIO'
|
||||
import * as keyHelper from 'utils/keyHelper'
|
||||
|
|
@ -88,16 +88,21 @@ export function SidebarSettings(props: React.PropsWithChildren<Props>) {
|
|||
})
|
||||
}}
|
||||
value={configContext.value.toggleButtonContent}
|
||||
></SelectInput>
|
||||
/>
|
||||
</Field>
|
||||
<SimpleToggleField
|
||||
field={{
|
||||
key: 'intelligentToggle',
|
||||
label: 'Auto expand',
|
||||
tooltip:
|
||||
'Gitako will expand when exploring source files, pull requests, etc. And collapse otherwise.',
|
||||
disabled: configContext.value.sidebarToggleMode === 'float',
|
||||
tooltip: `Gitako will expand when exploring source files, pull requests, etc. And collapse otherwise.${
|
||||
configContext.value.sidebarToggleMode === 'float'
|
||||
? '\nNow disabled as sidebar is in float mode.'
|
||||
: ''
|
||||
}`,
|
||||
overwrite: {
|
||||
value: enabled => enabled === null,
|
||||
value: enabled =>
|
||||
configContext.value.sidebarToggleMode === 'float' ? false : enabled === null,
|
||||
onChange: checked => (checked ? null : true),
|
||||
},
|
||||
}}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
import * as React from 'react'
|
||||
import * as configsHelper from 'utils/configHelper'
|
||||
import { Config } from 'utils/configHelper'
|
||||
import { Config, configHelper } from 'utils/config/helper'
|
||||
|
||||
type Props = {}
|
||||
|
||||
|
|
@ -12,19 +11,19 @@ export const ConfigsContext = React.createContext<ContextShape | null>(null)
|
|||
export function ConfigsContextWrapper(props: React.PropsWithChildren<Props>) {
|
||||
const [configs, setConfigs] = React.useState<Config | null>(null)
|
||||
React.useEffect(() => {
|
||||
configsHelper.get().then(setConfigs)
|
||||
configHelper.get().then(setConfigs)
|
||||
}, [])
|
||||
const onChange = React.useCallback(
|
||||
(updatedConfigs: Partial<Config>) => {
|
||||
const mergedConfigs = { ...configs, ...updatedConfigs } as Config
|
||||
configsHelper.set(mergedConfigs)
|
||||
configHelper.set(mergedConfigs)
|
||||
setConfigs(mergedConfigs)
|
||||
},
|
||||
[configs, setConfigs],
|
||||
)
|
||||
if (configs === null) return null
|
||||
return (
|
||||
<ConfigsContext.Provider value={{ value: configs, onChange: onChange }}>
|
||||
<ConfigsContext.Provider value={{ value: configs, onChange }}>
|
||||
{props.children}
|
||||
</ConfigsContext.Provider>
|
||||
)
|
||||
|
|
|
|||
12
src/containers/ErrorContext.tsx
Normal file
12
src/containers/ErrorContext.tsx
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
import * as React from 'react'
|
||||
import { useStateIO } from 'utils/hooks/useStateIO'
|
||||
|
||||
export type SideBarErrorContextShape = IO<string | null>
|
||||
|
||||
export const SideBarErrorContext = React.createContext<SideBarErrorContextShape | null>(null)
|
||||
|
||||
export function StateBarErrorContextWrapper({ children }: React.PropsWithChildren<{}>) {
|
||||
const $error = useStateIO<string | null>(null)
|
||||
|
||||
return <SideBarErrorContext.Provider value={$error}>{children}</SideBarErrorContext.Provider>
|
||||
}
|
||||
61
src/containers/OAuthWrapper.tsx
Normal file
61
src/containers/OAuthWrapper.tsx
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
import { useConfigs } from 'containers/ConfigsContext'
|
||||
import { platform } from 'platforms'
|
||||
import * as React from 'react'
|
||||
import { parseURLSearch, run } from 'utils/general'
|
||||
import { useLoadedContext } from 'utils/hooks/useLoadedContext'
|
||||
import { useStateIO } from 'utils/hooks/useStateIO'
|
||||
import { SideBarStateContext } from './SideBarState'
|
||||
|
||||
/**
|
||||
* Setup access token before sending other requests
|
||||
*/
|
||||
export function OAuthWrapper({ children }: React.PropsWithChildren<{}>) {
|
||||
const running = useGetAccessToken()
|
||||
const $state = useLoadedContext(SideBarStateContext)
|
||||
|
||||
const needGetAccessTokenRef = React.useRef(running)
|
||||
React.useEffect(() => {
|
||||
if (needGetAccessTokenRef.current) {
|
||||
$state.onChange(running ? 'getting-access-token' : 'after-getting-access-token')
|
||||
}
|
||||
}, [running])
|
||||
|
||||
// block children rendering on the first render if setting token
|
||||
if (running && $state.value !== 'getting-access-token') return null
|
||||
return <>{children}</>
|
||||
}
|
||||
|
||||
function useGetAccessToken() {
|
||||
const $block = useStateIO(() => Boolean(getCodeSearchParam()))
|
||||
const configContext = useConfigs()
|
||||
const { accessToken } = configContext.value
|
||||
React.useEffect(() => {
|
||||
run(async function () {
|
||||
const code = getCodeSearchParam()
|
||||
if (code && !accessToken) {
|
||||
const accessToken = await getAccessTokenWithCode(code)
|
||||
if (accessToken) configContext.onChange({ accessToken })
|
||||
}
|
||||
$block.onChange(false)
|
||||
})
|
||||
}, [])
|
||||
|
||||
return $block.value
|
||||
}
|
||||
|
||||
function getCodeSearchParam() {
|
||||
return parseURLSearch().get('code')
|
||||
}
|
||||
|
||||
async function getAccessTokenWithCode(code: string) {
|
||||
const accessToken = await platform.setOAuth(code)
|
||||
if (!accessToken) alert(`Gitako: The OAuth token may have expired, please try again.`)
|
||||
const search = parseURLSearch()
|
||||
search.delete('code')
|
||||
window.history.replaceState(
|
||||
{},
|
||||
'removed search param',
|
||||
window.location.pathname.replace(window.location.search, '?' + search.toString()),
|
||||
)
|
||||
return accessToken
|
||||
}
|
||||
107
src/containers/RepoContext.tsx
Normal file
107
src/containers/RepoContext.tsx
Normal file
|
|
@ -0,0 +1,107 @@
|
|||
import { useConfigs } from 'containers/ConfigsContext'
|
||||
import { platform } from 'platforms'
|
||||
import * as React from 'react'
|
||||
import { useEffectOnSerializableUpdates } from 'utils/hooks/useEffectOnSerializableUpdates'
|
||||
import { useLoadedContext } from 'utils/hooks/useLoadedContext'
|
||||
import { useOnPJAXDone } from 'utils/hooks/usePJAX'
|
||||
import { useStateIO } from 'utils/hooks/useStateIO'
|
||||
import { useCatchNetworkError } from '../utils/hooks/useCatchNetworkError'
|
||||
import { SideBarStateContext } from './SideBarState'
|
||||
|
||||
export const RepoContext = React.createContext<MetaData | null>(null)
|
||||
|
||||
export function RepoContextWrapper({ children }: React.PropsWithChildren<{}>) {
|
||||
const partialMetaData = usePartialMetaData()
|
||||
const defaultBranch = useDefaultBranch(partialMetaData)
|
||||
const metaData = useMetaData(partialMetaData, defaultBranch)
|
||||
|
||||
return <RepoContext.Provider value={metaData}>{children}</RepoContext.Provider>
|
||||
}
|
||||
|
||||
function resolvePartialMetaData() {
|
||||
const partialMetaData = platform.resolvePartialMetaData()
|
||||
if (partialMetaData) {
|
||||
const { userName, repoName, type } = partialMetaData
|
||||
return {
|
||||
userName,
|
||||
repoName,
|
||||
type: type === 'pull' ? type : undefined,
|
||||
}
|
||||
} else {
|
||||
return partialMetaData
|
||||
}
|
||||
}
|
||||
|
||||
function usePartialMetaData(): PartialMetaData | null {
|
||||
const $state = useLoadedContext(SideBarStateContext)
|
||||
const isGettingAccessToken = $state.value === 'getting-access-token' // will be false after getting access token and trigger meta-resolve progress
|
||||
// sync along URL and DOM
|
||||
const $partialMetaData = useStateIO(isGettingAccessToken ? null : resolvePartialMetaData)
|
||||
const $committedPartialMetaData = useStateIO($partialMetaData.value)
|
||||
const setPartialMetaData = () => $partialMetaData.onChange(resolvePartialMetaData())
|
||||
React.useEffect(() => {
|
||||
if (!isGettingAccessToken) setPartialMetaData()
|
||||
}, [isGettingAccessToken])
|
||||
useOnPJAXDone(setPartialMetaData)
|
||||
useEffectOnSerializableUpdates(
|
||||
$partialMetaData.value,
|
||||
JSON.stringify,
|
||||
$committedPartialMetaData.onChange,
|
||||
)
|
||||
React.useEffect(() => {
|
||||
if (!$partialMetaData.value && !isGettingAccessToken) {
|
||||
$state.onChange('disabled')
|
||||
}
|
||||
}, [$partialMetaData.value])
|
||||
return $committedPartialMetaData.value
|
||||
}
|
||||
|
||||
function useBranchName(): MetaData['branchName'] | null {
|
||||
// sync along URL and DOM
|
||||
const $branchName = useStateIO(() => platform.resolvePartialMetaData()?.branchName || null)
|
||||
useOnPJAXDone(() => $branchName.onChange(platform.resolvePartialMetaData()?.branchName || null))
|
||||
return $branchName.value
|
||||
}
|
||||
|
||||
function useDefaultBranch(partialMetaData: PartialMetaData | null) {
|
||||
const { accessToken } = useConfigs().value
|
||||
const $state = useLoadedContext(SideBarStateContext)
|
||||
const $defaultBranch = useStateIO<string | null>(null)
|
||||
const catchNetworkError = useCatchNetworkError()
|
||||
React.useEffect(() => {
|
||||
catchNetworkError(async () => {
|
||||
if (!partialMetaData) return
|
||||
$state.onChange('meta-loading')
|
||||
|
||||
const defaultBranch = await platform.getDefaultBranchName(partialMetaData, accessToken)
|
||||
$defaultBranch.onChange(defaultBranch)
|
||||
})
|
||||
}, [partialMetaData, accessToken])
|
||||
return $defaultBranch.value
|
||||
}
|
||||
|
||||
function useMetaData(
|
||||
partialMetaData: PartialMetaData | null,
|
||||
defaultBranchName: MetaData['defaultBranchName'] | null,
|
||||
) {
|
||||
const $state = useLoadedContext(SideBarStateContext)
|
||||
const $metaData = useStateIO<MetaData | null>(null)
|
||||
const branchName = useBranchName()
|
||||
const theBranch = branchName && branchName !== defaultBranchName ? branchName : defaultBranchName
|
||||
React.useEffect(() => {
|
||||
if (partialMetaData && defaultBranchName && theBranch) {
|
||||
const { userName, repoName } = partialMetaData
|
||||
const safeMetaData: MetaData = {
|
||||
userName,
|
||||
repoName,
|
||||
branchName: theBranch,
|
||||
defaultBranchName,
|
||||
}
|
||||
$metaData.onChange(safeMetaData)
|
||||
$state.onChange('meta-loaded')
|
||||
} else {
|
||||
$metaData.onChange(null)
|
||||
}
|
||||
}, [partialMetaData, defaultBranchName, theBranch])
|
||||
return $metaData.value
|
||||
}
|
||||
28
src/containers/SideBarState.tsx
Normal file
28
src/containers/SideBarState.tsx
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
import * as React from 'react'
|
||||
import { useStateIO } from 'utils/hooks/useStateIO'
|
||||
|
||||
export type SideBarState =
|
||||
| 'disabled'
|
||||
| 'getting-access-token'
|
||||
| 'after-getting-access-token' // mid-state for a smoother state switch out of 'getting-access-token'
|
||||
| 'meta-loading'
|
||||
| 'meta-loaded'
|
||||
| 'tree-loading'
|
||||
| 'tree-rendering'
|
||||
| 'tree-rendered'
|
||||
| 'idle'
|
||||
| 'error-due-to-auth'
|
||||
|
||||
export type SideBarStateContextShape = IO<SideBarState>
|
||||
|
||||
export const SideBarStateContext = React.createContext<SideBarStateContextShape | null>(null)
|
||||
|
||||
export function StateBarStateContextWrapper({ children }: React.PropsWithChildren<{}>) {
|
||||
const $state = useStateIO<SideBarState>('disabled')
|
||||
|
||||
return (
|
||||
<SideBarStateContext.Provider value={$state}>
|
||||
{$state.value !== null && children}
|
||||
</SideBarStateContext.Provider>
|
||||
)
|
||||
}
|
||||
|
|
@ -6,7 +6,7 @@ import * as React from 'react'
|
|||
import * as ReactDOM from 'react-dom'
|
||||
import './content.scss'
|
||||
|
||||
if (platform.resolveMeta()) {
|
||||
if (platform.resolvePartialMetaData()) {
|
||||
addMiddleware(withErrorLog)
|
||||
|
||||
if (document.readyState === 'loading') {
|
||||
|
|
@ -26,7 +26,7 @@ async function init() {
|
|||
// injects a copy of stylesheets so that other extensions(e.g. dark reader) could read
|
||||
// resolves when style is loaded to prevent render without proper styles
|
||||
async function injectStyles(url: string) {
|
||||
return new Promise(resolve => {
|
||||
return new Promise<void>(resolve => {
|
||||
const linkElement = document.createElement('link')
|
||||
linkElement.setAttribute('rel', 'stylesheet')
|
||||
linkElement.setAttribute('href', url)
|
||||
|
|
|
|||
|
|
@ -1,26 +1,26 @@
|
|||
import { SideBarStateContextShape } from 'containers/SideBarState'
|
||||
import { GetCreatedMethod, MethodCreator } from 'driver/connect'
|
||||
import { platform } from 'platforms'
|
||||
import { Config } from 'utils/configHelper'
|
||||
import { Config } from 'utils/config/helper'
|
||||
import * as DOMHelper from 'utils/DOMHelper'
|
||||
import { OperatingSystems, os } from 'utils/general'
|
||||
import { VisibleNodes, VisibleNodesGenerator } from 'utils/VisibleNodesGenerator'
|
||||
|
||||
export type Props = {
|
||||
treeRoot?: TreeNode
|
||||
metaData: MetaData
|
||||
freeze: boolean
|
||||
accessToken: string | undefined
|
||||
toggleShowSettings: React.MouseEventHandler
|
||||
config: Config
|
||||
loadWithPJAX(url: string): void
|
||||
defer?: boolean
|
||||
catchNetworkErrors: <T>(fn: () => T) => Promise<T | undefined>
|
||||
}
|
||||
|
||||
export type ConnectorState = {
|
||||
state: 'pulling' | 'rendering' | 'done'
|
||||
visibleNodesGenerator: VisibleNodesGenerator | null
|
||||
visibleNodes: VisibleNodes | null
|
||||
searchKey: string
|
||||
searched: boolean // derived state from searchKey, = !!searchKey
|
||||
defer: boolean
|
||||
|
||||
handleKeyDown: GetCreatedMethod<typeof handleKeyDown>
|
||||
updateSearchKey: GetCreatedMethod<typeof updateSearchKey>
|
||||
|
|
@ -45,37 +45,58 @@ type BoundMethodCreator<Args extends any[] = []> = MethodCreator<Props, Connecto
|
|||
|
||||
export const setUpTree: BoundMethodCreator<
|
||||
[
|
||||
Required<Pick<Props, 'treeRoot' | 'metaData'>> & {
|
||||
config: Pick<Config, 'compressSingletonFolder' | 'accessToken'>
|
||||
},
|
||||
{ stateContext: SideBarStateContextShape } & Required<Pick<Props, 'metaData'>> & {
|
||||
config: Pick<Config, 'compressSingletonFolder' | 'accessToken'>
|
||||
},
|
||||
]
|
||||
> = dispatch => async ({ treeRoot, metaData, config }) => {
|
||||
dispatch.set({ state: 'rendering' })
|
||||
> = dispatch => ({ stateContext, metaData, config }) => {
|
||||
const {
|
||||
props: { catchNetworkErrors },
|
||||
} = dispatch.get()
|
||||
|
||||
const visibleNodesGenerator = new VisibleNodesGenerator({
|
||||
root: treeRoot,
|
||||
compress: config.compressSingletonFolder,
|
||||
async getTreeData(path) {
|
||||
const { root } = await platform.getTreeData(metaData, path, false, config.accessToken)
|
||||
return root
|
||||
},
|
||||
})
|
||||
dispatch.set({ visibleNodesGenerator })
|
||||
visibleNodesGenerator.onUpdate(visibleNodes => dispatch.set({ visibleNodes }))
|
||||
catchNetworkErrors(async () => {
|
||||
const { userName, repoName, branchName } = metaData
|
||||
|
||||
if (platform.shouldExpandAll?.()) {
|
||||
const unsubscribe = visibleNodesGenerator.onUpdate(visibleNodes => {
|
||||
unsubscribe()
|
||||
visibleNodes.nodes.forEach(node =>
|
||||
dispatch.call(toggleNodeExpansion, node, { recursive: true }),
|
||||
)
|
||||
stateContext.onChange('tree-loading')
|
||||
const { root: treeRoot, defer = false } = await platform.getTreeData(
|
||||
{
|
||||
branchName: branchName,
|
||||
userName,
|
||||
repoName,
|
||||
},
|
||||
'/',
|
||||
true,
|
||||
config.accessToken,
|
||||
)
|
||||
|
||||
stateContext.onChange('tree-rendering')
|
||||
dispatch.set({ defer })
|
||||
|
||||
const visibleNodesGenerator = new VisibleNodesGenerator({
|
||||
root: treeRoot,
|
||||
compress: config.compressSingletonFolder,
|
||||
async getTreeData(path) {
|
||||
const { root } = await platform.getTreeData(metaData, path, false, config.accessToken)
|
||||
return root
|
||||
},
|
||||
})
|
||||
} else {
|
||||
const targetPath = platform.getCurrentPath(metaData.branchName)
|
||||
if (targetPath) dispatch.call(goTo, targetPath)
|
||||
}
|
||||
dispatch.set({ visibleNodesGenerator })
|
||||
visibleNodesGenerator.onUpdate(visibleNodes => dispatch.set({ visibleNodes }))
|
||||
|
||||
dispatch.set({ state: 'done' })
|
||||
if (platform.shouldExpandAll?.()) {
|
||||
const unsubscribe = visibleNodesGenerator.onUpdate(visibleNodes => {
|
||||
unsubscribe()
|
||||
visibleNodes.nodes.forEach(node =>
|
||||
dispatch.call(toggleNodeExpansion, node, { recursive: true }),
|
||||
)
|
||||
})
|
||||
} else {
|
||||
const targetPath = platform.getCurrentPath(metaData.branchName)
|
||||
if (targetPath) dispatch.call(goTo, targetPath)
|
||||
}
|
||||
|
||||
stateContext.onChange('tree-rendered')
|
||||
})
|
||||
}
|
||||
|
||||
export const handleKeyDown: BoundMethodCreator<[React.KeyboardEvent]> = dispatch => event => {
|
||||
|
|
@ -112,6 +133,10 @@ export const handleKeyDown: BoundMethodCreator<[React.KeyboardEvent]> = dispatch
|
|||
break
|
||||
|
||||
case 'ArrowLeft':
|
||||
if (wouldBlockHistoryNavigation(event)) {
|
||||
muteEvent = false
|
||||
break
|
||||
}
|
||||
if (expandedNodes.has(focusedNode.path)) {
|
||||
dispatch.call(toggleNodeExpansion, focusedNode, { recursive: event.altKey })
|
||||
} else {
|
||||
|
|
@ -125,6 +150,10 @@ export const handleKeyDown: BoundMethodCreator<[React.KeyboardEvent]> = dispatch
|
|||
|
||||
// consider the two keys as 'confirm' key
|
||||
case 'ArrowRight':
|
||||
if (wouldBlockHistoryNavigation(event)) {
|
||||
muteEvent = false
|
||||
break
|
||||
}
|
||||
// expand node or focus on first content node or redirect to file page
|
||||
if (focusedNode.type === 'tree') {
|
||||
if (expandedNodes.has(focusedNode.path)) {
|
||||
|
|
@ -285,3 +314,8 @@ export const expandTo: BoundMethodCreator<[string[]]> = dispatch => async curren
|
|||
visibleNodesGenerator.focusNode(nodeExpandedTo)
|
||||
}
|
||||
}
|
||||
|
||||
function wouldBlockHistoryNavigation(event: React.KeyboardEvent) {
|
||||
// Alt + left/right is usually history navigation shortcut on OS other than macOS
|
||||
return os !== OperatingSystems.macOS && event.altKey
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,185 +0,0 @@
|
|||
import { ConfigsContextShape } from 'containers/ConfigsContext'
|
||||
import { GetCreatedMethod, MethodCreator } from 'driver/connect'
|
||||
import { errors, platform, platformName } from 'platforms'
|
||||
import * as DOMHelper from 'utils/DOMHelper'
|
||||
import { createPromiseQueue } from 'utils/general'
|
||||
|
||||
export type Props = {
|
||||
configContext: ConfigsContextShape
|
||||
}
|
||||
|
||||
export type ConnectorState = {
|
||||
// error message
|
||||
error?: string
|
||||
// whether Gitako side bar should be shown
|
||||
shouldShow: boolean
|
||||
// whether show settings pane
|
||||
showSettings: boolean
|
||||
// whether failed loading the repo due to it is private
|
||||
errorDueToAuth: boolean
|
||||
// meta data for the repository
|
||||
metaData?: MetaData
|
||||
// file tree data
|
||||
treeData?: TreeNode
|
||||
logoContainerElement: Element | null
|
||||
defer?: boolean
|
||||
disabled: boolean
|
||||
initializingPromise: Promise<void> | null
|
||||
} & {
|
||||
init: GetCreatedMethod<typeof init>
|
||||
setShouldShow: GetCreatedMethod<typeof setShouldShow>
|
||||
toggleShowSideBar: GetCreatedMethod<typeof toggleShowSideBar>
|
||||
toggleShowSettings: GetCreatedMethod<typeof toggleShowSettings>
|
||||
}
|
||||
|
||||
type BoundMethodCreator<Args extends any[] = []> = MethodCreator<Props, ConnectorState, Args>
|
||||
|
||||
const promiseQueue = createPromiseQueue()
|
||||
|
||||
export const init: BoundMethodCreator = dispatch => async () => {
|
||||
const leave = await promiseQueue.enter()
|
||||
|
||||
try {
|
||||
const metaData = platform.resolveMeta()
|
||||
if (!metaData) {
|
||||
dispatch.set({ disabled: true })
|
||||
return
|
||||
}
|
||||
const { userName, repoName, branchName } = metaData
|
||||
|
||||
DOMHelper.markGitakoReadyState(true)
|
||||
dispatch.set({
|
||||
errorDueToAuth: false,
|
||||
showSettings: false,
|
||||
logoContainerElement: DOMHelper.insertLogoMountPoint(),
|
||||
})
|
||||
|
||||
const {
|
||||
props: { configContext },
|
||||
} = dispatch.get()
|
||||
const { accessToken } = configContext.value
|
||||
|
||||
const guessDefaultBranch = 'master' // when to switch to 'main'?
|
||||
let getTreeData = platform.getTreeData(
|
||||
{
|
||||
branchName: branchName || guessDefaultBranch,
|
||||
userName,
|
||||
repoName,
|
||||
},
|
||||
'/',
|
||||
true,
|
||||
accessToken,
|
||||
)
|
||||
getTreeData.catch(error => error) // catch it early to prevent the error being raised higher
|
||||
|
||||
if (branchName) {
|
||||
const safeMetaData = {
|
||||
userName,
|
||||
repoName,
|
||||
branchName,
|
||||
}
|
||||
dispatch.set({ metaData: safeMetaData })
|
||||
getTreeData.catch(error => {
|
||||
dispatch.call(handleError, error)
|
||||
})
|
||||
} else {
|
||||
const defaultBranchName = await platform.getDefaultBranchName(
|
||||
{ userName, repoName },
|
||||
accessToken,
|
||||
)
|
||||
|
||||
if (!defaultBranchName) {
|
||||
throw new Error(`Failed resolving default branch name`)
|
||||
}
|
||||
|
||||
const safeMetaData = {
|
||||
userName,
|
||||
repoName,
|
||||
branchName: defaultBranchName,
|
||||
}
|
||||
dispatch.set({ metaData: safeMetaData })
|
||||
|
||||
if (defaultBranchName !== guessDefaultBranch && metaData.type !== 'pull') {
|
||||
// Accessing repository's non-homepage(no branch name in URL, nor in DOM)
|
||||
// We predicted its default branch to be 'master' and sent aggressive request
|
||||
// Throw that request due to the repo do not use {defaultBranchName} as default branch
|
||||
getTreeData = platform.getTreeData(
|
||||
{
|
||||
branchName: defaultBranchName,
|
||||
userName,
|
||||
repoName,
|
||||
},
|
||||
'/',
|
||||
true,
|
||||
accessToken,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const { root: treeData, defer } = await getTreeData
|
||||
dispatch.set({ treeData, defer })
|
||||
} catch (err) {
|
||||
dispatch.call(handleError, err)
|
||||
}
|
||||
|
||||
leave()
|
||||
}
|
||||
|
||||
export const handleError: BoundMethodCreator<[Error]> = dispatch => async err => {
|
||||
if (err.message === errors.EMPTY_PROJECT) {
|
||||
dispatch.call(setError, 'This project seems to be empty.')
|
||||
} else if (err.message === errors.BLOCKED_PROJECT) {
|
||||
dispatch.call(setError, 'Access to the project is blocked.')
|
||||
} else if (
|
||||
err.message === errors.NOT_FOUND ||
|
||||
err.message === errors.BAD_CREDENTIALS ||
|
||||
err.message === errors.API_RATE_LIMIT
|
||||
) {
|
||||
dispatch.set({ errorDueToAuth: true })
|
||||
} else if (err.message === errors.CONNECTION_BLOCKED) {
|
||||
const { props } = dispatch.get()
|
||||
if (props.configContext.value.accessToken) {
|
||||
dispatch.call(setError, `Cannot connect to ${platformName}.`)
|
||||
} else {
|
||||
dispatch.set({ errorDueToAuth: true })
|
||||
}
|
||||
} else if (err.message === errors.SERVER_FAULT) {
|
||||
dispatch.call(setError, `${platformName} server went down.`)
|
||||
} else {
|
||||
DOMHelper.markGitakoReadyState(false)
|
||||
dispatch.call(setError, 'Some thing went wrong.')
|
||||
throw err
|
||||
}
|
||||
}
|
||||
|
||||
export const toggleShowSideBar: BoundMethodCreator = dispatch => () => {
|
||||
const {
|
||||
state: { shouldShow },
|
||||
props: { configContext },
|
||||
} = dispatch.get()
|
||||
dispatch.call(setShouldShow, !shouldShow)
|
||||
|
||||
const {
|
||||
value: { intelligentToggle },
|
||||
} = configContext
|
||||
if (intelligentToggle !== null) {
|
||||
configContext.onChange({ intelligentToggle: !shouldShow })
|
||||
}
|
||||
}
|
||||
|
||||
export const setShouldShow: BoundMethodCreator<
|
||||
[ConnectorState['shouldShow']]
|
||||
> = dispatch => shouldShow => {
|
||||
dispatch.set({ shouldShow }, shouldShow ? DOMHelper.focusFileExplorer : undefined)
|
||||
DOMHelper.setBodyIndent(shouldShow)
|
||||
}
|
||||
|
||||
export const setError: BoundMethodCreator<[ConnectorState['error']]> = dispatch => error => {
|
||||
dispatch.set({ error })
|
||||
dispatch.call(setShouldShow, false)
|
||||
}
|
||||
|
||||
export const toggleShowSettings: BoundMethodCreator = dispatch => () =>
|
||||
dispatch.set(({ showSettings }) => ({
|
||||
showSettings: !showSettings,
|
||||
}))
|
||||
|
|
@ -4,8 +4,5 @@ import {
|
|||
ConnectorState as FileExplorerConnectorState,
|
||||
Props as FileExplorerProps,
|
||||
} from './FileExplorer'
|
||||
import * as SideBar from './SideBar'
|
||||
import { ConnectorState as SideBarConnectorState, Props as SideBarProps } from './SideBar'
|
||||
|
||||
export const FileExplorerCore: Sources<FileExplorerProps, FileExplorerConnectorState> = FileExplorer
|
||||
export const SideBarCore: Sources<SideBarProps, SideBarConnectorState> = SideBar
|
||||
|
|
|
|||
4
src/global.d.ts
vendored
4
src/global.d.ts
vendored
|
|
@ -1,10 +1,13 @@
|
|||
type MetaData = {
|
||||
userName: string
|
||||
repoName: string
|
||||
defaultBranchName: string
|
||||
branchName: string
|
||||
type?: EnumString<'tree' | 'blob' | 'pull'>
|
||||
}
|
||||
|
||||
type PartialMetaData = Omit<MakeOptional<MetaData, 'branchName'>, 'defaultBranchName'>
|
||||
|
||||
type TreeNode = {
|
||||
name: string
|
||||
contents?: TreeNode[]
|
||||
|
|
@ -13,6 +16,7 @@ type TreeNode = {
|
|||
url?: string
|
||||
sha?: string
|
||||
accessDenied?: boolean
|
||||
comments?: number
|
||||
}
|
||||
|
||||
type IO<T, ChangeT = T> = {
|
||||
|
|
|
|||
|
|
@ -106,6 +106,16 @@ export async function getPullTreeData(
|
|||
return await request(url, { accessToken })
|
||||
}
|
||||
|
||||
export async function getPullComments(
|
||||
userName: string,
|
||||
repoName: string,
|
||||
pullId: string,
|
||||
accessToken?: string,
|
||||
): Promise<GitHubAPI.PullComments> {
|
||||
const url = `https://${API_ENDPOINT}/repos/${userName}/${repoName}/pulls/${pullId}/comments`
|
||||
return await request(url, { accessToken })
|
||||
}
|
||||
|
||||
export async function getPullPageDocument(
|
||||
userName: string,
|
||||
repoName: string,
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ export function CopyFileButton(props: React.PropsWithChildren<Props>) {
|
|||
}, [])
|
||||
|
||||
return (
|
||||
<a ref={elementRef} className={cx('btn btn-sm BtnGroup-item copy-file-btn', className)}>
|
||||
<a ref={elementRef} className={cx('btn btn-sm BtnGroup-item', className)}>
|
||||
{content}
|
||||
</a>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -44,8 +44,9 @@ export function getCurrentBranch(passive = false) {
|
|||
if (branchButtonElement) {
|
||||
const branchNameSpanElement = branchButtonElement.querySelector('span')
|
||||
if (branchNameSpanElement) {
|
||||
const partialBranchNameFromInnerText = branchNameSpanElement.innerText
|
||||
if (!partialBranchNameFromInnerText.includes('…')) return partialBranchNameFromInnerText
|
||||
const partialBranchNameFromInnerText = branchNameSpanElement.textContent || ''
|
||||
if (partialBranchNameFromInnerText && !partialBranchNameFromInnerText.includes('…'))
|
||||
return partialBranchNameFromInnerText
|
||||
}
|
||||
const defaultTitle = 'Switch branches or tags'
|
||||
const title = branchButtonElement.title.trim()
|
||||
|
|
@ -139,6 +140,13 @@ export function getCodeElement() {
|
|||
* click these buttons will copy file content to clipboard
|
||||
*/
|
||||
export function attachCopyFileBtn() {
|
||||
const removeButtons = () => {
|
||||
const buttons = document.querySelectorAll(`.${copyFileButtonClassName}`)
|
||||
buttons.forEach(button => {
|
||||
button.parentElement?.removeChild(button)
|
||||
})
|
||||
}
|
||||
|
||||
if (getCurrentPageType() === PAGE_TYPES.RAW_TEXT) {
|
||||
// the button group in file content header
|
||||
const buttonGroupSelector = '.repository-content .Box-header .BtnGroup'
|
||||
|
|
@ -148,6 +156,8 @@ export function attachCopyFileBtn() {
|
|||
raiseError(new Error(`No button groups found`))
|
||||
}
|
||||
|
||||
removeButtons() // prevent duplicated buttons
|
||||
|
||||
buttonGroups.forEach(async buttonGroup => {
|
||||
if (!buttonGroup.lastElementChild) return
|
||||
const button = await renderReact(React.createElement(CopyFileButton))
|
||||
|
|
@ -158,12 +168,7 @@ export function attachCopyFileBtn() {
|
|||
}
|
||||
|
||||
// return callback so that disabling after redirecting from file page to non-page works properly
|
||||
return () => {
|
||||
const buttons = document.querySelectorAll(`.${copyFileButtonClassName}`)
|
||||
buttons.forEach(button => {
|
||||
button.parentElement?.removeChild(button)
|
||||
})
|
||||
}
|
||||
return removeButtons
|
||||
}
|
||||
|
||||
export function attachCopySnippet() {
|
||||
|
|
@ -228,3 +233,22 @@ export function attachCopySnippet() {
|
|||
)
|
||||
})
|
||||
}
|
||||
|
||||
export function getPath() {
|
||||
const folderPathElementSelector = '.file-navigation .position-relative' // available when in path like '/tree/...'
|
||||
const blobPathElementSelector = '#blob-path' // available when in path like '/blob/...'
|
||||
const pathElement =
|
||||
document.querySelector(blobPathElementSelector) ||
|
||||
document.querySelector(folderPathElementSelector)?.nextElementSibling
|
||||
if (!pathElement?.querySelector('.js-repo-root')) {
|
||||
return []
|
||||
}
|
||||
const path = ((pathElement as HTMLDivElement).textContent || '')
|
||||
.replace(/\n/g, '')
|
||||
.replace(/\/\s+Jump to.*/m, '')
|
||||
.trim()
|
||||
.split('/')
|
||||
.filter(Boolean)
|
||||
.slice(1) // the first is the repo's name
|
||||
return path
|
||||
}
|
||||
|
|
|
|||
12
src/platforms/GitHub/Request.d.ts
vendored
12
src/platforms/GitHub/Request.d.ts
vendored
|
|
@ -35,7 +35,19 @@ declare namespace GitHubAPI {
|
|||
changed_files: number
|
||||
}
|
||||
|
||||
type PullComment = {
|
||||
path: string
|
||||
pull_request_review_id: number
|
||||
id: number
|
||||
node_id: string
|
||||
diff_hunk: string
|
||||
body: string
|
||||
html_url: string
|
||||
author_association: string
|
||||
}
|
||||
|
||||
type PullTreeData = PullTreeItem[]
|
||||
type PullComments = PullComment[]
|
||||
|
||||
type MetaData = {
|
||||
name: string
|
||||
|
|
|
|||
17
src/platforms/GitHub/hooks/useGitHubAttachCopyFileButton.ts
Normal file
17
src/platforms/GitHub/hooks/useGitHubAttachCopyFileButton.ts
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
import { platform } from 'platforms'
|
||||
import * as React from 'react'
|
||||
import { useOnPJAXDone } from 'utils/hooks/usePJAX'
|
||||
import * as DOMHelper from '../DOMHelper'
|
||||
import { GitHub } from '../index'
|
||||
|
||||
export function useGitHubAttachCopyFileButton(copyFileButton: boolean) {
|
||||
const attachCopyFileButton = React.useCallback(
|
||||
function attachCopyFileButton() {
|
||||
if (platform !== GitHub) return
|
||||
if (copyFileButton) return DOMHelper.attachCopyFileBtn() || undefined // for the sake of react effect
|
||||
},
|
||||
[copyFileButton],
|
||||
)
|
||||
React.useEffect(attachCopyFileButton, [copyFileButton])
|
||||
useOnPJAXDone(attachCopyFileButton)
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
import { platform } from 'platforms'
|
||||
import * as React from 'react'
|
||||
import { useOnPJAXDone } from 'utils/hooks/usePJAX'
|
||||
import * as DOMHelper from '../DOMHelper'
|
||||
import { GitHub } from '../index'
|
||||
|
||||
export function useGitHubAttachCopySnippetButton(copySnippetButton: boolean) {
|
||||
const attachCopySnippetButton = React.useCallback(
|
||||
function attachCopySnippetButton() {
|
||||
if (platform !== GitHub) return
|
||||
if (copySnippetButton) return DOMHelper.attachCopySnippet() || undefined // for the sake of react effect
|
||||
},
|
||||
[copySnippetButton],
|
||||
)
|
||||
React.useEffect(attachCopySnippetButton, [copySnippetButton])
|
||||
useOnPJAXDone(attachCopySnippetButton)
|
||||
}
|
||||
162
src/platforms/GitHub/hooks/useGitHubCodeFold.tsx
Normal file
162
src/platforms/GitHub/hooks/useGitHubCodeFold.tsx
Normal file
|
|
@ -0,0 +1,162 @@
|
|||
import { platform } from 'platforms'
|
||||
import { useCallback, useEffect } from 'react'
|
||||
import { useOnPJAXDone } from 'utils/hooks/usePJAX'
|
||||
import { GitHub } from '..'
|
||||
|
||||
const theCSSClassMark = 'gitako-code-fold-attached'
|
||||
const theCSSClassMarkWhenDisabled = 'gitako-code-fold-attached-disabled'
|
||||
const theCSSClassForHiddenLine = 'gitako-code-fold-hidden'
|
||||
const theCSSClassForToggleElement = 'gitako-code-fold-handler'
|
||||
const tableSelector = `.blob-wrapper table`
|
||||
const selectorOfLineNumber = `.blob-num`
|
||||
const selectorOfLineContent = `.blob-code`
|
||||
|
||||
const theCSSClassForToggleElementOnActive = 'active'
|
||||
function init() {
|
||||
type LineNumber = number // alias
|
||||
const blocks: LineNumber[] = [] // startLine -> exclusiveEndLine
|
||||
/**
|
||||
* For example, given such input
|
||||
*
|
||||
* 0 |∇ line1
|
||||
* 1 |∇ line2
|
||||
* 2 |
|
||||
* 3 |∇ line3
|
||||
* 4 | line4
|
||||
* 5 | line5
|
||||
*
|
||||
* blocks will be
|
||||
* 0 -> 5
|
||||
* 1 -> 3
|
||||
* 2
|
||||
* 3 -> 5
|
||||
* 4
|
||||
* 5
|
||||
*/
|
||||
|
||||
const table = document.querySelector(tableSelector)
|
||||
const lineElements = Array.from(document.querySelectorAll([tableSelector, 'tr'].join(' ')))
|
||||
if (!table || !lineElements.length) return
|
||||
if (table.classList.contains(theCSSClassMark)) {
|
||||
if (table.classList.contains(theCSSClassMarkWhenDisabled)) {
|
||||
// reactivate
|
||||
table.classList.remove(theCSSClassMarkWhenDisabled)
|
||||
}
|
||||
return
|
||||
}
|
||||
table.classList.add(theCSSClassMark)
|
||||
|
||||
// setup blocks
|
||||
{
|
||||
type Level = number // measured by leading whitespace amount
|
||||
const stack: [Level, LineNumber][] = []
|
||||
|
||||
function trySeal(lineNumber: number, level: number) {
|
||||
let ignoredTheHighestLevelItem = false
|
||||
while (stack.length) {
|
||||
const top = stack.pop()! // safe
|
||||
const [$LineNumber, $level] = top
|
||||
|
||||
if ($level < level) {
|
||||
stack.push(top)
|
||||
break
|
||||
} else if (!ignoredTheHighestLevelItem) {
|
||||
ignoredTheHighestLevelItem = true
|
||||
} else {
|
||||
blocks[$LineNumber] = lineNumber
|
||||
}
|
||||
}
|
||||
stack.push([lineNumber, level])
|
||||
}
|
||||
|
||||
lineElements.forEach((element, lineNumber) => {
|
||||
const text = element.querySelector(selectorOfLineContent)?.textContent || null
|
||||
if (text === null) return
|
||||
|
||||
const level = getTextLevel(text)
|
||||
if (level === -1) return
|
||||
|
||||
trySeal(lineNumber, level)
|
||||
})
|
||||
|
||||
trySeal(lineElements.length, -1)
|
||||
}
|
||||
|
||||
// attach toggle buttons
|
||||
blocks.forEach((end, line) => {
|
||||
if (!end) return
|
||||
|
||||
const toggleElement = document.createElement('div')
|
||||
toggleElement.setAttribute('role', 'button')
|
||||
toggleElement.classList.add(theCSSClassForToggleElement)
|
||||
|
||||
const lineNumberElement = lineElements[line].querySelector(selectorOfLineNumber)
|
||||
lineNumberElement?.appendChild(toggleElement)
|
||||
})
|
||||
|
||||
const foldLines = new Set<LineNumber>()
|
||||
function toggleLine(line: number) {
|
||||
// const lineElements = Array.from(document.querySelectorAll(lineSelector))
|
||||
const element = lineElements[line]
|
||||
element.classList.toggle(theCSSClassForToggleElementOnActive)
|
||||
if (foldLines.has(line)) {
|
||||
foldLines.delete(line)
|
||||
} else {
|
||||
foldLines.add(line)
|
||||
}
|
||||
|
||||
const linesToHide = new Set<LineNumber>()
|
||||
for (const line of foldLines.values()) {
|
||||
const end = blocks[line]
|
||||
for (let $line = line + 1; $line < end; $line++) linesToHide.add($line)
|
||||
}
|
||||
|
||||
lineElements.forEach((element, i) => {
|
||||
if (linesToHide.has(i)) element.classList.add(theCSSClassForHiddenLine)
|
||||
else element.classList.remove(theCSSClassForHiddenLine)
|
||||
})
|
||||
}
|
||||
|
||||
table.addEventListener('click', e => {
|
||||
if (e.target instanceof HTMLElement) {
|
||||
if (e.target.classList.contains(theCSSClassForToggleElement)) {
|
||||
const tr = e.target.parentElement?.parentElement
|
||||
if (tr) {
|
||||
toggleLine(lineElements.indexOf(tr))
|
||||
e.stopPropagation()
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function cancelToggleFeature() {
|
||||
const table = document.querySelector(tableSelector)
|
||||
table?.classList.add(theCSSClassMarkWhenDisabled)
|
||||
}
|
||||
|
||||
function getTextLevel(text: string) {
|
||||
const leading = countLeadingWhitespace(text)
|
||||
return leading === text.length ? -1 : leading
|
||||
}
|
||||
|
||||
function countLeadingWhitespace(text: string) {
|
||||
let i = 0
|
||||
for (; i < text.length; i++) {
|
||||
// Mixed usage of space and table indentation? ¯\_(ツ)_/¯
|
||||
if (!(text[i] === ' ' || text[i] === '\t' || text[i] === '\n')) break
|
||||
}
|
||||
return i
|
||||
}
|
||||
|
||||
export function useGitHubCodeFold(active: boolean) {
|
||||
const effect = useCallback(() => {
|
||||
if (platform !== GitHub) return
|
||||
if (active) {
|
||||
init()
|
||||
return () => cancelToggleFeature()
|
||||
}
|
||||
}, [active])
|
||||
useEffect(effect, [effect])
|
||||
useOnPJAXDone(effect)
|
||||
}
|
||||
|
|
@ -1,13 +1,15 @@
|
|||
import { useConfigs } from 'containers/ConfigsContext'
|
||||
import { GITHUB_OAUTH } from 'env'
|
||||
import { Base64 } from 'js-base64'
|
||||
import { platform } from 'platforms'
|
||||
import * as React from 'react'
|
||||
import { resolveGitModules } from 'utils/gitSubmodule'
|
||||
import { useOnPJAXDone } from 'utils/hooks/usePJAX'
|
||||
import { sortFoldersToFront } from 'utils/treeParser'
|
||||
import * as API from './API'
|
||||
import * as DOMHelper from './DOMHelper'
|
||||
import { useGitHubAttachCopyFileButton } from './hooks/useGitHubAttachCopyFileButton'
|
||||
import { useGitHubAttachCopySnippetButton } from './hooks/useGitHubAttachCopySnippetButton'
|
||||
import { useGitHubCodeFold } from './hooks/useGitHubCodeFold'
|
||||
import * as URLHelper from './URLHelper'
|
||||
export { useGitHubCodeFold } from './hooks/useGitHubCodeFold'
|
||||
|
||||
function processTree(tree: TreeNode[]): TreeNode {
|
||||
// nodes are created from items and put onto tree
|
||||
|
|
@ -70,9 +72,7 @@ function getUrlForRedirect(
|
|||
// Modern browsers have great support for handling unsafe URL,
|
||||
// It may be possible to sanitize path with
|
||||
// `path => path.includes('#') ? path.replace(/#/g, '%23') : '...'
|
||||
return `https://${
|
||||
window.location.host
|
||||
}/${userName}/${repoName}/${type}/${branchName}/${path
|
||||
return `https://${window.location.host}/${userName}/${repoName}/${type}/${branchName}/${path
|
||||
.split('/')
|
||||
.map(encodeURIComponent)
|
||||
.join('/')}`
|
||||
|
|
@ -82,11 +82,32 @@ export function isEnterprise() {
|
|||
return !window.location.host.endsWith('github.com')
|
||||
}
|
||||
|
||||
function resolvePageScope(defaultBranchName?: string) {
|
||||
const parsed = URLHelper.parse()
|
||||
switch (parsed.type) {
|
||||
case 'blob':
|
||||
case 'tree': {
|
||||
// handle URLs like {user}/{repo}/{'tree'|'blob'}/{sha|branch}, issue #131
|
||||
const branchName = DOMHelper.getCurrentBranch()
|
||||
if (branchName && branchName !== defaultBranchName) return `branch-${branchName}`
|
||||
break
|
||||
}
|
||||
case 'tags':
|
||||
return 'tags'
|
||||
case 'releases':
|
||||
return 'releases'
|
||||
case 'pull':
|
||||
const pullId = URLHelper.isInPullPage()
|
||||
if (pullId) return `pull-${pullId}`
|
||||
}
|
||||
return 'general'
|
||||
}
|
||||
|
||||
const pathSHAMap = new Map<string, string>()
|
||||
|
||||
export const GitHub: Platform = {
|
||||
isEnterprise,
|
||||
resolveMeta() {
|
||||
resolvePartialMetaData() {
|
||||
if (!DOMHelper.isInRepoPage()) {
|
||||
return null
|
||||
}
|
||||
|
|
@ -119,8 +140,7 @@ export const GitHub: Platform = {
|
|||
return metaData
|
||||
},
|
||||
async getDefaultBranchName({ userName, repoName }, accessToken) {
|
||||
const data = await API.getRepoMeta(userName, repoName, accessToken)
|
||||
return data.default_branch
|
||||
return (await API.getRepoMeta(userName, repoName, accessToken)).default_branch
|
||||
},
|
||||
resolveUrlFromMetaData({ userName, repoName }) {
|
||||
return {
|
||||
|
|
@ -140,9 +160,10 @@ export const GitHub: Platform = {
|
|||
GITHUB_API_RESPONSE_LENGTH_LIMIT / GITHUB_API_PAGED_RESPONSE_LENGTH_LIMIT,
|
||||
)
|
||||
let page = 1
|
||||
const [pullData, treeData] = await Promise.all([
|
||||
const [pullData, treeData, commentData] = await Promise.all([
|
||||
API.getPullData(userName, repoName, pullId, accessToken),
|
||||
API.getPullTreeData(userName, repoName, pullId, page, accessToken),
|
||||
API.getPullComments(userName, repoName, pullId, accessToken),
|
||||
])
|
||||
|
||||
const count = pullData.changed_files
|
||||
|
|
@ -170,6 +191,7 @@ export const GitHub: Platform = {
|
|||
window.location.search
|
||||
}#${creator(item.filename) || ''}`,
|
||||
sha: item.sha,
|
||||
comments: commentData?.filter(comment => item.filename === comment.path).length,
|
||||
}))
|
||||
|
||||
const root = processTree(nodes)
|
||||
|
|
@ -235,7 +257,11 @@ export const GitHub: Platform = {
|
|||
return Boolean(URLHelper.isInPullPage())
|
||||
},
|
||||
getCurrentPath(branchName) {
|
||||
return URLHelper.getCurrentPath(branchName)
|
||||
if (URLHelper.parse().path.length) {
|
||||
return DOMHelper.getPath()
|
||||
} else {
|
||||
return []
|
||||
}
|
||||
},
|
||||
setOAuth(code) {
|
||||
return API.OAuth(code)
|
||||
|
|
@ -248,6 +274,12 @@ export const GitHub: Platform = {
|
|||
})
|
||||
return `https://github.com/login/oauth/authorize?` + params.toString()
|
||||
},
|
||||
usePlatformHooks() {
|
||||
const { copyFileButton, copySnippetButton, codeFolding } = useConfigs().value
|
||||
useGitHubAttachCopyFileButton(copyFileButton)
|
||||
useGitHubAttachCopySnippetButton(copySnippetButton)
|
||||
useGitHubCodeFold(codeFolding)
|
||||
},
|
||||
}
|
||||
|
||||
async function createPullFileResolver(userName: string, repoName: string, pullId: string) {
|
||||
|
|
@ -258,54 +290,3 @@ async function createPullFileResolver(userName: string, repoName: string, pullId
|
|||
return id
|
||||
}
|
||||
}
|
||||
|
||||
function findMissingFolders(nodes: TreeNode[]) {
|
||||
const folders = new Set<string>()
|
||||
const foundFolders = new Set<string>()
|
||||
for (const node of nodes) {
|
||||
let path = node.path
|
||||
if (node.type === 'tree') foundFolders.add(path)
|
||||
else {
|
||||
while (true) {
|
||||
// 'a/b' -> 'a'
|
||||
// 'a' -> ''
|
||||
path = path.substring(0, path.lastIndexOf('/'))
|
||||
if (path === '') break
|
||||
folders.add(path)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const missingFolders: string[] = []
|
||||
for (const folder of folders) {
|
||||
if (!foundFolders.has(folder)) {
|
||||
missingFolders.push(folder)
|
||||
}
|
||||
}
|
||||
|
||||
return missingFolders
|
||||
}
|
||||
|
||||
export function useGitHubAttachCopySnippetButton(copySnippetButton: boolean) {
|
||||
const attachCopySnippetButton = React.useCallback(
|
||||
function attachCopySnippetButton() {
|
||||
if (platform !== GitHub) return
|
||||
if (copySnippetButton) return DOMHelper.attachCopySnippet() || undefined // for the sake of react effect
|
||||
},
|
||||
[copySnippetButton],
|
||||
)
|
||||
React.useEffect(attachCopySnippetButton, [copySnippetButton])
|
||||
useOnPJAXDone(attachCopySnippetButton)
|
||||
}
|
||||
|
||||
export function useGitHubAttachCopyFileButton(copyFileButton: boolean) {
|
||||
const attachCopyFileButton = React.useCallback(
|
||||
function attachCopyFileButton() {
|
||||
if (platform !== GitHub) return
|
||||
if (copyFileButton) return DOMHelper.attachCopyFileBtn() || undefined // for the sake of react effect
|
||||
},
|
||||
[copyFileButton],
|
||||
)
|
||||
React.useEffect(attachCopyFileButton, [copyFileButton])
|
||||
useOnPJAXDone(attachCopyFileButton)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -57,14 +57,14 @@ async function request(
|
|||
}
|
||||
}
|
||||
|
||||
export const API_ENDPOINT = `${window.location.host}/api/v1`
|
||||
export const API_ENDPOINT = `${window.location.protocol}//${window.location.host}/api/v1`
|
||||
|
||||
export async function getRepoMeta(
|
||||
userName: string,
|
||||
repoName: string,
|
||||
accessToken?: string,
|
||||
): Promise<GiteaAPI.MetaData> {
|
||||
const url = `https://${API_ENDPOINT}/repos/${userName}/${repoName}`
|
||||
const url = `${API_ENDPOINT}/repos/${userName}/${repoName}`
|
||||
return await request(url, { accessToken })
|
||||
}
|
||||
|
||||
|
|
@ -78,7 +78,7 @@ export async function getTreeData(
|
|||
const search = new URLSearchParams()
|
||||
if (recursive) search.set('recursive', '1')
|
||||
const url =
|
||||
`https://${API_ENDPOINT}/repos/${userName}/${repoName}/git/trees/${branchName}?` + search
|
||||
`${API_ENDPOINT}/repos/${userName}/${repoName}/git/trees/${branchName}?` + search
|
||||
return await request(url, { accessToken })
|
||||
}
|
||||
|
||||
|
|
@ -88,7 +88,7 @@ export async function getBlobData(
|
|||
sha: string,
|
||||
accessToken?: string,
|
||||
): Promise<GitHubAPI.BlobData> {
|
||||
const url = `https://${API_ENDPOINT}/repos/${userName}/${repoName}/git/blobs/${sha}`
|
||||
const url = `${API_ENDPOINT}/repos/${userName}/${repoName}/git/blobs/${sha}`
|
||||
return await request(url, { accessToken })
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ function getUrlForRedirect(
|
|||
// Modern browsers have great support for handling unsafe URL,
|
||||
// It may be possible to sanitize path with
|
||||
// `path => path.includes('#') ? path.replace(/#/g, '%23') : '...'
|
||||
return `https://${
|
||||
return `${window.location.protocol}//${
|
||||
window.location.host
|
||||
}/${userName}/${repoName}/src/branch/${branchName}/${path
|
||||
.split('/')
|
||||
|
|
@ -77,7 +77,7 @@ export const Gitea: Platform = {
|
|||
isEnterprise() {
|
||||
return !window.location.host.endsWith('gitea.com')
|
||||
},
|
||||
resolveMeta() {
|
||||
resolvePartialMetaData() {
|
||||
if (!DOMHelper.isInRepoPage()) {
|
||||
return null
|
||||
}
|
||||
|
|
@ -107,8 +107,8 @@ export const Gitea: Platform = {
|
|||
},
|
||||
resolveUrlFromMetaData({ userName, repoName }) {
|
||||
return {
|
||||
repoUrl: `https://${window.location.host}/${userName}/${repoName}`,
|
||||
userUrl: `https://${window.location.host}/${userName}`,
|
||||
repoUrl: `${window.location.protocol}//${window.location.host}/${userName}/${repoName}`,
|
||||
userUrl: `${window.location.protocol}//${window.location.host}/${userName}`,
|
||||
}
|
||||
},
|
||||
async getTreeData(metaData, path, recursive, accessToken) {
|
||||
|
|
@ -163,6 +163,6 @@ export const Gitea: Platform = {
|
|||
return API.OAuth(code)
|
||||
},
|
||||
getOAuthLink() {
|
||||
return `https://${window.location.host}/api/v1/user/applications/oauth2`
|
||||
return `${window.location.protocol}//${window.location.host}/api/v1/user/applications/oauth2`
|
||||
},
|
||||
}
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ export const Gitee: Platform = {
|
|||
isEnterprise() {
|
||||
return !window.location.host.endsWith('gitee.com')
|
||||
},
|
||||
resolveMeta() {
|
||||
resolvePartialMetaData() {
|
||||
if (!DOMHelper.isInRepoPage()) {
|
||||
return null
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ export const dummyPlatformForTypeSafety: Platform = {
|
|||
isEnterprise() {
|
||||
return false
|
||||
},
|
||||
resolveMeta() {
|
||||
resolvePartialMetaData() {
|
||||
return null
|
||||
},
|
||||
getDefaultBranchName: dummyPlatformMethod,
|
||||
|
|
|
|||
|
|
@ -1,11 +1,9 @@
|
|||
import { dummyPlatformForTypeSafety } from './dummyPlatformForTypeSafety'
|
||||
import { Gitee } from './Gitee'
|
||||
import { Gitea } from './Gitea'
|
||||
import { Gitee } from './Gitee'
|
||||
import { GitHub } from './GitHub'
|
||||
|
||||
const platforms: {
|
||||
[name: string]: Platform
|
||||
} = {
|
||||
const platforms = {
|
||||
GitHub: GitHub,
|
||||
Gitee: Gitee,
|
||||
Gitea: Gitea,
|
||||
|
|
@ -13,7 +11,7 @@ const platforms: {
|
|||
|
||||
function resolvePlatform() {
|
||||
for (const platform of Object.values(platforms)) {
|
||||
if (platform.resolveMeta()) return platform
|
||||
if (platform.resolvePartialMetaData()) return platform
|
||||
}
|
||||
return dummyPlatformForTypeSafety
|
||||
}
|
||||
|
|
|
|||
10
src/platforms/platform.d.ts
vendored
10
src/platforms/platform.d.ts
vendored
|
|
@ -1,19 +1,18 @@
|
|||
type Platform = {
|
||||
isEnterprise(): boolean
|
||||
// branch name might not be available when resolving from DOM and URL
|
||||
resolveMeta(): MakeOptional<MetaData, 'branchName'> | null
|
||||
resolvePartialMetaData(): PartialMetaData | null
|
||||
// resolveMetaData(metaData: PartialMetaData, accessToken?: string): Async<MetaData>
|
||||
getDefaultBranchName(
|
||||
metaData: Pick<MetaData, 'userName' | 'repoName'>,
|
||||
accessToken?: string,
|
||||
): Promise<string>
|
||||
resolveUrlFromMetaData(
|
||||
metaData: MetaData,
|
||||
): {
|
||||
resolveUrlFromMetaData(metaData: Pick<MetaData, 'userName' | 'repoName'>): {
|
||||
userUrl: string
|
||||
repoUrl: string
|
||||
}
|
||||
getTreeData(
|
||||
metaData: MetaData,
|
||||
metaData: Pick<MetaData, 'userName' | 'repoName' | 'branchName'>,
|
||||
path?: string,
|
||||
recursive?: boolean,
|
||||
accessToken?: string,
|
||||
|
|
@ -23,4 +22,5 @@ type Platform = {
|
|||
getCurrentPath(branchName: string): string[] | null
|
||||
setOAuth(code: string): Promise<string | null>
|
||||
getOAuthLink(): string
|
||||
usePlatformHooks?(): void
|
||||
}
|
||||
|
|
|
|||
68
src/resize-observer.d.ts
vendored
68
src/resize-observer.d.ts
vendored
|
|
@ -1,68 +0,0 @@
|
|||
interface Window {
|
||||
ResizeObserver: ResizeObserver
|
||||
}
|
||||
|
||||
/**
|
||||
* The ResizeObserver interface is used to observe changes to Element's content
|
||||
* rect.
|
||||
*
|
||||
* It is modeled after MutationObserver and IntersectionObserver.
|
||||
*/
|
||||
interface ResizeObserver {
|
||||
new (callback: ResizeObserverCallback): ResizeObserver
|
||||
|
||||
/**
|
||||
* Adds target to the list of observed elements.
|
||||
*/
|
||||
observe: (target: Element) => void
|
||||
|
||||
/**
|
||||
* Removes target from the list of observed elements.
|
||||
*/
|
||||
unobserve: (target: Element) => void
|
||||
|
||||
/**
|
||||
* Clears both the observationTargets and activeTargets lists.
|
||||
*/
|
||||
disconnect: () => void
|
||||
}
|
||||
|
||||
/**
|
||||
* This callback delivers ResizeObserver's notifications. It is invoked by a
|
||||
* broadcast active observations algorithm.
|
||||
*/
|
||||
interface ResizeObserverCallback {
|
||||
(entries: ResizeObserverEntry[], observer: ResizeObserver): void
|
||||
}
|
||||
|
||||
interface ResizeObserverEntry {
|
||||
/**
|
||||
* @param target The Element whose size has changed.
|
||||
*/
|
||||
new (target: Element): void
|
||||
|
||||
/**
|
||||
* The Element whose size has changed.
|
||||
*/
|
||||
readonly target: Element
|
||||
|
||||
/**
|
||||
* Element's content rect when ResizeObserverCallback is invoked.
|
||||
*/
|
||||
readonly contentRect: DOMRectReadOnly
|
||||
}
|
||||
|
||||
interface DOMRectReadOnly {
|
||||
// static fromRect(other: DOMRectInit | undefined): DOMRectReadOnly;
|
||||
|
||||
readonly x: number
|
||||
readonly y: number
|
||||
readonly width: number
|
||||
readonly height: number
|
||||
readonly top: number
|
||||
readonly right: number
|
||||
readonly bottom: number
|
||||
readonly left: number
|
||||
|
||||
toJSON: () => any
|
||||
}
|
||||
|
|
@ -1,579 +0,0 @@
|
|||
@use './variables.scss' as variables;
|
||||
|
||||
@mixin assign {
|
||||
--gitako-auto-black: #{variables.$auto-black};
|
||||
--gitako-auto-white: #{variables.$auto-white};
|
||||
--gitako-auto-gray-0: #{variables.$auto-gray-0};
|
||||
--gitako-auto-gray-1: #{variables.$auto-gray-1};
|
||||
--gitako-auto-gray-2: #{variables.$auto-gray-2};
|
||||
--gitako-auto-gray-3: #{variables.$auto-gray-3};
|
||||
--gitako-auto-gray-4: #{variables.$auto-gray-4};
|
||||
--gitako-auto-gray-5: #{variables.$auto-gray-5};
|
||||
--gitako-auto-gray-6: #{variables.$auto-gray-6};
|
||||
--gitako-auto-gray-7: #{variables.$auto-gray-7};
|
||||
--gitako-auto-gray-8: #{variables.$auto-gray-8};
|
||||
--gitako-auto-gray-9: #{variables.$auto-gray-9};
|
||||
--gitako-auto-blue-0: #{variables.$auto-blue-0};
|
||||
--gitako-auto-blue-1: #{variables.$auto-blue-1};
|
||||
--gitako-auto-blue-2: #{variables.$auto-blue-2};
|
||||
--gitako-auto-blue-3: #{variables.$auto-blue-3};
|
||||
--gitako-auto-blue-4: #{variables.$auto-blue-4};
|
||||
--gitako-auto-blue-5: #{variables.$auto-blue-5};
|
||||
--gitako-auto-blue-6: #{variables.$auto-blue-6};
|
||||
--gitako-auto-blue-7: #{variables.$auto-blue-7};
|
||||
--gitako-auto-blue-8: #{variables.$auto-blue-8};
|
||||
--gitako-auto-blue-9: #{variables.$auto-blue-9};
|
||||
--gitako-auto-green-0: #{variables.$auto-green-0};
|
||||
--gitako-auto-green-1: #{variables.$auto-green-1};
|
||||
--gitako-auto-green-2: #{variables.$auto-green-2};
|
||||
--gitako-auto-green-3: #{variables.$auto-green-3};
|
||||
--gitako-auto-green-4: #{variables.$auto-green-4};
|
||||
--gitako-auto-green-5: #{variables.$auto-green-5};
|
||||
--gitako-auto-green-6: #{variables.$auto-green-6};
|
||||
--gitako-auto-green-7: #{variables.$auto-green-7};
|
||||
--gitako-auto-green-8: #{variables.$auto-green-8};
|
||||
--gitako-auto-green-9: #{variables.$auto-green-9};
|
||||
--gitako-auto-yellow-0: #{variables.$auto-yellow-0};
|
||||
--gitako-auto-yellow-1: #{variables.$auto-yellow-1};
|
||||
--gitako-auto-yellow-2: #{variables.$auto-yellow-2};
|
||||
--gitako-auto-yellow-3: #{variables.$auto-yellow-3};
|
||||
--gitako-auto-yellow-4: #{variables.$auto-yellow-4};
|
||||
--gitako-auto-yellow-5: #{variables.$auto-yellow-5};
|
||||
--gitako-auto-yellow-6: #{variables.$auto-yellow-6};
|
||||
--gitako-auto-yellow-7: #{variables.$auto-yellow-7};
|
||||
--gitako-auto-yellow-8: #{variables.$auto-yellow-8};
|
||||
--gitako-auto-yellow-9: #{variables.$auto-yellow-9};
|
||||
--gitako-auto-orange-0: #{variables.$auto-orange-0};
|
||||
--gitako-auto-orange-1: #{variables.$auto-orange-1};
|
||||
--gitako-auto-orange-2: #{variables.$auto-orange-2};
|
||||
--gitako-auto-orange-3: #{variables.$auto-orange-3};
|
||||
--gitako-auto-orange-4: #{variables.$auto-orange-4};
|
||||
--gitako-auto-orange-5: #{variables.$auto-orange-5};
|
||||
--gitako-auto-orange-6: #{variables.$auto-orange-6};
|
||||
--gitako-auto-orange-7: #{variables.$auto-orange-7};
|
||||
--gitako-auto-orange-8: #{variables.$auto-orange-8};
|
||||
--gitako-auto-orange-9: #{variables.$auto-orange-9};
|
||||
--gitako-auto-red-0: #{variables.$auto-red-0};
|
||||
--gitako-auto-red-1: #{variables.$auto-red-1};
|
||||
--gitako-auto-red-2: #{variables.$auto-red-2};
|
||||
--gitako-auto-red-3: #{variables.$auto-red-3};
|
||||
--gitako-auto-red-4: #{variables.$auto-red-4};
|
||||
--gitako-auto-red-5: #{variables.$auto-red-5};
|
||||
--gitako-auto-red-6: #{variables.$auto-red-6};
|
||||
--gitako-auto-red-7: #{variables.$auto-red-7};
|
||||
--gitako-auto-red-8: #{variables.$auto-red-8};
|
||||
--gitako-auto-red-9: #{variables.$auto-red-9};
|
||||
--gitako-auto-purple-0: #{variables.$auto-purple-0};
|
||||
--gitako-auto-purple-1: #{variables.$auto-purple-1};
|
||||
--gitako-auto-purple-2: #{variables.$auto-purple-2};
|
||||
--gitako-auto-purple-3: #{variables.$auto-purple-3};
|
||||
--gitako-auto-purple-4: #{variables.$auto-purple-4};
|
||||
--gitako-auto-purple-5: #{variables.$auto-purple-5};
|
||||
--gitako-auto-purple-6: #{variables.$auto-purple-6};
|
||||
--gitako-auto-purple-7: #{variables.$auto-purple-7};
|
||||
--gitako-auto-purple-8: #{variables.$auto-purple-8};
|
||||
--gitako-auto-purple-9: #{variables.$auto-purple-9};
|
||||
--gitako-auto-pink-0: #{variables.$auto-pink-0};
|
||||
--gitako-auto-pink-1: #{variables.$auto-pink-1};
|
||||
--gitako-auto-pink-2: #{variables.$auto-pink-2};
|
||||
--gitako-auto-pink-3: #{variables.$auto-pink-3};
|
||||
--gitako-auto-pink-4: #{variables.$auto-pink-4};
|
||||
--gitako-auto-pink-5: #{variables.$auto-pink-5};
|
||||
--gitako-auto-pink-6: #{variables.$auto-pink-6};
|
||||
--gitako-auto-pink-7: #{variables.$auto-pink-7};
|
||||
--gitako-auto-pink-8: #{variables.$auto-pink-8};
|
||||
--gitako-auto-pink-9: #{variables.$auto-pink-9};
|
||||
--gitako-text-primary: #{variables.$text-primary};
|
||||
--gitako-text-secondary: #{variables.$text-secondary};
|
||||
--gitako-text-tertiary: #{variables.$text-tertiary};
|
||||
--gitako-text-placeholder: #{variables.$text-placeholder};
|
||||
--gitako-text-disabled: #{variables.$text-disabled};
|
||||
--gitako-text-inverse: #{variables.$text-inverse};
|
||||
--gitako-text-link: #{variables.$text-link};
|
||||
--gitako-text-danger: #{variables.$text-danger};
|
||||
--gitako-text-success: #{variables.$text-success};
|
||||
--gitako-text-warning: #{variables.$text-warning};
|
||||
--gitako-text-white: #{variables.$text-white};
|
||||
--gitako-icon-primary: #{variables.$icon-primary};
|
||||
--gitako-icon-secondary: #{variables.$icon-secondary};
|
||||
--gitako-icon-tertiary: #{variables.$icon-tertiary};
|
||||
--gitako-icon-info: #{variables.$icon-info};
|
||||
--gitako-icon-danger: #{variables.$icon-danger};
|
||||
--gitako-icon-success: #{variables.$icon-success};
|
||||
--gitako-icon-warning: #{variables.$icon-warning};
|
||||
--gitako-border-primary: #{variables.$border-primary};
|
||||
--gitako-border-secondary: #{variables.$border-secondary};
|
||||
--gitako-border-tertiary: #{variables.$border-tertiary};
|
||||
--gitako-border-overlay: #{variables.$border-overlay};
|
||||
--gitako-border-inverse: #{variables.$border-inverse};
|
||||
--gitako-border-info: #{variables.$border-info};
|
||||
--gitako-border-danger: #{variables.$border-danger};
|
||||
--gitako-border-success: #{variables.$border-success};
|
||||
--gitako-border-warning: #{variables.$border-warning};
|
||||
--gitako-bg-canvas: #{variables.$bg-canvas};
|
||||
--gitako-bg-canvas-mobile: #{variables.$bg-canvas-mobile};
|
||||
--gitako-bg-canvas-inverse: #{variables.$bg-canvas-inverse};
|
||||
--gitako-bg-canvas-inset: #{variables.$bg-canvas-inset};
|
||||
--gitako-bg-primary: #{variables.$bg-primary};
|
||||
--gitako-bg-secondary: #{variables.$bg-secondary};
|
||||
--gitako-bg-tertiary: #{variables.$bg-tertiary};
|
||||
--gitako-bg-overlay: #{variables.$bg-overlay};
|
||||
--gitako-bg-backdrop: #{variables.$bg-backdrop};
|
||||
--gitako-bg-info: #{variables.$bg-info};
|
||||
--gitako-bg-info-inverse: #{variables.$bg-info-inverse};
|
||||
--gitako-bg-danger: #{variables.$bg-danger};
|
||||
--gitako-bg-danger-inverse: #{variables.$bg-danger-inverse};
|
||||
--gitako-bg-success: #{variables.$bg-success};
|
||||
--gitako-bg-success-inverse: #{variables.$bg-success-inverse};
|
||||
--gitako-bg-warning: #{variables.$bg-warning};
|
||||
--gitako-bg-warning-inverse: #{variables.$bg-warning-inverse};
|
||||
--gitako-shadow-small: #{variables.$shadow-small};
|
||||
--gitako-shadow-medium: #{variables.$shadow-medium};
|
||||
--gitako-shadow-large: #{variables.$shadow-large};
|
||||
--gitako-shadow-extra-large: #{variables.$shadow-extra-large};
|
||||
--gitako-shadow-highlight: #{variables.$shadow-highlight};
|
||||
--gitako-shadow-inset: #{variables.$shadow-inset};
|
||||
--gitako-state-hover-primary-bg: #{variables.$state-hover-primary-bg};
|
||||
--gitako-state-hover-primary-border: #{variables.$state-hover-primary-border};
|
||||
--gitako-state-hover-primary-text: #{variables.$state-hover-primary-text};
|
||||
--gitako-state-hover-primary-icon: #{variables.$state-hover-primary-icon};
|
||||
--gitako-state-hover-secondary-bg: #{variables.$state-hover-secondary-bg};
|
||||
--gitako-state-hover-secondary-border: #{variables.$state-hover-secondary-border};
|
||||
--gitako-state-selected-primary-bg: #{variables.$state-selected-primary-bg};
|
||||
--gitako-state-selected-primary-border: #{variables.$state-selected-primary-border};
|
||||
--gitako-state-selected-primary-text: #{variables.$state-selected-primary-text};
|
||||
--gitako-state-selected-primary-icon: #{variables.$state-selected-primary-icon};
|
||||
--gitako-state-focus-border: #{variables.$state-focus-border};
|
||||
--gitako-state-focus-shadow: #{variables.$state-focus-shadow};
|
||||
--gitako-fade-fg-10: #{variables.$fade-fg-10};
|
||||
--gitako-fade-fg-15: #{variables.$fade-fg-15};
|
||||
--gitako-fade-fg-30: #{variables.$fade-fg-30};
|
||||
--gitako-fade-fg-50: #{variables.$fade-fg-50};
|
||||
--gitako-fade-fg-70: #{variables.$fade-fg-70};
|
||||
--gitako-fade-fg-85: #{variables.$fade-fg-85};
|
||||
--gitako-fade-black-10: #{variables.$fade-black-10};
|
||||
--gitako-fade-black-15: #{variables.$fade-black-15};
|
||||
--gitako-fade-black-30: #{variables.$fade-black-30};
|
||||
--gitako-fade-black-50: #{variables.$fade-black-50};
|
||||
--gitako-fade-black-70: #{variables.$fade-black-70};
|
||||
--gitako-fade-black-85: #{variables.$fade-black-85};
|
||||
--gitako-fade-white-10: #{variables.$fade-white-10};
|
||||
--gitako-fade-white-15: #{variables.$fade-white-15};
|
||||
--gitako-fade-white-30: #{variables.$fade-white-30};
|
||||
--gitako-fade-white-50: #{variables.$fade-white-50};
|
||||
--gitako-fade-white-70: #{variables.$fade-white-70};
|
||||
--gitako-fade-white-85: #{variables.$fade-white-85};
|
||||
--gitako-alert-info-text: #{variables.$alert-info-text};
|
||||
--gitako-alert-info-icon: #{variables.$alert-info-icon};
|
||||
--gitako-alert-info-bg: #{variables.$alert-info-bg};
|
||||
--gitako-alert-info-border: #{variables.$alert-info-border};
|
||||
--gitako-alert-warn-text: #{variables.$alert-warn-text};
|
||||
--gitako-alert-warn-icon: #{variables.$alert-warn-icon};
|
||||
--gitako-alert-warn-bg: #{variables.$alert-warn-bg};
|
||||
--gitako-alert-warn-border: #{variables.$alert-warn-border};
|
||||
--gitako-alert-error-text: #{variables.$alert-error-text};
|
||||
--gitako-alert-error-icon: #{variables.$alert-error-icon};
|
||||
--gitako-alert-error-bg: #{variables.$alert-error-bg};
|
||||
--gitako-alert-error-border: #{variables.$alert-error-border};
|
||||
--gitako-alert-success-text: #{variables.$alert-success-text};
|
||||
--gitako-alert-success-icon: #{variables.$alert-success-icon};
|
||||
--gitako-alert-success-bg: #{variables.$alert-success-bg};
|
||||
--gitako-alert-success-border: #{variables.$alert-success-border};
|
||||
--gitako-autocomplete-shadow: #{variables.$autocomplete-shadow};
|
||||
--gitako-autocomplete-row-border: #{variables.$autocomplete-row-border};
|
||||
--gitako-blankslate-icon: #{variables.$blankslate-icon};
|
||||
--gitako-btn-text: #{variables.$btn-text};
|
||||
--gitako-btn-bg: #{variables.$btn-bg};
|
||||
--gitako-btn-border: #{variables.$btn-border};
|
||||
--gitako-btn-shadow: #{variables.$btn-shadow};
|
||||
--gitako-btn-inset-shadow: #{variables.$btn-inset-shadow};
|
||||
--gitako-btn-hover-bg: #{variables.$btn-hover-bg};
|
||||
--gitako-btn-hover-border: #{variables.$btn-hover-border};
|
||||
--gitako-btn-selected-bg: #{variables.$btn-selected-bg};
|
||||
--gitako-btn-focus-bg: #{variables.$btn-focus-bg};
|
||||
--gitako-btn-focus-border: #{variables.$btn-focus-border};
|
||||
--gitako-btn-focus-shadow: #{variables.$btn-focus-shadow};
|
||||
--gitako-btn-shadow-active: #{variables.$btn-shadow-active};
|
||||
--gitako-btn-shadow-input-focus: #{variables.$btn-shadow-input-focus};
|
||||
--gitako-btn-primary-text: #{variables.$btn-primary-text};
|
||||
--gitako-btn-primary-bg: #{variables.$btn-primary-bg};
|
||||
--gitako-btn-primary-border: #{variables.$btn-primary-border};
|
||||
--gitako-btn-primary-shadow: #{variables.$btn-primary-shadow};
|
||||
--gitako-btn-primary-inset-shadow: #{variables.$btn-primary-inset-shadow};
|
||||
--gitako-btn-primary-hover-bg: #{variables.$btn-primary-hover-bg};
|
||||
--gitako-btn-primary-hover-border: #{variables.$btn-primary-hover-border};
|
||||
--gitako-btn-primary-selected-bg: #{variables.$btn-primary-selected-bg};
|
||||
--gitako-btn-primary-selected-shadow: #{variables.$btn-primary-selected-shadow};
|
||||
--gitako-btn-primary-disabled-text: #{variables.$btn-primary-disabled-text};
|
||||
--gitako-btn-primary-disabled-bg: #{variables.$btn-primary-disabled-bg};
|
||||
--gitako-btn-primary-disabled-border: #{variables.$btn-primary-disabled-border};
|
||||
--gitako-btn-primary-focus-bg: #{variables.$btn-primary-focus-bg};
|
||||
--gitako-btn-primary-focus-border: #{variables.$btn-primary-focus-border};
|
||||
--gitako-btn-primary-focus-shadow: #{variables.$btn-primary-focus-shadow};
|
||||
--gitako-btn-primary-icon: #{variables.$btn-primary-icon};
|
||||
--gitako-btn-primary-counter-bg: #{variables.$btn-primary-counter-bg};
|
||||
--gitako-btn-outline-text: #{variables.$btn-outline-text};
|
||||
--gitako-btn-outline-hover-text: #{variables.$btn-outline-hover-text};
|
||||
--gitako-btn-outline-hover-bg: #{variables.$btn-outline-hover-bg};
|
||||
--gitako-btn-outline-hover-border: #{variables.$btn-outline-hover-border};
|
||||
--gitako-btn-outline-hover-shadow: #{variables.$btn-outline-hover-shadow};
|
||||
--gitako-btn-outline-hover-inset-shadow: #{variables.$btn-outline-hover-inset-shadow};
|
||||
--gitako-btn-outline-hover-counter-bg: #{variables.$btn-outline-hover-counter-bg};
|
||||
--gitako-btn-outline-selected-text: #{variables.$btn-outline-selected-text};
|
||||
--gitako-btn-outline-selected-bg: #{variables.$btn-outline-selected-bg};
|
||||
--gitako-btn-outline-selected-border: #{variables.$btn-outline-selected-border};
|
||||
--gitako-btn-outline-selected-shadow: #{variables.$btn-outline-selected-shadow};
|
||||
--gitako-btn-outline-disabled-text: #{variables.$btn-outline-disabled-text};
|
||||
--gitako-btn-outline-disabled-bg: #{variables.$btn-outline-disabled-bg};
|
||||
--gitako-btn-outline-disabled-counter-bg: #{variables.$btn-outline-disabled-counter-bg};
|
||||
--gitako-btn-outline-focus-border: #{variables.$btn-outline-focus-border};
|
||||
--gitako-btn-outline-focus-shadow: #{variables.$btn-outline-focus-shadow};
|
||||
--gitako-btn-outline-counter-bg: #{variables.$btn-outline-counter-bg};
|
||||
--gitako-btn-danger-text: #{variables.$btn-danger-text};
|
||||
--gitako-btn-danger-hover-text: #{variables.$btn-danger-hover-text};
|
||||
--gitako-btn-danger-hover-bg: #{variables.$btn-danger-hover-bg};
|
||||
--gitako-btn-danger-hover-border: #{variables.$btn-danger-hover-border};
|
||||
--gitako-btn-danger-hover-shadow: #{variables.$btn-danger-hover-shadow};
|
||||
--gitako-btn-danger-hover-inset-shadow: #{variables.$btn-danger-hover-inset-shadow};
|
||||
--gitako-btn-danger-hover-counter-bg: #{variables.$btn-danger-hover-counter-bg};
|
||||
--gitako-btn-danger-selected-text: #{variables.$btn-danger-selected-text};
|
||||
--gitako-btn-danger-selected-bg: #{variables.$btn-danger-selected-bg};
|
||||
--gitako-btn-danger-selected-border: #{variables.$btn-danger-selected-border};
|
||||
--gitako-btn-danger-selected-shadow: #{variables.$btn-danger-selected-shadow};
|
||||
--gitako-btn-danger-disabled-text: #{variables.$btn-danger-disabled-text};
|
||||
--gitako-btn-danger-disabled-bg: #{variables.$btn-danger-disabled-bg};
|
||||
--gitako-btn-danger-disabled-counter-bg: #{variables.$btn-danger-disabled-counter-bg};
|
||||
--gitako-btn-danger-focus-border: #{variables.$btn-danger-focus-border};
|
||||
--gitako-btn-danger-focus-shadow: #{variables.$btn-danger-focus-shadow};
|
||||
--gitako-btn-danger-counter-bg: #{variables.$btn-danger-counter-bg};
|
||||
--gitako-btn-counter-bg: #{variables.$btn-counter-bg};
|
||||
--gitako-counter-text: #{variables.$counter-text};
|
||||
--gitako-counter-bg: #{variables.$counter-bg};
|
||||
--gitako-counter-primary-text: #{variables.$counter-primary-text};
|
||||
--gitako-counter-primary-bg: #{variables.$counter-primary-bg};
|
||||
--gitako-counter-secondary-text: #{variables.$counter-secondary-text};
|
||||
--gitako-dropdown-shadow: #{variables.$dropdown-shadow};
|
||||
--gitako-label-border: #{variables.$label-border};
|
||||
--gitako-label-primary-text: #{variables.$label-primary-text};
|
||||
--gitako-label-primary-border: #{variables.$label-primary-border};
|
||||
--gitako-label-secondary-text: #{variables.$label-secondary-text};
|
||||
--gitako-label-secondary-border: #{variables.$label-secondary-border};
|
||||
--gitako-label-info-text: #{variables.$label-info-text};
|
||||
--gitako-label-info-border: #{variables.$label-info-border};
|
||||
--gitako-label-success-text: #{variables.$label-success-text};
|
||||
--gitako-label-success-border: #{variables.$label-success-border};
|
||||
--gitako-label-warning-text: #{variables.$label-warning-text};
|
||||
--gitako-label-warning-border: #{variables.$label-warning-border};
|
||||
--gitako-label-danger-text: #{variables.$label-danger-text};
|
||||
--gitako-label-danger-border: #{variables.$label-danger-border};
|
||||
--gitako-label-orange-text: #{variables.$label-orange-text};
|
||||
--gitako-label-orange-border: #{variables.$label-orange-border};
|
||||
--gitako-input-bg: #{variables.$input-bg};
|
||||
--gitako-input-contrast-bg: #{variables.$input-contrast-bg};
|
||||
--gitako-input-border: #{variables.$input-border};
|
||||
--gitako-input-shadow: #{variables.$input-shadow};
|
||||
--gitako-input-disabled-bg: #{variables.$input-disabled-bg};
|
||||
--gitako-input-disabled-border: #{variables.$input-disabled-border};
|
||||
--gitako-input-warning-border: #{variables.$input-warning-border};
|
||||
--gitako-input-error-border: #{variables.$input-error-border};
|
||||
--gitako-input-tooltip-success-text: #{variables.$input-tooltip-success-text};
|
||||
--gitako-input-tooltip-success-bg: #{variables.$input-tooltip-success-bg};
|
||||
--gitako-input-tooltip-success-border: #{variables.$input-tooltip-success-border};
|
||||
--gitako-input-tooltip-warning-text: #{variables.$input-tooltip-warning-text};
|
||||
--gitako-input-tooltip-warning-bg: #{variables.$input-tooltip-warning-bg};
|
||||
--gitako-input-tooltip-warning-border: #{variables.$input-tooltip-warning-border};
|
||||
--gitako-input-tooltip-error-text: #{variables.$input-tooltip-error-text};
|
||||
--gitako-input-tooltip-error-bg: #{variables.$input-tooltip-error-bg};
|
||||
--gitako-input-tooltip-error-border: #{variables.$input-tooltip-error-border};
|
||||
--gitako-avatar-bg: #{variables.$avatar-bg};
|
||||
--gitako-avatar-border: #{variables.$avatar-border};
|
||||
--gitako-avatar-stack-fade: #{variables.$avatar-stack-fade};
|
||||
--gitako-avatar-stack-fade-more: #{variables.$avatar-stack-fade-more};
|
||||
--gitako-avatar-child-shadow: #{variables.$avatar-child-shadow};
|
||||
--gitako-toast-text: #{variables.$toast-text};
|
||||
--gitako-toast-bg: #{variables.$toast-bg};
|
||||
--gitako-toast-border: #{variables.$toast-border};
|
||||
--gitako-toast-shadow: #{variables.$toast-shadow};
|
||||
--gitako-toast-icon: #{variables.$toast-icon};
|
||||
--gitako-toast-icon-bg: #{variables.$toast-icon-bg};
|
||||
--gitako-toast-icon-border: #{variables.$toast-icon-border};
|
||||
--gitako-toast-success-text: #{variables.$toast-success-text};
|
||||
--gitako-toast-success-border: #{variables.$toast-success-border};
|
||||
--gitako-toast-success-icon: #{variables.$toast-success-icon};
|
||||
--gitako-toast-success-icon-bg: #{variables.$toast-success-icon-bg};
|
||||
--gitako-toast-success-icon-border: #{variables.$toast-success-icon-border};
|
||||
--gitako-toast-warning-text: #{variables.$toast-warning-text};
|
||||
--gitako-toast-warning-border: #{variables.$toast-warning-border};
|
||||
--gitako-toast-warning-icon: #{variables.$toast-warning-icon};
|
||||
--gitako-toast-warning-icon-bg: #{variables.$toast-warning-icon-bg};
|
||||
--gitako-toast-warning-icon-border: #{variables.$toast-warning-icon-border};
|
||||
--gitako-toast-danger-text: #{variables.$toast-danger-text};
|
||||
--gitako-toast-danger-border: #{variables.$toast-danger-border};
|
||||
--gitako-toast-danger-icon: #{variables.$toast-danger-icon};
|
||||
--gitako-toast-danger-icon-bg: #{variables.$toast-danger-icon-bg};
|
||||
--gitako-toast-danger-icon-border: #{variables.$toast-danger-icon-border};
|
||||
--gitako-toast-loading-text: #{variables.$toast-loading-text};
|
||||
--gitako-toast-loading-border: #{variables.$toast-loading-border};
|
||||
--gitako-toast-loading-icon: #{variables.$toast-loading-icon};
|
||||
--gitako-toast-loading-icon-bg: #{variables.$toast-loading-icon-bg};
|
||||
--gitako-toast-loading-icon-border: #{variables.$toast-loading-icon-border};
|
||||
--gitako-timeline-text: #{variables.$timeline-text};
|
||||
--gitako-timeline-badge-bg: #{variables.$timeline-badge-bg};
|
||||
--gitako-timeline-target-badge-border: #{variables.$timeline-target-badge-border};
|
||||
--gitako-timeline-target-badge-shadow: #{variables.$timeline-target-badge-shadow};
|
||||
--gitako-select-menu-border-secondary: #{variables.$select-menu-border-secondary};
|
||||
--gitako-select-menu-shadow: #{variables.$select-menu-shadow};
|
||||
--gitako-select-menu-backdrop-bg: #{variables.$select-menu-backdrop-bg};
|
||||
--gitako-select-menu-backdrop-border: #{variables.$select-menu-backdrop-border};
|
||||
--gitako-select-menu-tap-highlight: #{variables.$select-menu-tap-highlight};
|
||||
--gitako-select-menu-tap-focus-bg: #{variables.$select-menu-tap-focus-bg};
|
||||
--gitako-box-blue-border: #{variables.$box-blue-border};
|
||||
--gitako-box-row-yellow-bg: #{variables.$box-row-yellow-bg};
|
||||
--gitako-box-row-blue-bg: #{variables.$box-row-blue-bg};
|
||||
--gitako-box-header-blue-bg: #{variables.$box-header-blue-bg};
|
||||
--gitako-box-header-blue-border: #{variables.$box-header-blue-border};
|
||||
--gitako-box-border-info: #{variables.$box-border-info};
|
||||
--gitako-box-bg-info: #{variables.$box-bg-info};
|
||||
--gitako-box-border-warning: #{variables.$box-border-warning};
|
||||
--gitako-box-bg-warning: #{variables.$box-bg-warning};
|
||||
--gitako-branch-name-text: #{variables.$branch-name-text};
|
||||
--gitako-branch-name-icon: #{variables.$branch-name-icon};
|
||||
--gitako-branch-name-bg: #{variables.$branch-name-bg};
|
||||
--gitako-branch-name-link-text: #{variables.$branch-name-link-text};
|
||||
--gitako-branch-name-link-icon: #{variables.$branch-name-link-icon};
|
||||
--gitako-branch-name-link-bg: #{variables.$branch-name-link-bg};
|
||||
--gitako-markdown-code-bg: #{variables.$markdown-code-bg};
|
||||
--gitako-markdown-frame-border: #{variables.$markdown-frame-border};
|
||||
--gitako-markdown-blockquote-border: #{variables.$markdown-blockquote-border};
|
||||
--gitako-markdown-table-border: #{variables.$markdown-table-border};
|
||||
--gitako-markdown-table-tr-border: #{variables.$markdown-table-tr-border};
|
||||
--gitako-menu-heading-text: #{variables.$menu-heading-text};
|
||||
--gitako-menu-border-active: #{variables.$menu-border-active};
|
||||
--gitako-menu-bg-active: #{variables.$menu-bg-active};
|
||||
--gitako-sidenav-selected-bg: #{variables.$sidenav-selected-bg};
|
||||
--gitako-sidenav-border-active: #{variables.$sidenav-border-active};
|
||||
--gitako-header-text: #{variables.$header-text};
|
||||
--gitako-header-bg: #{variables.$header-bg};
|
||||
--gitako-header-logo: #{variables.$header-logo};
|
||||
--gitako-filter-item-bar-bg: #{variables.$filter-item-bar-bg};
|
||||
--gitako-hidden-text-expander-bg: #{variables.$hidden-text-expander-bg};
|
||||
--gitako-hidden-text-expander-bg-hover: #{variables.$hidden-text-expander-bg-hover};
|
||||
--gitako-drag-and-drop-border: #{variables.$drag-and-drop-border};
|
||||
--gitako-upload-enabled-border: #{variables.$upload-enabled-border};
|
||||
--gitako-upload-enabled-border-focused: #{variables.$upload-enabled-border-focused};
|
||||
--gitako-previewable-comment-form-border: #{variables.$previewable-comment-form-border};
|
||||
--gitako-underlinenav-border: #{variables.$underlinenav-border};
|
||||
--gitako-underlinenav-border-hover: #{variables.$underlinenav-border-hover};
|
||||
--gitako-underlinenav-border-active: #{variables.$underlinenav-border-active};
|
||||
--gitako-underlinenav-text: #{variables.$underlinenav-text};
|
||||
--gitako-underlinenav-text-hover: #{variables.$underlinenav-text-hover};
|
||||
--gitako-underlinenav-text-active: #{variables.$underlinenav-text-active};
|
||||
--gitako-underlinenav-icon: #{variables.$underlinenav-icon};
|
||||
--gitako-underlinenav-icon-hover: #{variables.$underlinenav-icon-hover};
|
||||
--gitako-underlinenav-icon-active: #{variables.$underlinenav-icon-active};
|
||||
--gitako-underlinenav-counter-text: #{variables.$underlinenav-counter-text};
|
||||
--gitako-verified-badge-text: #{variables.$verified-badge-text};
|
||||
--gitako-verified-badge-bg: #{variables.$verified-badge-bg};
|
||||
--gitako-verified-badge-border: #{variables.$verified-badge-border};
|
||||
--gitako-social-count-bg: #{variables.$social-count-bg};
|
||||
--gitako-tooltip-text: #{variables.$tooltip-text};
|
||||
--gitako-tooltip-bg: #{variables.$tooltip-bg};
|
||||
--gitako-header-search-bg: #{variables.$header-search-bg};
|
||||
--gitako-header-search-border: #{variables.$header-search-border};
|
||||
--gitako-search-keyword-hl: #{variables.$search-keyword-hl};
|
||||
--gitako-diffstat-neutral-bg: #{variables.$diffstat-neutral-bg};
|
||||
--gitako-diffstat-neutral-border: #{variables.$diffstat-neutral-border};
|
||||
--gitako-diffstat-deletion-bg: #{variables.$diffstat-deletion-bg};
|
||||
--gitako-diffstat-deletion-border: #{variables.$diffstat-deletion-border};
|
||||
--gitako-diffstat-addition-bg: #{variables.$diffstat-addition-bg};
|
||||
--gitako-diffstat-addition-border: #{variables.$diffstat-addition-border};
|
||||
--gitako-files-explorer-icon: #{variables.$files-explorer-icon};
|
||||
--gitako-hl-author-bg: #{variables.$hl-author-bg};
|
||||
--gitako-hl-author-border: #{variables.$hl-author-border};
|
||||
--gitako-logo-subdued: #{variables.$logo-subdued};
|
||||
--gitako-discussion-border: #{variables.$discussion-border};
|
||||
--gitako-discussion-bg-success: #{variables.$discussion-bg-success};
|
||||
--gitako-actions-workflow-table-sticky-bg: #{variables.$actions-workflow-table-sticky-bg};
|
||||
--gitako-repo-language-color-border: #{variables.$repo-language-color-border};
|
||||
--gitako-code-selection-bg: #{variables.$code-selection-bg};
|
||||
--gitako-blob-line-highlight-bg: #{variables.$blob-line-highlight-bg};
|
||||
--gitako-blob-line-highlight-border: #{variables.$blob-line-highlight-border};
|
||||
--gitako-diff-addition-text: #{variables.$diff-addition-text};
|
||||
--gitako-diff-addition-bg: #{variables.$diff-addition-bg};
|
||||
--gitako-diff-addition-border: #{variables.$diff-addition-border};
|
||||
--gitako-diff-deletion-text: #{variables.$diff-deletion-text};
|
||||
--gitako-diff-deletion-bg: #{variables.$diff-deletion-bg};
|
||||
--gitako-diff-deletion-border: #{variables.$diff-deletion-border};
|
||||
--gitako-diff-change-text: #{variables.$diff-change-text};
|
||||
--gitako-diff-change-bg: #{variables.$diff-change-bg};
|
||||
--gitako-diff-change-border: #{variables.$diff-change-border};
|
||||
--gitako-diff-blob-num-text: #{variables.$diff-blob-num-text};
|
||||
--gitako-diff-blob-num-hover-text: #{variables.$diff-blob-num-hover-text};
|
||||
--gitako-diff-blob-addition-num-text: #{variables.$diff-blob-addition-num-text};
|
||||
--gitako-diff-blob-addition-num-hover-text: #{variables.$diff-blob-addition-num-hover-text};
|
||||
--gitako-diff-blob-addition-num-bg: #{variables.$diff-blob-addition-num-bg};
|
||||
--gitako-diff-blob-addition-line-bg: #{variables.$diff-blob-addition-line-bg};
|
||||
--gitako-diff-blob-addition-word-bg: #{variables.$diff-blob-addition-word-bg};
|
||||
--gitako-diff-blob-deletion-num-text: #{variables.$diff-blob-deletion-num-text};
|
||||
--gitako-diff-blob-deletion-num-hover-text: #{variables.$diff-blob-deletion-num-hover-text};
|
||||
--gitako-diff-blob-deletion-num-bg: #{variables.$diff-blob-deletion-num-bg};
|
||||
--gitako-diff-blob-deletion-line-bg: #{variables.$diff-blob-deletion-line-bg};
|
||||
--gitako-diff-blob-deletion-word-bg: #{variables.$diff-blob-deletion-word-bg};
|
||||
--gitako-diff-blob-hunk-text: #{variables.$diff-blob-hunk-text};
|
||||
--gitako-diff-blob-hunk-num-bg: #{variables.$diff-blob-hunk-num-bg};
|
||||
--gitako-diff-blob-hunk-line-bg: #{variables.$diff-blob-hunk-line-bg};
|
||||
--gitako-diff-blob-empty-block-bg: #{variables.$diff-blob-empty-block-bg};
|
||||
--gitako-diff-blob-selected-line-highlight-bg: #{variables.$diff-blob-selected-line-highlight-bg};
|
||||
--gitako-diff-blob-selected-line-highlight-border: #{variables.$diff-blob-selected-line-highlight-border};
|
||||
--gitako-diff-blob-selected-line-highlight-mix-blend-mode: #{variables.$diff-blob-selected-line-highlight-mix-blend-mode};
|
||||
--gitako-diff-blob-expander-icon: #{variables.$diff-blob-expander-icon};
|
||||
--gitako-diff-blob-expander-hover-icon: #{variables.$diff-blob-expander-hover-icon};
|
||||
--gitako-diff-blob-expander-hover-bg: #{variables.$diff-blob-expander-hover-bg};
|
||||
--gitako-diff-blob-comment-button-icon: #{variables.$diff-blob-comment-button-icon};
|
||||
--gitako-diff-blob-comment-button-bg: #{variables.$diff-blob-comment-button-bg};
|
||||
--gitako-diff-blob-comment-button-gradient-bg: #{variables.$diff-blob-comment-button-gradient-bg};
|
||||
--gitako-global-nav-logo: #{variables.$global-nav-logo};
|
||||
--gitako-global-nav-bg: #{variables.$global-nav-bg};
|
||||
--gitako-global-nav-text: #{variables.$global-nav-text};
|
||||
--gitako-global-nav-icon: #{variables.$global-nav-icon};
|
||||
--gitako-global-nav-input-bg: #{variables.$global-nav-input-bg};
|
||||
--gitako-global-nav-input-border: #{variables.$global-nav-input-border};
|
||||
--gitako-global-nav-input-icon: #{variables.$global-nav-input-icon};
|
||||
--gitako-global-nav-input-placeholder: #{variables.$global-nav-input-placeholder};
|
||||
--gitako-calendar-graph-day-bg: #{variables.$calendar-graph-day-bg};
|
||||
--gitako-calendar-graph-day-border: #{variables.$calendar-graph-day-border};
|
||||
--gitako-calendar-graph-day-l1-bg: #{variables.$calendar-graph-day-l1-bg};
|
||||
--gitako-calendar-graph-day-l2-bg: #{variables.$calendar-graph-day-l2-bg};
|
||||
--gitako-calendar-graph-day-l3-bg: #{variables.$calendar-graph-day-l3-bg};
|
||||
--gitako-calendar-graph-day-l4-bg: #{variables.$calendar-graph-day-l4-bg};
|
||||
--gitako-calendar-graph-day-l4-border: #{variables.$calendar-graph-day-l4-border};
|
||||
--gitako-calendar-graph-day-l3-border: #{variables.$calendar-graph-day-l3-border};
|
||||
--gitako-calendar-graph-day-l2-border: #{variables.$calendar-graph-day-l2-border};
|
||||
--gitako-calendar-graph-day-l1-border: #{variables.$calendar-graph-day-l1-border};
|
||||
--gitako-footer-invertocat-octicon: #{variables.$footer-invertocat-octicon};
|
||||
--gitako-footer-invertocat-octicon-hover: #{variables.$footer-invertocat-octicon-hover};
|
||||
--gitako-pr-state-draft-text: #{variables.$pr-state-draft-text};
|
||||
--gitako-pr-state-draft-bg: #{variables.$pr-state-draft-bg};
|
||||
--gitako-pr-state-draft-border: #{variables.$pr-state-draft-border};
|
||||
--gitako-pr-state-open-text: #{variables.$pr-state-open-text};
|
||||
--gitako-pr-state-open-bg: #{variables.$pr-state-open-bg};
|
||||
--gitako-pr-state-open-border: #{variables.$pr-state-open-border};
|
||||
--gitako-pr-state-merged-text: #{variables.$pr-state-merged-text};
|
||||
--gitako-pr-state-merged-bg: #{variables.$pr-state-merged-bg};
|
||||
--gitako-pr-state-merged-border: #{variables.$pr-state-merged-border};
|
||||
--gitako-pr-state-closed-text: #{variables.$pr-state-closed-text};
|
||||
--gitako-pr-state-closed-bg: #{variables.$pr-state-closed-bg};
|
||||
--gitako-pr-state-closed-border: #{variables.$pr-state-closed-border};
|
||||
--gitako-topic-tag-text: #{variables.$topic-tag-text};
|
||||
--gitako-topic-tag-bg: #{variables.$topic-tag-bg};
|
||||
--gitako-topic-tag-hover-bg: #{variables.$topic-tag-hover-bg};
|
||||
--gitako-topic-tag-active-bg: #{variables.$topic-tag-active-bg};
|
||||
--gitako-merge-box-success-icon-bg: #{variables.$merge-box-success-icon-bg};
|
||||
--gitako-merge-box-success-icon-text: #{variables.$merge-box-success-icon-text};
|
||||
--gitako-merge-box-success-icon-border: #{variables.$merge-box-success-icon-border};
|
||||
--gitako-merge-box-success-indicator-bg: #{variables.$merge-box-success-indicator-bg};
|
||||
--gitako-merge-box-success-indicator-border: #{variables.$merge-box-success-indicator-border};
|
||||
--gitako-merge-box-merged-icon-bg: #{variables.$merge-box-merged-icon-bg};
|
||||
--gitako-merge-box-merged-icon-text: #{variables.$merge-box-merged-icon-text};
|
||||
--gitako-merge-box-merged-icon-border: #{variables.$merge-box-merged-icon-border};
|
||||
--gitako-merge-box-merged-box-border: #{variables.$merge-box-merged-box-border};
|
||||
--gitako-merge-box-neutral-icon-bg: #{variables.$merge-box-neutral-icon-bg};
|
||||
--gitako-merge-box-neutral-icon-text: #{variables.$merge-box-neutral-icon-text};
|
||||
--gitako-merge-box-neutral-icon-border: #{variables.$merge-box-neutral-icon-border};
|
||||
--gitako-merge-box-neutral-indicator-bg: #{variables.$merge-box-neutral-indicator-bg};
|
||||
--gitako-merge-box-neutral-indicator-border: #{variables.$merge-box-neutral-indicator-border};
|
||||
--gitako-merge-box-warning-icon-bg: #{variables.$merge-box-warning-icon-bg};
|
||||
--gitako-merge-box-warning-icon-text: #{variables.$merge-box-warning-icon-text};
|
||||
--gitako-merge-box-warning-icon-border: #{variables.$merge-box-warning-icon-border};
|
||||
--gitako-merge-box-warning-box-border: #{variables.$merge-box-warning-box-border};
|
||||
--gitako-merge-box-warning-merge-highlight: #{variables.$merge-box-warning-merge-highlight};
|
||||
--gitako-merge-box-error-icon-bg: #{variables.$merge-box-error-icon-bg};
|
||||
--gitako-merge-box-error-icon-text: #{variables.$merge-box-error-icon-text};
|
||||
--gitako-merge-box-error-icon-border: #{variables.$merge-box-error-icon-border};
|
||||
--gitako-merge-box-error-indicator-bg: #{variables.$merge-box-error-indicator-bg};
|
||||
--gitako-merge-box-error-indicator-border: #{variables.$merge-box-error-indicator-border};
|
||||
--gitako-project-card-bg: #{variables.$project-card-bg};
|
||||
--gitako-project-header-bg: #{variables.$project-header-bg};
|
||||
--gitako-project-sidebar-bg: #{variables.$project-sidebar-bg};
|
||||
--gitako-project-gradient-in: #{variables.$project-gradient-in};
|
||||
--gitako-project-gradient-out: #{variables.$project-gradient-out};
|
||||
--gitako-marketing-icon-primary: #{variables.$marketing-icon-primary};
|
||||
--gitako-marketing-icon-secondary: #{variables.$marketing-icon-secondary};
|
||||
--gitako-prettylights-syntax-comment: #{variables.$prettylights-syntax-comment};
|
||||
--gitako-prettylights-syntax-constant: #{variables.$prettylights-syntax-constant};
|
||||
--gitako-prettylights-syntax-entity: #{variables.$prettylights-syntax-entity};
|
||||
--gitako-prettylights-syntax-storage-modifier-import: #{variables.$prettylights-syntax-storage-modifier-import};
|
||||
--gitako-prettylights-syntax-entity-tag: #{variables.$prettylights-syntax-entity-tag};
|
||||
--gitako-prettylights-syntax-keyword: #{variables.$prettylights-syntax-keyword};
|
||||
--gitako-prettylights-syntax-string: #{variables.$prettylights-syntax-string};
|
||||
--gitako-prettylights-syntax-variable: #{variables.$prettylights-syntax-variable};
|
||||
--gitako-prettylights-syntax-brackethighlighter-unmatched: #{variables.$prettylights-syntax-brackethighlighter-unmatched};
|
||||
--gitako-prettylights-syntax-invalid-illegal-text: #{variables.$prettylights-syntax-invalid-illegal-text};
|
||||
--gitako-prettylights-syntax-invalid-illegal-bg: #{variables.$prettylights-syntax-invalid-illegal-bg};
|
||||
--gitako-prettylights-syntax-carriage-return-text: #{variables.$prettylights-syntax-carriage-return-text};
|
||||
--gitako-prettylights-syntax-carriage-return-bg: #{variables.$prettylights-syntax-carriage-return-bg};
|
||||
--gitako-prettylights-syntax-string-regexp: #{variables.$prettylights-syntax-string-regexp};
|
||||
--gitako-prettylights-syntax-markup-list: #{variables.$prettylights-syntax-markup-list};
|
||||
--gitako-prettylights-syntax-markup-heading: #{variables.$prettylights-syntax-markup-heading};
|
||||
--gitako-prettylights-syntax-markup-italic: #{variables.$prettylights-syntax-markup-italic};
|
||||
--gitako-prettylights-syntax-markup-bold: #{variables.$prettylights-syntax-markup-bold};
|
||||
--gitako-prettylights-syntax-markup-deleted-text: #{variables.$prettylights-syntax-markup-deleted-text};
|
||||
--gitako-prettylights-syntax-markup-deleted-bg: #{variables.$prettylights-syntax-markup-deleted-bg};
|
||||
--gitako-prettylights-syntax-markup-inserted-text: #{variables.$prettylights-syntax-markup-inserted-text};
|
||||
--gitako-prettylights-syntax-markup-inserted-bg: #{variables.$prettylights-syntax-markup-inserted-bg};
|
||||
--gitako-prettylights-syntax-markup-changed-text: #{variables.$prettylights-syntax-markup-changed-text};
|
||||
--gitako-prettylights-syntax-markup-changed-bg: #{variables.$prettylights-syntax-markup-changed-bg};
|
||||
--gitako-prettylights-syntax-markup-ignored-text: #{variables.$prettylights-syntax-markup-ignored-text};
|
||||
--gitako-prettylights-syntax-markup-ignored-bg: #{variables.$prettylights-syntax-markup-ignored-bg};
|
||||
--gitako-prettylights-syntax-meta-diff-range: #{variables.$prettylights-syntax-meta-diff-range};
|
||||
--gitako-prettylights-syntax-brackethighlighter-angle: #{variables.$prettylights-syntax-brackethighlighter-angle};
|
||||
--gitako-prettylights-syntax-sublimelinter-gutter-mark: #{variables.$prettylights-syntax-sublimelinter-gutter-mark};
|
||||
--gitako-prettylights-syntax-constant-other-reference-link: #{variables.$prettylights-syntax-constant-other-reference-link};
|
||||
--gitako-codemirror-text: #{variables.$codemirror-text};
|
||||
--gitako-codemirror-bg: #{variables.$codemirror-bg};
|
||||
--gitako-codemirror-gutters-bg: #{variables.$codemirror-gutters-bg};
|
||||
--gitako-codemirror-guttermarker-text: #{variables.$codemirror-guttermarker-text};
|
||||
--gitako-codemirror-guttermarker-subtle-text: #{variables.$codemirror-guttermarker-subtle-text};
|
||||
--gitako-codemirror-linenumber-text: #{variables.$codemirror-linenumber-text};
|
||||
--gitako-codemirror-cursor: #{variables.$codemirror-cursor};
|
||||
--gitako-codemirror-selection-bg: #{variables.$codemirror-selection-bg};
|
||||
--gitako-codemirror-activeline-bg: #{variables.$codemirror-activeline-bg};
|
||||
--gitako-codemirror-matchingbracket-text: #{variables.$codemirror-matchingbracket-text};
|
||||
--gitako-codemirror-lines-bg: #{variables.$codemirror-lines-bg};
|
||||
--gitako-codemirror-syntax-comment: #{variables.$codemirror-syntax-comment};
|
||||
--gitako-codemirror-syntax-constant: #{variables.$codemirror-syntax-constant};
|
||||
--gitako-codemirror-syntax-entity: #{variables.$codemirror-syntax-entity};
|
||||
--gitako-codemirror-syntax-keyword: #{variables.$codemirror-syntax-keyword};
|
||||
--gitako-codemirror-syntax-storage: #{variables.$codemirror-syntax-storage};
|
||||
--gitako-codemirror-syntax-string: #{variables.$codemirror-syntax-string};
|
||||
--gitako-codemirror-syntax-support: #{variables.$codemirror-syntax-support};
|
||||
--gitako-codemirror-syntax-variable: #{variables.$codemirror-syntax-variable};
|
||||
--gitako-ansi-black: #{variables.$ansi-black};
|
||||
--gitako-ansi-black-bright: #{variables.$ansi-black-bright};
|
||||
--gitako-ansi-white: #{variables.$ansi-white};
|
||||
--gitako-ansi-white-bright: #{variables.$ansi-white-bright};
|
||||
--gitako-ansi-gray: #{variables.$ansi-gray};
|
||||
--gitako-ansi-red: #{variables.$ansi-red};
|
||||
--gitako-ansi-red-bright: #{variables.$ansi-red-bright};
|
||||
--gitako-ansi-green: #{variables.$ansi-green};
|
||||
--gitako-ansi-green-bright: #{variables.$ansi-green-bright};
|
||||
--gitako-ansi-yellow: #{variables.$ansi-yellow};
|
||||
--gitako-ansi-yellow-bright: #{variables.$ansi-yellow-bright};
|
||||
--gitako-ansi-blue: #{variables.$ansi-blue};
|
||||
--gitako-ansi-blue-bright: #{variables.$ansi-blue-bright};
|
||||
--gitako-ansi-magenta: #{variables.$ansi-magenta};
|
||||
--gitako-ansi-magenta-bright: #{variables.$ansi-magenta-bright};
|
||||
--gitako-ansi-cyan: #{variables.$ansi-cyan};
|
||||
--gitako-ansi-cyan-bright: #{variables.$ansi-cyan-bright};
|
||||
}
|
||||
|
||||
// How to merge the selectors?
|
||||
// Is it possible to not have two copies of dark theme variables?
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root[data-color-mode='auto'] {
|
||||
@include assign();
|
||||
}
|
||||
}
|
||||
:root[data-color-mode='dark'] {
|
||||
@include assign();
|
||||
}
|
||||
File diff suppressed because it is too large
Load diff
680
src/styles/darkDimmed/variables.scss
Normal file
680
src/styles/darkDimmed/variables.scss
Normal file
|
|
@ -0,0 +1,680 @@
|
|||
$variables: (
|
||||
'auto-black': '#cdd9e5',
|
||||
'auto-white': '#1c2128',
|
||||
'auto-gray-0': '#22272e',
|
||||
'auto-gray-1': '#2d333b',
|
||||
'auto-gray-2': '#373e47',
|
||||
'auto-gray-3': '#444c56',
|
||||
'auto-gray-4': '#545d68',
|
||||
'auto-gray-5': '#636e7b',
|
||||
'auto-gray-6': '#768390',
|
||||
'auto-gray-7': '#909dab',
|
||||
'auto-gray-8': '#adbac7',
|
||||
'auto-gray-9': '#cdd9e5',
|
||||
'auto-blue-0': '#0f2d5c',
|
||||
'auto-blue-1': '#143d79',
|
||||
'auto-blue-2': '#1b4b91',
|
||||
'auto-blue-3': '#255ab2',
|
||||
'auto-blue-4': '#316dca',
|
||||
'auto-blue-5': '#4184e4',
|
||||
'auto-blue-6': '#539bf5',
|
||||
'auto-blue-7': '#6cb6ff',
|
||||
'auto-blue-8': '#96d0ff',
|
||||
'auto-blue-9': '#c6e6ff',
|
||||
'auto-green-0': '#113417',
|
||||
'auto-green-1': '#1b4721',
|
||||
'auto-green-2': '#245829',
|
||||
'auto-green-3': '#2b6a30',
|
||||
'auto-green-4': '#347d39',
|
||||
'auto-green-5': '#46954a',
|
||||
'auto-green-6': '#57ab5a',
|
||||
'auto-green-7': '#6bc46d',
|
||||
'auto-green-8': '#8ddb8c',
|
||||
'auto-green-9': '#b4f1b4',
|
||||
'auto-yellow-0': '#452700',
|
||||
'auto-yellow-1': '#593600',
|
||||
'auto-yellow-2': '#6c4400',
|
||||
'auto-yellow-3': '#805400',
|
||||
'auto-yellow-4': '#966600',
|
||||
'auto-yellow-5': '#ae7c14',
|
||||
'auto-yellow-6': '#c69026',
|
||||
'auto-yellow-7': '#daaa3f',
|
||||
'auto-yellow-8': '#eac55f',
|
||||
'auto-yellow-9': '#fbe090',
|
||||
'auto-orange-0': '#4d210c',
|
||||
'auto-orange-1': '#682d0f',
|
||||
'auto-orange-2': '#7f3913',
|
||||
'auto-orange-3': '#94471b',
|
||||
'auto-orange-4': '#ae5622',
|
||||
'auto-orange-5': '#cc6b2c',
|
||||
'auto-orange-6': '#e0823d',
|
||||
'auto-orange-7': '#f69d50',
|
||||
'auto-orange-8': '#ffbc6f',
|
||||
'auto-orange-9': '#ffddb0',
|
||||
'auto-red-0': '#78191b',
|
||||
'auto-red-1': '#78191b',
|
||||
'auto-red-2': '#922323',
|
||||
'auto-red-3': '#ad2e2c',
|
||||
'auto-red-4': '#c93c37',
|
||||
'auto-red-5': '#e5534b',
|
||||
'auto-red-6': '#f47067',
|
||||
'auto-red-7': '#ff938a',
|
||||
'auto-red-8': '#ffb8b0',
|
||||
'auto-red-9': '#ffd8d3',
|
||||
'auto-purple-0': '#352160',
|
||||
'auto-purple-1': '#472c82',
|
||||
'auto-purple-2': '#5936a2',
|
||||
'auto-purple-3': '#6b44bc',
|
||||
'auto-purple-4': '#8256d0',
|
||||
'auto-purple-5': '#986ee2',
|
||||
'auto-purple-6': '#b083f0',
|
||||
'auto-purple-7': '#dcbdfb',
|
||||
'auto-purple-8': '#dcbdfb',
|
||||
'auto-purple-9': '#eedcff',
|
||||
'auto-pink-0': '#551639',
|
||||
'auto-pink-1': '#69264a',
|
||||
'auto-pink-2': '#7e325a',
|
||||
'auto-pink-3': '#983b6e',
|
||||
'auto-pink-4': '#ae4c82',
|
||||
'auto-pink-5': '#c96198',
|
||||
'auto-pink-6': '#e275ad',
|
||||
'auto-pink-7': '#fc8dc7',
|
||||
'auto-pink-8': '#ffb3d8',
|
||||
'auto-pink-9': '#ffd7eb',
|
||||
'text-primary': '#adbac7',
|
||||
'text-secondary': '#768390',
|
||||
'text-tertiary': '#768390',
|
||||
'text-placeholder': '#545d68',
|
||||
'text-disabled': '#545d68',
|
||||
'text-inverse': '#22272e',
|
||||
'text-link': '#539bf5',
|
||||
'text-danger': '#e5534b',
|
||||
'text-success': '#6bc46d',
|
||||
'text-warning': '#daaa3f',
|
||||
'text-white': '#cdd9e5',
|
||||
'icon-primary': '#adbac7',
|
||||
'icon-secondary': '#636e7b',
|
||||
'icon-tertiary': '#545d68',
|
||||
'icon-info': '#6cb6ff',
|
||||
'icon-danger': '#e5534b',
|
||||
'icon-success': '#6bc46d',
|
||||
'icon-warning': '#daaa3f',
|
||||
'border-primary': '#444c56',
|
||||
'border-secondary': '#373e47',
|
||||
'border-tertiary': '#636e7b',
|
||||
'border-overlay': '#444c56',
|
||||
'border-inverse': '#cdd9e5',
|
||||
'border-info': '#4184e466',
|
||||
'border-danger': '#e5534b66',
|
||||
'border-success': '#57ab5a66',
|
||||
'border-warning': '#ae7c1466',
|
||||
'bg-canvas': '#22272e',
|
||||
'bg-canvas-mobile': '#1c2128',
|
||||
'bg-canvas-inverse': '#cdd9e5',
|
||||
'bg-canvas-inset': '#1e2228',
|
||||
'bg-primary': '#22272e',
|
||||
'bg-secondary': '#22272e',
|
||||
'bg-tertiary': '#2d333b',
|
||||
'bg-overlay': '#373e47',
|
||||
'bg-backdrop': '#1c2128cc',
|
||||
'bg-info': '#4184e41a',
|
||||
'bg-info-inverse': '#4184e4',
|
||||
'bg-danger': '#e5534b1a',
|
||||
'bg-danger-inverse': '#c93c37',
|
||||
'bg-success': '#46954a1a',
|
||||
'bg-success-inverse': '#46954a',
|
||||
'bg-warning': '#ae7c141a',
|
||||
'bg-warning-inverse': '#ae7c14',
|
||||
'shadow-small': '0 0 #0000',
|
||||
'shadow-medium': '0 3px 6px #1c2128',
|
||||
'shadow-large': '0 8px 24px #1c2128',
|
||||
'shadow-extra-large': '0 12px 48px #1c2128',
|
||||
'shadow-highlight': '0 0 #0000',
|
||||
'shadow-inset': '0 0 #0000',
|
||||
'state-hover-primary-bg': '#316dca',
|
||||
'state-hover-primary-border': '#4184e4',
|
||||
'state-hover-primary-text': '#cdd9e5',
|
||||
'state-hover-primary-icon': '#cdd9e5',
|
||||
'state-hover-secondary-bg': '#2d333b',
|
||||
'state-hover-secondary-border': '#2d333b',
|
||||
'state-selected-primary-bg': '#316dca',
|
||||
'state-selected-primary-border': '#4184e4',
|
||||
'state-selected-primary-text': '#cdd9e5',
|
||||
'state-selected-primary-icon': '#cdd9e5',
|
||||
'state-focus-border': '#4184e4',
|
||||
'state-focus-shadow': '0 0 0 3px #143d79',
|
||||
'fade-fg-10': '#cdd9e51a',
|
||||
'fade-fg-15': '#cdd9e526',
|
||||
'fade-fg-30': '#cdd9e54d',
|
||||
'fade-fg-50': '#cdd9e580',
|
||||
'fade-fg-70': '#cdd9e5b3',
|
||||
'fade-fg-85': '#cdd9e5d9',
|
||||
'fade-black-10': '#1c21281a',
|
||||
'fade-black-15': '#1c212826',
|
||||
'fade-black-30': '#1c21284d',
|
||||
'fade-black-50': '#1c212880',
|
||||
'fade-black-70': '#1c2128b3',
|
||||
'fade-black-85': '#1c2128d9',
|
||||
'fade-white-10': '#cdd9e51a',
|
||||
'fade-white-15': '#cdd9e526',
|
||||
'fade-white-30': '#cdd9e54d',
|
||||
'fade-white-50': '#cdd9e580',
|
||||
'fade-white-70': '#cdd9e5b3',
|
||||
'fade-white-85': '#cdd9e5d9',
|
||||
'alert-info-text': '#6cb6ff',
|
||||
'alert-info-icon': '#6cb6ff',
|
||||
'alert-info-bg': '#4184e41a',
|
||||
'alert-info-border': '#4184e466',
|
||||
'alert-warn-text': '#daaa3f',
|
||||
'alert-warn-icon': '#daaa3f',
|
||||
'alert-warn-bg': '#ae7c141a',
|
||||
'alert-warn-border': '#ae7c1466',
|
||||
'alert-error-text': '#f47067',
|
||||
'alert-error-icon': '#f47067',
|
||||
'alert-error-bg': '#e5534b1a',
|
||||
'alert-error-border': '#e5534b66',
|
||||
'alert-success-text': '#6bc46d',
|
||||
'alert-success-icon': '#6bc46d',
|
||||
'alert-success-bg': '#46954a1a',
|
||||
'alert-success-border': '#46954a66',
|
||||
'autocomplete-shadow': '0 16px 32px #1c2128d9',
|
||||
'autocomplete-row-border': '#444c56',
|
||||
'blankslate-icon': '#5f6a76',
|
||||
'btn-text': '#adbac7',
|
||||
'btn-bg': '#373e47',
|
||||
'btn-border': '#444c56',
|
||||
'btn-shadow': '0 0 #0000',
|
||||
'btn-inset-shadow': '0 0 #0000',
|
||||
'btn-hover-bg': '#444c56',
|
||||
'btn-hover-border': '#768390',
|
||||
'btn-selected-bg': '#2d333b',
|
||||
'btn-focus-bg': '#373e47',
|
||||
'btn-focus-border': '#768390',
|
||||
'btn-focus-shadow': '0 0 0 3px #7683904d',
|
||||
'btn-shadow-active': 'inset 0 0.15em 0.3em #1c212826',
|
||||
'btn-shadow-input-focus': '0 0 0 0.2em #316dca4d',
|
||||
'btn-primary-text': '#fff',
|
||||
'btn-primary-bg': '#347d39',
|
||||
'btn-primary-border': '#46954a',
|
||||
'btn-primary-shadow': '0 0 #0000',
|
||||
'btn-primary-inset-shadow': '0 0 #0000',
|
||||
'btn-primary-hover-bg': '#46954a',
|
||||
'btn-primary-hover-border': '#57ab5a',
|
||||
'btn-primary-selected-bg': '#347d39',
|
||||
'btn-primary-selected-shadow': '0 0 #0000',
|
||||
'btn-primary-disabled-text': '#cdd9e580',
|
||||
'btn-primary-disabled-bg': '#347d3999',
|
||||
'btn-primary-disabled-border': '#0000',
|
||||
'btn-primary-focus-bg': '#347d39',
|
||||
'btn-primary-focus-border': '#57ab5a',
|
||||
'btn-primary-focus-shadow': '0 0 0 3px #2ea44f66',
|
||||
'btn-primary-icon': '#cdd9e5',
|
||||
'btn-primary-counter-bg': '#cdd9e533',
|
||||
'btn-outline-text': '#539bf5',
|
||||
'btn-outline-hover-text': '#539bf5',
|
||||
'btn-outline-hover-bg': '#444c56',
|
||||
'btn-outline-hover-border': '#539bf5',
|
||||
'btn-outline-hover-shadow': '0 1px 0 #1c21281a',
|
||||
'btn-outline-hover-inset-shadow': 'inset 0 1px 0 #cdd9e508',
|
||||
'btn-outline-hover-counter-bg': '#cdd9e533',
|
||||
'btn-outline-selected-text': '#cdd9e5',
|
||||
'btn-outline-selected-bg': '#1b4b91',
|
||||
'btn-outline-selected-border': '#cdd9e51a',
|
||||
'btn-outline-selected-shadow': '0 0 #0000',
|
||||
'btn-outline-disabled-text': '#539bf580',
|
||||
'btn-outline-disabled-bg': '#22272e',
|
||||
'btn-outline-disabled-counter-bg': '#316dca0d',
|
||||
'btn-outline-focus-border': '#539bf5',
|
||||
'btn-outline-focus-shadow': '0 0 0 3px #255ab266',
|
||||
'btn-outline-counter-bg': '#316dca1a',
|
||||
'btn-danger-text': '#e5534b',
|
||||
'btn-danger-hover-text': '#fff',
|
||||
'btn-danger-hover-bg': '#c93c37',
|
||||
'btn-danger-hover-border': '#e5534b',
|
||||
'btn-danger-hover-shadow': '0 0 #0000',
|
||||
'btn-danger-hover-inset-shadow': '0 0 #0000',
|
||||
'btn-danger-hover-counter-bg': '#fff3',
|
||||
'btn-danger-selected-text': '#fff',
|
||||
'btn-danger-selected-bg': '#ad2e2c',
|
||||
'btn-danger-selected-border': '#cdd9e51a',
|
||||
'btn-danger-selected-shadow': '0 0 #0000',
|
||||
'btn-danger-disabled-text': '#e5534b80',
|
||||
'btn-danger-disabled-bg': '#22272e',
|
||||
'btn-danger-disabled-counter-bg': '#c93c370d',
|
||||
'btn-danger-focus-border': '#e5534b',
|
||||
'btn-danger-focus-shadow': '0 0 0 3px #ad2e2c66',
|
||||
'btn-danger-counter-bg': '#c93c371a',
|
||||
'btn-danger-icon': '#e5534b',
|
||||
'btn-danger-hover-icon': '#cdd9e5',
|
||||
'btn-counter-bg': '#444c56',
|
||||
'counter-text': '#adbac7',
|
||||
'counter-bg': '#444c56',
|
||||
'counter-primary-text': '#adbac7',
|
||||
'counter-primary-bg': '#636e7b',
|
||||
'counter-secondary-text': '#768390',
|
||||
'counter-secondary-bg': '#76839033',
|
||||
'dropdown-shadow': '0 16px 32px #1c2128d9',
|
||||
'label-border': '#444c56',
|
||||
'label-primary-text': '#909dab',
|
||||
'label-primary-border': '#636e7b',
|
||||
'label-secondary-text': '#768390',
|
||||
'label-secondary-border': '#444c56',
|
||||
'label-info-text': '#4184e4',
|
||||
'label-info-border': '#4184e466',
|
||||
'label-success-text': '#57ab5a',
|
||||
'label-success-border': '#46954a66',
|
||||
'label-warning-text': '#daaa3f',
|
||||
'label-warning-border': '#f2d35b66',
|
||||
'label-danger-text': '#e5534b',
|
||||
'label-danger-border': '#e5534b66',
|
||||
'label-orange-text': '#cc6b2c',
|
||||
'label-orange-border': '#cc6b2c66',
|
||||
'input-bg': '#22272e',
|
||||
'input-contrast-bg': '#1c212880',
|
||||
'input-border': '#373e47',
|
||||
'input-shadow': '0 0 #0000',
|
||||
'input-disabled-bg': '#2d333b',
|
||||
'input-disabled-border': '#444c56',
|
||||
'input-warning-border': '#c69026',
|
||||
'input-error-border': '#e5534b',
|
||||
'input-tooltip-success-text': '#6bc46d',
|
||||
'input-tooltip-success-bg': '#263231',
|
||||
'input-tooltip-success-border': '#335a3b',
|
||||
'input-tooltip-warning-text': '#daaa3f',
|
||||
'input-tooltip-warning-bg': '#30302b',
|
||||
'input-tooltip-warning-border': '#624e22',
|
||||
'input-tooltip-error-text': '#f47067',
|
||||
'input-tooltip-error-bg': '#362b31',
|
||||
'input-tooltip-error-border': '#7c3b3b',
|
||||
'avatar-bg': '#cdd9e51a',
|
||||
'avatar-border': '#cdd9e51a',
|
||||
'avatar-stack-fade': '#444c56',
|
||||
'avatar-stack-fade-more': '#373e47',
|
||||
'avatar-child-shadow': '-2px -2px 0 #22272e',
|
||||
'toast-text': '#adbac7',
|
||||
'toast-bg': '#444c56',
|
||||
'toast-border': '#636e7b',
|
||||
'toast-shadow': '0 8px 24px #1c2128',
|
||||
'toast-icon': '#cdd9e5',
|
||||
'toast-icon-bg': '#316dca',
|
||||
'toast-icon-border': '#4184e4',
|
||||
'toast-success-text': '#adbac7',
|
||||
'toast-success-border': '#636e7b',
|
||||
'toast-success-icon': '#cdd9e5',
|
||||
'toast-success-icon-bg': '#46954a',
|
||||
'toast-success-icon-border': '#57ab5a',
|
||||
'toast-warning-text': '#adbac7',
|
||||
'toast-warning-border': '#636e7b',
|
||||
'toast-warning-icon': '#cdd9e5',
|
||||
'toast-warning-icon-bg': '#ae7c14',
|
||||
'toast-warning-icon-border': '#c69026',
|
||||
'toast-danger-text': '#adbac7',
|
||||
'toast-danger-border': '#636e7b',
|
||||
'toast-danger-icon': '#cdd9e5',
|
||||
'toast-danger-icon-bg': '#c93c37',
|
||||
'toast-danger-icon-border': '#e5534b',
|
||||
'toast-loading-text': '#adbac7',
|
||||
'toast-loading-border': '#636e7b',
|
||||
'toast-loading-icon': '#cdd9e5',
|
||||
'toast-loading-icon-bg': '#636e7b',
|
||||
'toast-loading-icon-border': '#768390',
|
||||
'timeline-text': '#909dab',
|
||||
'timeline-badge-bg': '#22272e',
|
||||
'timeline-badge-success-border': '#46954a',
|
||||
'timeline-target-badge-border': '#316dca',
|
||||
'timeline-target-badge-shadow': '#1b4b91',
|
||||
'select-menu-border-secondary': '#444c56',
|
||||
'select-menu-shadow': '0 0 18px #1c212866',
|
||||
'select-menu-backdrop-bg': '#1c212880',
|
||||
'select-menu-backdrop-border': '#545d68',
|
||||
'select-menu-tap-highlight': '#444c5680',
|
||||
'select-menu-tap-focus-bg': '#143d79',
|
||||
'box-blue-border': '#1b4b91',
|
||||
'box-row-yellow-bg': '#ebc4401a',
|
||||
'box-row-blue-bg': '#6cb6ff1a',
|
||||
'box-header-blue-bg': '#22272e',
|
||||
'box-header-blue-border': '#444c56',
|
||||
'box-border-info': '#4184e466',
|
||||
'box-bg-info': '#4184e41a',
|
||||
'box-border-warning': '#ae7c1466',
|
||||
'box-bg-warning': '#ae7c141a',
|
||||
'branch-name-text': '#adbac7',
|
||||
'branch-name-icon': '#909dab',
|
||||
'branch-name-bg': '#539bf51a',
|
||||
'branch-name-link-text': '#539bf5',
|
||||
'branch-name-link-icon': '#539bf5',
|
||||
'branch-name-link-bg': '#539bf51a',
|
||||
'markdown-code-bg': '#cdd9e526',
|
||||
'markdown-frame-border': '#4f5964',
|
||||
'markdown-blockquote-border': '#4f5964',
|
||||
'markdown-table-border': '#4f5964',
|
||||
'markdown-table-tr-border': '#3b424b',
|
||||
'menu-heading-text': '#768390',
|
||||
'menu-border-active': '#f78166',
|
||||
'menu-bg-active': '#2d333b',
|
||||
'sidenav-selected-bg': '#373e47',
|
||||
'sidenav-border-active': '#f78166',
|
||||
'header-text': '#cdd9e5b3',
|
||||
'header-bg': '#2d333b',
|
||||
'header-logo': '#cdd9e5',
|
||||
'filter-item-bar-bg': '#292e35',
|
||||
'hidden-text-expander-bg': '#373e47',
|
||||
'hidden-text-expander-bg-hover': '#444c56',
|
||||
'drag-and-drop-border': '#393f48',
|
||||
'upload-enabled-border': '#4f5964',
|
||||
'upload-enabled-border-focused': '#4f84d4',
|
||||
'previewable-comment-form-border': '#393f48',
|
||||
'underlinenav-border': '#444c5600',
|
||||
'underlinenav-border-hover': '#444c56',
|
||||
'underlinenav-border-active': '#f78166',
|
||||
'underlinenav-text': '#768390',
|
||||
'underlinenav-text-hover': '#adbac7',
|
||||
'underlinenav-text-active': '#adbac7',
|
||||
'underlinenav-icon': '#636e7b',
|
||||
'underlinenav-icon-hover': '#adbac7',
|
||||
'underlinenav-icon-active': '#adbac7',
|
||||
'underlinenav-counter-text': '#768390',
|
||||
'underlinenav-counter-bg': '#76839033',
|
||||
'verified-badge-text': '#57ab5a',
|
||||
'verified-badge-bg': '#57ab5a1a',
|
||||
'verified-badge-border': '#57ab5a66',
|
||||
'social-count-bg': '#373e47',
|
||||
'tooltip-text': '#cdd9e5',
|
||||
'tooltip-bg': '#636e7b',
|
||||
'header-search-bg': '#22272e',
|
||||
'header-search-border': '#373e47',
|
||||
'search-keyword-hl': '#ae7c1466',
|
||||
'diffstat-neutral-bg': '#444c56',
|
||||
'diffstat-neutral-border': '#cdd9e51a',
|
||||
'diffstat-deletion-bg': '#c93c37',
|
||||
'diffstat-deletion-border': '#e5534b',
|
||||
'diffstat-addition-bg': '#347d39',
|
||||
'diffstat-addition-border': '#46954a',
|
||||
'mktg-success': '#3d8942',
|
||||
'mktg-info': '#3877d5',
|
||||
'mktg-bg-shade-gradient-top': '#1c212811',
|
||||
'mktg-bg-shade-gradient-bottom': '#1c212800',
|
||||
'mktg-btn-bg': '#316dca',
|
||||
'mktg-btn-border': '#316dca',
|
||||
'mktg-btn-text': '#cdd9e5',
|
||||
'mktg-btn-icon': '#cdd9e5',
|
||||
'mktg-btn-focus-shadow': '0 0 0 3px #316dca4d',
|
||||
'mktg-btn-hover-bg': '#4184e4',
|
||||
'mktg-btn-hover-border': '#4184e4',
|
||||
'mktg-btn-disabled-bg': '#4184e480',
|
||||
'mktg-btn-disabled-border': '#0000',
|
||||
'mktg-btn-disabled-text': '#cdd9e580',
|
||||
'mktg-btn-disabled-icon': '#cdd9e580',
|
||||
'mktg-btn-primary-bg': '#347d39',
|
||||
'mktg-btn-primary-border': '#347d39',
|
||||
'mktg-btn-primary-text': '#cdd9e5',
|
||||
'mktg-btn-primary-icon': '#cdd9e5',
|
||||
'mktg-btn-primary-focus-shadow': '0 0 0 3px #347d394d',
|
||||
'mktg-btn-primary-hover-bg': '#46954a',
|
||||
'mktg-btn-primary-hover-border': '#46954a',
|
||||
'mktg-btn-primary-disabled-bg': '#46954a80',
|
||||
'mktg-btn-primary-disabled-border': '#0000',
|
||||
'mktg-btn-primary-disabled-text': '#cdd9e580',
|
||||
'mktg-btn-primary-disabled-icon': '#cdd9e580',
|
||||
'mktg-btn-outline-bg': '#0000',
|
||||
'mktg-btn-outline-border': '#4184e480',
|
||||
'mktg-btn-outline-text': '#4184e4',
|
||||
'mktg-btn-outline-icon': '#4184e4',
|
||||
'mktg-btn-outline-focus-shadow': '0 0 0 3px #4184e44d',
|
||||
'mktg-btn-outline-hover-bg': '#0000',
|
||||
'mktg-btn-outline-hover-border': '#4184e4',
|
||||
'mktg-btn-outline-hover-text': '#539bf5',
|
||||
'mktg-btn-outline-hover-icon': '#539bf5',
|
||||
'mktg-btn-outline-disabled-bg': '#0000',
|
||||
'mktg-btn-outline-disabled-border': '#4184e433',
|
||||
'mktg-btn-outline-disabled-text': '#4184e480',
|
||||
'mktg-btn-outline-disabled-icon': '#4184e480',
|
||||
'mktg-btn-dark-bg': '#0000',
|
||||
'mktg-btn-dark-border': '#adbac780',
|
||||
'mktg-btn-dark-text': '#adbac7',
|
||||
'mktg-btn-dark-icon': '#adbac7',
|
||||
'mktg-btn-dark-focus-shadow': '0 0 0 3px #adbac74d',
|
||||
'mktg-btn-dark-hover-bg': '#adbac780',
|
||||
'mktg-btn-dark-hover-border': '#adbac780',
|
||||
'mktg-btn-dark-hover-text': '#22272e',
|
||||
'mktg-btn-dark-hover-icon': '#22272e',
|
||||
'mktg-btn-dark-disabled-bg': '#0000',
|
||||
'mktg-btn-dark-disabled-border': '#adbac733',
|
||||
'mktg-btn-dark-disabled-text': '#adbac780',
|
||||
'mktg-btn-dark-disabled-icon': '#adbac780',
|
||||
'files-explorer-icon': '#636e7b',
|
||||
'hl-author-bg': '#0f2d5c',
|
||||
'hl-author-border': '#1b4b91',
|
||||
'logo-subdued': '#444c56',
|
||||
'discussion-border': '#494c49',
|
||||
'discussion-bg-success': '#46954a1a',
|
||||
'actions-workflow-table-sticky-bg': '#22272ef2',
|
||||
'repo-language-color-border': '#cdd9e533',
|
||||
'code-selection-bg': '#6cb6ff4d',
|
||||
'highlight-text': '#ffd467',
|
||||
'highlight-bg': '#cc8f2c61',
|
||||
'blob-line-highlight-bg': '#c6902626',
|
||||
'blob-line-highlight-border': '#daaa3f',
|
||||
'diff-addition-text': '#6bc46d',
|
||||
'diff-addition-bg': '#46954a33',
|
||||
'diff-addition-border': '#2b6a30',
|
||||
'diff-deletion-text': '#e5534b',
|
||||
'diff-deletion-bg': '#c93c3733',
|
||||
'diff-deletion-border': '#ad2e2c',
|
||||
'diff-change-text': '#daaa3f',
|
||||
'diff-change-bg': '#452700',
|
||||
'diff-change-border': '#966600',
|
||||
'diff-blob-num-text': '#cdd9e54d',
|
||||
'diff-blob-num-hover-text': '#cdd9e599',
|
||||
'diff-blob-addition-num-text': '#57ab5a',
|
||||
'diff-blob-addition-num-hover-text': '#8ddb8c',
|
||||
'diff-blob-addition-num-bg': '#46954a1a',
|
||||
'diff-blob-addition-line-bg': '#46954a33',
|
||||
'diff-blob-addition-word-bg': '#46954a8c',
|
||||
'diff-blob-deletion-num-text': '#e5534b',
|
||||
'diff-blob-deletion-num-hover-text': '#ff938a',
|
||||
'diff-blob-deletion-num-bg': '#c93c371a',
|
||||
'diff-blob-deletion-line-bg': '#c93c3733',
|
||||
'diff-blob-deletion-word-bg': '#c93c3780',
|
||||
'diff-blob-hunk-text': '#768390',
|
||||
'diff-blob-hunk-num-bg': '#539bf526',
|
||||
'diff-blob-hunk-line-bg': '#539bf51a',
|
||||
'diff-blob-empty-block-bg': '#2d333b',
|
||||
'diff-blob-selected-line-highlight-bg': '#ae7c141a',
|
||||
'diff-blob-selected-line-highlight-border': '#ae7c14',
|
||||
'diff-blob-selected-line-highlight-mix-blend-mode': 'normal',
|
||||
'diff-blob-expander-icon': '#768390',
|
||||
'diff-blob-expander-hover-icon': '#cdd9e5',
|
||||
'diff-blob-expander-hover-bg': '#316dca',
|
||||
'diff-blob-comment-button-icon': '#cdd9e5',
|
||||
'diff-blob-comment-button-bg': '#316dca',
|
||||
'diff-blob-comment-button-gradient-bg': '#437bd1',
|
||||
'global-nav-logo': '#cdd9e5',
|
||||
'global-nav-bg': '#2d333b',
|
||||
'global-nav-text': '#adbac7',
|
||||
'global-nav-icon': '#adbac7',
|
||||
'global-nav-input-bg': '#22272e',
|
||||
'global-nav-input-border': '#373e47',
|
||||
'global-nav-input-icon': '#373e47',
|
||||
'global-nav-input-placeholder': '#545d68',
|
||||
'calendar-graph-day-bg': '#2d333b',
|
||||
'calendar-graph-day-border': '#1b1f230f',
|
||||
'calendar-graph-day-L1-bg': '#003820',
|
||||
'calendar-graph-day-L2-bg': '#00602d',
|
||||
'calendar-graph-day-L3-bg': '#10983d',
|
||||
'calendar-graph-day-L4-bg': '#27d545',
|
||||
'calendar-graph-day-L4-border': '#ffffff0d',
|
||||
'calendar-graph-day-L3-border': '#ffffff0d',
|
||||
'calendar-graph-day-L2-border': '#ffffff0d',
|
||||
'calendar-graph-day-L1-border': '#ffffff0d',
|
||||
'footer-invertocat-octicon': '#444c56',
|
||||
'footer-invertocat-octicon-hover': '#636e7b',
|
||||
'pr-state-draft-text': '#768390',
|
||||
'pr-state-draft-bg': '#7683901a',
|
||||
'pr-state-draft-border': '#76839066',
|
||||
'pr-state-open-text': '#57ab5a',
|
||||
'pr-state-open-bg': '#57ab5a1a',
|
||||
'pr-state-open-border': '#57ab5a66',
|
||||
'pr-state-merged-text': '#986ee2',
|
||||
'pr-state-merged-bg': '#b083f01a',
|
||||
'pr-state-merged-border': '#b083f066',
|
||||
'pr-state-closed-text': '#e5534b',
|
||||
'pr-state-closed-bg': '#c93c371a',
|
||||
'pr-state-closed-border': '#c93c3766',
|
||||
'topic-tag-text': '#539bf5',
|
||||
'topic-tag-bg': '#4184e41a',
|
||||
'topic-tag-hover-bg': '#4184e433',
|
||||
'topic-tag-active-bg': '#4184e426',
|
||||
'merge-box-success-icon-bg': '#46954a1a',
|
||||
'merge-box-success-icon-text': '#57ab5a',
|
||||
'merge-box-success-icon-border': '#46954a66',
|
||||
'merge-box-success-indicator-bg': '#347d39',
|
||||
'merge-box-success-indicator-border': '#46954a',
|
||||
'merge-box-merged-icon-bg': '#b083f01a',
|
||||
'merge-box-merged-icon-text': '#986ee2',
|
||||
'merge-box-merged-icon-border': '#b083f066',
|
||||
'merge-box-merged-box-border': '#b083f066',
|
||||
'merge-box-neutral-icon-bg': '#adbac71a',
|
||||
'merge-box-neutral-icon-text': '#768390',
|
||||
'merge-box-neutral-icon-border': '#adbac766',
|
||||
'merge-box-neutral-indicator-bg': '#545d68',
|
||||
'merge-box-neutral-indicator-border': '#636e7b',
|
||||
'merge-box-warning-icon-bg': '#ae7c141a',
|
||||
'merge-box-warning-icon-text': '#daaa3f',
|
||||
'merge-box-warning-icon-border': '#ae7c1466',
|
||||
'merge-box-warning-box-border': '#ae7c1466',
|
||||
'merge-box-warning-merge-highlight': '#ae7c141a',
|
||||
'merge-box-error-icon-bg': '#e5534b1a',
|
||||
'merge-box-error-icon-text': '#e5534b',
|
||||
'merge-box-error-icon-border': '#e5534b66',
|
||||
'merge-box-error-indicator-bg': '#c93c37',
|
||||
'merge-box-error-indicator-border': '#e5534b',
|
||||
'project-card-bg': '#2d333b',
|
||||
'project-header-bg': '#22272e',
|
||||
'project-sidebar-bg': '#2d333b',
|
||||
'project-gradient-in': '#2d333b',
|
||||
'project-gradient-out': '#2d333b00',
|
||||
'checks-bg': '#1e2228',
|
||||
'checks-run-border-width': '1px',
|
||||
'checks-container-border-width': '1px',
|
||||
'checks-text-primary': '#adbac7',
|
||||
'checks-text-secondary': '#768390',
|
||||
'checks-text-link': '#539bf5',
|
||||
'checks-btn-icon': '#636e7b',
|
||||
'checks-btn-hover-icon': '#adbac7',
|
||||
'checks-btn-hover-bg': '#444c56',
|
||||
'checks-input-text': '#768390',
|
||||
'checks-input-placeholder-text': '#545d68',
|
||||
'checks-input-focus-text': '#adbac7',
|
||||
'checks-input-bg': '#22272e',
|
||||
'checks-input-shadow': '0 0 0 1px #373e47',
|
||||
'checks-dropdown-text': '#adbac7',
|
||||
'checks-dropdown-bg': '#373e47',
|
||||
'checks-dropdown-border': '#444c56',
|
||||
'checks-dropdown-hover-text': '#cdd9e5',
|
||||
'checks-dropdown-hover-bg': '#316dca',
|
||||
'checks-dropdown-btn-hover-text': '#cdd9e5',
|
||||
'checks-dropdown-btn-hover-bg': '#2d333b',
|
||||
'checks-scrollbar-thumb-bg': '#444c56',
|
||||
'checks-header-label-text': '#768390',
|
||||
'checks-header-label-open-text': '#adbac7',
|
||||
'checks-header-border': '#373e47',
|
||||
'checks-header-icon': '#636e7b',
|
||||
'checks-line-text': '#768390',
|
||||
'checks-line-num-text': '#768390',
|
||||
'checks-line-timestamp-text': '#768390',
|
||||
'checks-line-hover-bg': '#2d333b',
|
||||
'checks-line-selected-bg': '#4184e41a',
|
||||
'checks-line-selected-num-text': '#539bf5',
|
||||
'checks-line-dt-fm-text': '#22272e',
|
||||
'checks-line-dt-fm-bg': '#c69026',
|
||||
'checks-gate-bg': '#80540026',
|
||||
'checks-gate-text': '#768390',
|
||||
'checks-gate-waiting-text': '#daaa3f',
|
||||
'checks-step-header-open-bg': '#2d333b',
|
||||
'checks-step-error-text': '#e5534b',
|
||||
'checks-step-warning-text': '#daaa3f',
|
||||
'checks-logline-text': '#636e7b',
|
||||
'checks-logline-num-text': '#768390',
|
||||
'checks-logline-debug-text': '#b083f0',
|
||||
'checks-logline-error-text': '#768390',
|
||||
'checks-logline-error-num-text': '#768390',
|
||||
'checks-logline-error-bg': '#e5534b1a',
|
||||
'checks-logline-warning-text': '#768390',
|
||||
'checks-logline-warning-num-text': '#daaa3f',
|
||||
'checks-logline-warning-bg': '#ae7c141a',
|
||||
'checks-logline-command-text': '#539bf5',
|
||||
'checks-logline-section-text': '#6bc46d',
|
||||
'intro-shelf-gradient-left': '#4184e41a',
|
||||
'intro-shelf-gradient-right': '#46954a1a',
|
||||
'intro-shelf-gradient-in': '#22272e',
|
||||
'intro-shelf-gradient-out': '#22272e00',
|
||||
'marketing-icon-primary': '#6cb6ff',
|
||||
'marketing-icon-secondary': '#316dca',
|
||||
'prettylights-syntax-comment': '#768390',
|
||||
'prettylights-syntax-constant': '#6cb6ff',
|
||||
'prettylights-syntax-entity': '#dcbdfb',
|
||||
'prettylights-syntax-storage-modifier-import': '#adbac7',
|
||||
'prettylights-syntax-entity-tag': '#8ddb8c',
|
||||
'prettylights-syntax-keyword': '#f47067',
|
||||
'prettylights-syntax-string': '#96d0ff',
|
||||
'prettylights-syntax-variable': '#f69d50',
|
||||
'prettylights-syntax-brackethighlighter-unmatched': '#e5534b',
|
||||
'prettylights-syntax-invalid-illegal-text': '#cdd9e5',
|
||||
'prettylights-syntax-invalid-illegal-bg': '#922323',
|
||||
'prettylights-syntax-carriage-return-text': '#cdd9e5',
|
||||
'prettylights-syntax-carriage-return-bg': '#ad2e2c',
|
||||
'prettylights-syntax-string-regexp': '#8ddb8c',
|
||||
'prettylights-syntax-markup-list': '#eac55f',
|
||||
'prettylights-syntax-markup-heading': '#316dca',
|
||||
'prettylights-syntax-markup-italic': '#adbac7',
|
||||
'prettylights-syntax-markup-bold': '#adbac7',
|
||||
'prettylights-syntax-markup-deleted-text': '#ffd8d3',
|
||||
'prettylights-syntax-markup-deleted-bg': '#78191b',
|
||||
'prettylights-syntax-markup-inserted-text': '#b4f1b4',
|
||||
'prettylights-syntax-markup-inserted-bg': '#1b4721',
|
||||
'prettylights-syntax-markup-changed-text': '#ffddb0',
|
||||
'prettylights-syntax-markup-changed-bg': '#682d0f',
|
||||
'prettylights-syntax-markup-ignored-text': '#adbac7',
|
||||
'prettylights-syntax-markup-ignored-bg': '#255ab2',
|
||||
'prettylights-syntax-meta-diff-range': '#dcbdfb',
|
||||
'prettylights-syntax-brackethighlighter-angle': '#768390',
|
||||
'prettylights-syntax-sublimelinter-gutter-mark': '#545d68',
|
||||
'prettylights-syntax-constant-other-reference-link': '#96d0ff',
|
||||
'codemirror-text': '#adbac7',
|
||||
'codemirror-bg': '#22272e',
|
||||
'codemirror-gutters-bg': '#22272e',
|
||||
'codemirror-guttermarker-text': '#22272e',
|
||||
'codemirror-guttermarker-subtle-text': '#636e7b',
|
||||
'codemirror-linenumber-text': '#768390',
|
||||
'codemirror-cursor': '#cdd9e5',
|
||||
'codemirror-selection-bg': '#6cb6ff4d',
|
||||
'codemirror-activeline-bg': '#2d333b',
|
||||
'codemirror-matchingbracket-text': '#adbac7',
|
||||
'codemirror-lines-bg': '#22272e',
|
||||
'codemirror-syntax-comment': '#768390',
|
||||
'codemirror-syntax-constant': '#6cb6ff',
|
||||
'codemirror-syntax-entity': '#dcbdfb',
|
||||
'codemirror-syntax-keyword': '#f47067',
|
||||
'codemirror-syntax-storage': '#f47067',
|
||||
'codemirror-syntax-string': '#96d0ff',
|
||||
'codemirror-syntax-support': '#6cb6ff',
|
||||
'codemirror-syntax-variable': '#f69d50',
|
||||
'ansi-black': '#22272e',
|
||||
'ansi-black-bright': '#2d333b',
|
||||
'ansi-white': '#909dab',
|
||||
'ansi-white-bright': '#909dab',
|
||||
'ansi-gray': '#636e7b',
|
||||
'ansi-red': '#f47067',
|
||||
'ansi-red-bright': '#ff938a',
|
||||
'ansi-green': '#57ab5a',
|
||||
'ansi-green-bright': '#6bc46d',
|
||||
'ansi-yellow': '#c69026',
|
||||
'ansi-yellow-bright': '#daaa3f',
|
||||
'ansi-blue': '#539bf5',
|
||||
'ansi-blue-bright': '#6cb6ff',
|
||||
'ansi-magenta': '#b083f0',
|
||||
'ansi-magenta-bright': '#dcbdfb',
|
||||
'ansi-cyan': '#76e3ea',
|
||||
'ansi-cyan-bright': '#b3f0ff',
|
||||
);
|
||||
|
|
@ -1,7 +1,6 @@
|
|||
@import '~nprogress/nprogress.css';
|
||||
|
||||
@import './dark/export.scss';
|
||||
@import './light/export.scss';
|
||||
@import './themes.scss';
|
||||
|
||||
$name: gitako;
|
||||
|
||||
|
|
@ -14,6 +13,40 @@ $github-header-z-index: 32;
|
|||
$github-pull-request-float-header-z-index: 110;
|
||||
$minimal-z-index: max($github-header-z-index, $github-pull-request-float-header-z-index) + 1;
|
||||
|
||||
@mixin interactive-background($default, $hover, $active, $focus: $hover) {
|
||||
background-color: $default;
|
||||
&:hover {
|
||||
background-color: $hover;
|
||||
}
|
||||
&:focus {
|
||||
background-color: $focus;
|
||||
}
|
||||
&:active {
|
||||
background-color: $active;
|
||||
}
|
||||
}
|
||||
|
||||
@mixin interactive-background-on-before($default, $hover, $active, $focus: $hover) {
|
||||
&::before {
|
||||
background-color: $default;
|
||||
}
|
||||
&:hover {
|
||||
&::before {
|
||||
background-color: $hover;
|
||||
}
|
||||
}
|
||||
&:active {
|
||||
&::before {
|
||||
background-color: $active;
|
||||
}
|
||||
}
|
||||
&:hover {
|
||||
&::before {
|
||||
background-color: $hover;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
:root {
|
||||
--gitako-width: #{$side-bar-base-width};
|
||||
}
|
||||
|
|
@ -55,6 +88,117 @@ $minimal-z-index: max($github-header-z-index, $github-pull-request-float-header-
|
|||
}
|
||||
}
|
||||
|
||||
// code folding start
|
||||
.blob-wrapper table .blob-num {
|
||||
position: relative; // for positioning
|
||||
min-width: 60px;
|
||||
padding-right: 20px;
|
||||
}
|
||||
|
||||
// cancel code fold if not wrapped with .gitako-code-fold-mark
|
||||
.gitako-code-fold-handler {
|
||||
display: none;
|
||||
}
|
||||
.gitako-code-fold-hidden {
|
||||
display: table-cell;
|
||||
}
|
||||
|
||||
.gitako-code-fold-attached {
|
||||
tr {
|
||||
.gitako-code-fold-handler {
|
||||
display: initial;
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
right: 0px;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
&::before {
|
||||
content: '';
|
||||
display: block;
|
||||
width: 10px;
|
||||
height: 20px;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
transition: 0.25s ease;
|
||||
-webkit-mask-image: url('~@primer/octicons/build/svg/chevron-down.svg?inline');
|
||||
mask-image: url('~@primer/octicons/build/svg/chevron-down.svg?inline');
|
||||
-webkit-mask-size: contain;
|
||||
mask-size: contain;
|
||||
-webkit-mask-position: center;
|
||||
mask-position: center;
|
||||
}
|
||||
|
||||
@include interactive-background-on-before(
|
||||
var(--gitako-icon-tertiary),
|
||||
var(--gitako-icon-primary),
|
||||
var(--gitako-icon-secondary)
|
||||
);
|
||||
}
|
||||
|
||||
&.active {
|
||||
.gitako-code-fold-handler {
|
||||
&::before {
|
||||
transform: rotate(-90deg);
|
||||
}
|
||||
|
||||
@include interactive-background-on-before(
|
||||
var(--gitako-icon-secondary),
|
||||
var(--gitako-icon-tertiary),
|
||||
var(--gitako-icon-primary)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.gitako-code-fold-hidden {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
// code folding end
|
||||
|
||||
// clippy button
|
||||
.markdown-body {
|
||||
.clippy-wrapper {
|
||||
position: relative;
|
||||
width: 0;
|
||||
height: 0;
|
||||
top: 8px;
|
||||
left: calc(100% - 40px);
|
||||
z-index: 1;
|
||||
|
||||
.clippy {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
border: 1px solid var(--gitako-border-tertiary);
|
||||
border-radius: 4px;
|
||||
|
||||
@include interactive-background(
|
||||
var(--gitako-btn-bg),
|
||||
var(--gitako-btn-hover-bg),
|
||||
var(--gitako-btn-focus-bg)
|
||||
);
|
||||
.icon {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: block;
|
||||
background-image: url('~@primer/octicons-react/build/svg/clippy-16.svg?inline');
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
&.success {
|
||||
background-image: url('~@primer/octicons-react/build/svg/check-16.svg?inline');
|
||||
}
|
||||
&.fail {
|
||||
background-image: url('~@primer/octicons-react/build/svg/x-16.svg?inline');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// gitee
|
||||
&.git-project {
|
||||
#git-header-nav {
|
||||
|
|
@ -98,45 +242,6 @@ $minimal-z-index: max($github-header-z-index, $github-pull-request-float-header-
|
|||
}
|
||||
}
|
||||
|
||||
.markdown-body {
|
||||
.clippy-wrapper {
|
||||
position: relative;
|
||||
width: 0;
|
||||
height: 0;
|
||||
top: 8px;
|
||||
left: calc(100% - 40px);
|
||||
z-index: 1;
|
||||
|
||||
.clippy {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
border: 1px solid var(--gitako-border-tertiary);
|
||||
border-radius: 4px;
|
||||
background: var(--gitako-bg-secondary);
|
||||
&:hover {
|
||||
background: var(--gitako-bg-secondary);
|
||||
}
|
||||
&:active {
|
||||
background: var(--gitako-bg-secondary);
|
||||
}
|
||||
.icon {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: block;
|
||||
background-image: url('~@primer/octicons-react/build/svg/clippy-16.svg?inline');
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
&.success {
|
||||
background-image: url('~@primer/octicons-react/build/svg/check-16.svg?inline');
|
||||
}
|
||||
&.fail {
|
||||
background-image: url('~@primer/octicons-react/build/svg/x-16.svg?inline');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.progress-pjax-loader.is-loading {
|
||||
left: 0; /* reposition progress bar of GitHub */
|
||||
}
|
||||
|
|
@ -145,31 +250,24 @@ $minimal-z-index: max($github-header-z-index, $github-pull-request-float-header-
|
|||
display: none;
|
||||
}
|
||||
|
||||
.invisible {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
@mixin flex-center {
|
||||
display: inline-flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
@mixin icon-button {
|
||||
@mixin icon-button(
|
||||
$default: transparent,
|
||||
$hover: var(--gitako-btn-hover-bg),
|
||||
$active: var(--gitako-btn-focus-bg),
|
||||
$focus: $hover
|
||||
) {
|
||||
@include flex-center();
|
||||
cursor: pointer;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
@mixin button-color {
|
||||
border: none;
|
||||
background: transparent;
|
||||
&:hover {
|
||||
background: var(--gitako-btn-hover-bg);
|
||||
}
|
||||
&:active {
|
||||
background: var(--gitako-btn-focus-bg);
|
||||
}
|
||||
|
||||
@include interactive-background($default, $hover, $active, $focus);
|
||||
}
|
||||
|
||||
// Why does not TextInput get theme properly?
|
||||
|
|
@ -187,17 +285,30 @@ $minimal-z-index: max($github-header-z-index, $github-pull-request-float-header-
|
|||
left: 0px;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
transition: left 0.25s linear;
|
||||
|
||||
&.hidden {
|
||||
left: -40px;
|
||||
}
|
||||
|
||||
.#{$name}-toggle-show-button {
|
||||
@include icon-button;
|
||||
@include icon-button(transparent, transparent, transparent);
|
||||
background: transparent;
|
||||
border: none;
|
||||
padding: 0;
|
||||
position: relative;
|
||||
left: -8px;
|
||||
|
||||
&.error {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.octoface-icon {
|
||||
@include flex-center();
|
||||
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
padding: 4px;
|
||||
border-radius: 6px;
|
||||
border: 1px solid var(--gitako-border-tertiary);
|
||||
background: var(--gitako-bg-tertiary);
|
||||
|
|
@ -207,33 +318,27 @@ $minimal-z-index: max($github-header-z-index, $github-pull-request-float-header-
|
|||
}
|
||||
transition: all ease 0.3s;
|
||||
font-size: 16px;
|
||||
transform: translateX(0px);
|
||||
transform: translateX(8px);
|
||||
&:active,
|
||||
&:hover {
|
||||
transform: translateX(4px);
|
||||
transform: translateX(12px);
|
||||
}
|
||||
}
|
||||
.tentacle {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
object-fit: contain;
|
||||
transition: all ease 0.4s;
|
||||
transform: translateX(-16px);
|
||||
transform: translateX(-8px);
|
||||
filter: drop-shadow(0 0 1px var(--gitako-bg-backdrop));
|
||||
}
|
||||
&:active,
|
||||
&:hover {
|
||||
.tentacle {
|
||||
transform: translateX(-12px);
|
||||
transform: translateX(-4px);
|
||||
filter: drop-shadow(0 0 2px var(--gitako-bg-backdrop));
|
||||
}
|
||||
}
|
||||
|
||||
img {
|
||||
filter: drop-shadow(0 0 1px var(--gitako-bg-backdrop));
|
||||
transition: all ease 0.3s;
|
||||
width: 90%;
|
||||
height: 90%;
|
||||
object-fit: contain;
|
||||
}
|
||||
}
|
||||
|
||||
.error-message {
|
||||
|
|
@ -264,7 +369,8 @@ $minimal-z-index: max($github-header-z-index, $github-pull-request-float-header-
|
|||
color: var(--gitako-text-link);
|
||||
}
|
||||
|
||||
.#{$name}-position-wrapper {
|
||||
$resizeHandlerWidth: 1px;
|
||||
.#{$name}-side-bar-body-wrapper {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
|
|
@ -272,11 +378,21 @@ $minimal-z-index: max($github-header-z-index, $github-pull-request-float-header-
|
|||
z-index: $minimal-z-index;
|
||||
display: flex;
|
||||
|
||||
&.hidden {
|
||||
@extend %hidden;
|
||||
&.toggle-mode-persistent {
|
||||
&.collapsed {
|
||||
@extend %hidden;
|
||||
}
|
||||
}
|
||||
|
||||
.gitako-position-content {
|
||||
&.toggle-mode-float {
|
||||
left: 0;
|
||||
transition: all 0.25s cubic-bezier(0.55, 0.06, 0.68, 0.19); // values from Chrome devtools
|
||||
&.collapsed {
|
||||
left: calc(0px - #{$resizeHandlerWidth} - var(--gitako-width));
|
||||
}
|
||||
}
|
||||
|
||||
.gitako-side-bar-body-wrapper-content {
|
||||
width: var(--gitako-width);
|
||||
}
|
||||
}
|
||||
|
|
@ -287,7 +403,7 @@ $minimal-z-index: max($github-header-z-index, $github-pull-request-float-header-
|
|||
user-select: none;
|
||||
width: 0;
|
||||
background: var(--gitako-bg-tertiary);
|
||||
border-right: 1px solid var(--gitako-border-tertiary);
|
||||
border-right: $resizeHandlerWidth solid var(--gitako-border-tertiary);
|
||||
overflow: hidden;
|
||||
box-sizing: content-box;
|
||||
&:hover,
|
||||
|
|
@ -315,10 +431,6 @@ $minimal-z-index: max($github-header-z-index, $github-pull-request-float-header-
|
|||
border-left: 1px solid var(--gitako-border-overlay);
|
||||
overflow: hidden;
|
||||
|
||||
&.hidden {
|
||||
@extend %hidden;
|
||||
}
|
||||
|
||||
.octicon {
|
||||
transition: transform 0.3s ease;
|
||||
color: var(--gitako-icon-tertiary);
|
||||
|
|
@ -337,70 +449,79 @@ $minimal-z-index: max($github-header-z-index, $github-pull-request-float-header-
|
|||
text-align: center;
|
||||
}
|
||||
|
||||
.close-side-bar-button-position {
|
||||
position: absolute;
|
||||
right: 6px;
|
||||
top: 6px;
|
||||
z-index: 1; // prevent being covered by following elements
|
||||
|
||||
.close-side-bar-button {
|
||||
@include icon-button;
|
||||
@include button-color;
|
||||
width: $button-size;
|
||||
height: $button-size;
|
||||
border-radius: $button-size;
|
||||
|
||||
// feedback to click should be instant
|
||||
&:not(:active) {
|
||||
transition: background linear 0.3s;
|
||||
}
|
||||
|
||||
.action-icon {
|
||||
color: var(--gitako-icon-tertiary);
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
text-align: center;
|
||||
.octicon {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.#{$name}-side-bar-content {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
max-height: calc(100vh - 34px); // temporary fix for layout issue occurred since Chrome v76
|
||||
min-height: 0; // make content shrinkable
|
||||
|
||||
.header {
|
||||
position: relative;
|
||||
min-height: 62px; // GitHub header height if login
|
||||
background: var(--gitako-bg-tertiary);
|
||||
padding: 6px 10px;
|
||||
flex-shrink: 0;
|
||||
position: relative; // prevent overlap by outline of other elements
|
||||
|
||||
.meta-bar {
|
||||
position: relative; // prevent overlap by outline of other elements
|
||||
min-height: 62px; // GitHub header height if login
|
||||
flex-shrink: 0;
|
||||
padding: 8px 10px;
|
||||
padding-right: $button-size + 8px * 2; // space for toggle button
|
||||
background: var(--gitako-bg-tertiary);
|
||||
.user-and-repo {
|
||||
display: inline; // would be override by CSS rule of section from @primer/css
|
||||
line-height: 32px;
|
||||
|
||||
.user-and-repo a {
|
||||
a {
|
||||
color: var(--gitako-text-link);
|
||||
white-space: normal;
|
||||
}
|
||||
}
|
||||
|
||||
.branch-name {
|
||||
margin-left: 4px;
|
||||
padding: 4px 6px; // did not align well for some reason :/
|
||||
color: var(--gitako-branch-name-text);
|
||||
background-color: var(--gitako-branch-name-bg);
|
||||
}
|
||||
|
||||
.close-side-bar-button-position {
|
||||
float: right;
|
||||
z-index: 1; // prevent being covered by following elements
|
||||
|
||||
.close-side-bar-button {
|
||||
@include icon-button;
|
||||
width: $button-size;
|
||||
height: $button-size;
|
||||
border-radius: $button-size;
|
||||
|
||||
// feedback to click should be instant
|
||||
&:not(:active) {
|
||||
transition: background linear 0.3s;
|
||||
}
|
||||
|
||||
&.active .octicon {
|
||||
color: var(--gitako-icon-primary);
|
||||
}
|
||||
|
||||
.action-icon {
|
||||
color: var(--gitako-icon-tertiary);
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
text-align: center;
|
||||
.octicon {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.Pin,
|
||||
.Tab {
|
||||
transform: rotateY(180deg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.branch-name {
|
||||
.close-side-bar-button + .close-side-bar-button {
|
||||
margin-left: 4px;
|
||||
padding: 4px 6px; // did not align well for some reason :/
|
||||
color: var(--gitako-branch-name-text);
|
||||
background-color: var(--gitako-branch-name-bg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.description {
|
||||
border-top: 1px solid var(--gitako-border-overlay);
|
||||
.description-area {
|
||||
padding: 4px 10px;
|
||||
}
|
||||
|
||||
|
|
@ -474,25 +595,23 @@ $minimal-z-index: max($github-header-z-index, $github-pull-request-float-header-
|
|||
align-items: center;
|
||||
padding: 0 4px;
|
||||
|
||||
.toggle-mode {
|
||||
.toggle-search-mode {
|
||||
margin: 0;
|
||||
padding: 2px 4px;
|
||||
min-width: 32px;
|
||||
border: 1px solid var(--gitako-border-secondary);
|
||||
border-radius: 8px;
|
||||
background: var(--gitako-bg-primary);
|
||||
color: var(--gitako-text-secondary);
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
line-height: 1;
|
||||
outline: none;
|
||||
&:focus,
|
||||
&:hover {
|
||||
background: var(--gitako-bg-secondary);
|
||||
}
|
||||
&:active {
|
||||
background: var(--gitako-bg-tertiary);
|
||||
}
|
||||
|
||||
@include interactive-background(
|
||||
var(--gitako-bg-primary),
|
||||
var(--gitako-bg-secondary),
|
||||
var(--gitako-bg-tertiary)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -504,15 +623,27 @@ $minimal-z-index: max($github-header-z-index, $github-pull-request-float-header-
|
|||
}
|
||||
|
||||
.node-item {
|
||||
background: var(--gitako-bg-primary);
|
||||
&.focused,
|
||||
&:hover {
|
||||
background: var(--gitako-bg-tertiary);
|
||||
text-decoration: initial; // revert underline from .gitako-side-bar a:hover
|
||||
.node-item-label {
|
||||
text-decoration: underline; // apply underline like .gitako-side-bar a:hover
|
||||
}
|
||||
}
|
||||
&:active {
|
||||
background: var(--gitako-bg-secondary);
|
||||
|
||||
&.focused {
|
||||
@include interactive-background(
|
||||
var(--gitako-bg-tertiary),
|
||||
var(--gitako-bg-secondary),
|
||||
var(--gitako-bg-overlay)
|
||||
);
|
||||
}
|
||||
|
||||
@include interactive-background(
|
||||
var(--gitako-auto-white),
|
||||
var(--gitako-bg-secondary),
|
||||
var(--gitako-bg-tertiary)
|
||||
);
|
||||
|
||||
&.disabled {
|
||||
pointer-events: none;
|
||||
color: var(--gitako-text-disabled);
|
||||
|
|
@ -523,10 +654,18 @@ $minimal-z-index: max($github-header-z-index, $github-pull-request-float-header-
|
|||
margin: 0;
|
||||
line-height: 20px;
|
||||
cursor: pointer;
|
||||
border-bottom: 1px solid var(--gitako-border-secondary);
|
||||
white-space: nowrap;
|
||||
transition: padding 0.3s ease; // on toggle expansion in search results
|
||||
|
||||
border-bottom: 1px solid var(--gitako-border-secondary);
|
||||
&.compact {
|
||||
border-bottom: none;
|
||||
&.focused {
|
||||
border-top: 1px solid var(--gitako-border-secondary);
|
||||
border-bottom: 1px solid var(--gitako-border-secondary);
|
||||
}
|
||||
}
|
||||
|
||||
&:not(:hover) {
|
||||
color: var(--gitako-text-primary);
|
||||
}
|
||||
|
|
@ -579,18 +718,43 @@ $minimal-z-index: max($github-header-z-index, $github-pull-request-float-header-
|
|||
}
|
||||
}
|
||||
|
||||
.go-to-button,
|
||||
.find-in-folder-button {
|
||||
@include icon-button();
|
||||
@include button-color();
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
border-radius: 28px;
|
||||
white-space: nowrap;
|
||||
.octicon-wrapper {
|
||||
margin-right: 0;
|
||||
.actions {
|
||||
z-index: 1; // prevent being covered by next .node-item
|
||||
padding-right: 8px;
|
||||
|
||||
.node-item-comment {
|
||||
display: inline-block;
|
||||
width: 48px;
|
||||
padding: 0 4px;
|
||||
color: var(--gitako-text-tertiary);
|
||||
|
||||
.octicon-wrapper {
|
||||
margin: 0; // make it closer to the comment amount label
|
||||
}
|
||||
}
|
||||
|
||||
.go-to-button,
|
||||
.find-in-folder-button {
|
||||
@include icon-button();
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
border-radius: 28px;
|
||||
white-space: nowrap;
|
||||
.octicon-wrapper {
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.compact {
|
||||
.go-to-button,
|
||||
.find-in-folder-button {
|
||||
border-radius: 4px;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
&:not(:hover) {
|
||||
.go-to-button,
|
||||
.find-in-folder-button {
|
||||
|
|
@ -722,7 +886,6 @@ $minimal-z-index: max($github-header-z-index, $github-pull-request-float-header-
|
|||
|
||||
.settings-button {
|
||||
@include icon-button();
|
||||
@include button-color();
|
||||
$size: 32px;
|
||||
width: $size;
|
||||
height: $size;
|
||||
|
|
|
|||
|
|
@ -1,568 +0,0 @@
|
|||
@use './variables.scss' as variables;
|
||||
|
||||
:root {
|
||||
--gitako-auto-black: #{variables.$auto-black};
|
||||
--gitako-auto-white: #{variables.$auto-white};
|
||||
--gitako-auto-gray-0: #{variables.$auto-gray-0};
|
||||
--gitako-auto-gray-1: #{variables.$auto-gray-1};
|
||||
--gitako-auto-gray-2: #{variables.$auto-gray-2};
|
||||
--gitako-auto-gray-3: #{variables.$auto-gray-3};
|
||||
--gitako-auto-gray-4: #{variables.$auto-gray-4};
|
||||
--gitako-auto-gray-5: #{variables.$auto-gray-5};
|
||||
--gitako-auto-gray-6: #{variables.$auto-gray-6};
|
||||
--gitako-auto-gray-7: #{variables.$auto-gray-7};
|
||||
--gitako-auto-gray-8: #{variables.$auto-gray-8};
|
||||
--gitako-auto-gray-9: #{variables.$auto-gray-9};
|
||||
--gitako-auto-blue-0: #{variables.$auto-blue-0};
|
||||
--gitako-auto-blue-1: #{variables.$auto-blue-1};
|
||||
--gitako-auto-blue-2: #{variables.$auto-blue-2};
|
||||
--gitako-auto-blue-3: #{variables.$auto-blue-3};
|
||||
--gitako-auto-blue-4: #{variables.$auto-blue-4};
|
||||
--gitako-auto-blue-5: #{variables.$auto-blue-5};
|
||||
--gitako-auto-blue-6: #{variables.$auto-blue-6};
|
||||
--gitako-auto-blue-7: #{variables.$auto-blue-7};
|
||||
--gitako-auto-blue-8: #{variables.$auto-blue-8};
|
||||
--gitako-auto-blue-9: #{variables.$auto-blue-9};
|
||||
--gitako-auto-green-0: #{variables.$auto-green-0};
|
||||
--gitako-auto-green-1: #{variables.$auto-green-1};
|
||||
--gitako-auto-green-2: #{variables.$auto-green-2};
|
||||
--gitako-auto-green-3: #{variables.$auto-green-3};
|
||||
--gitako-auto-green-4: #{variables.$auto-green-4};
|
||||
--gitako-auto-green-5: #{variables.$auto-green-5};
|
||||
--gitako-auto-green-6: #{variables.$auto-green-6};
|
||||
--gitako-auto-green-7: #{variables.$auto-green-7};
|
||||
--gitako-auto-green-8: #{variables.$auto-green-8};
|
||||
--gitako-auto-green-9: #{variables.$auto-green-9};
|
||||
--gitako-auto-yellow-0: #{variables.$auto-yellow-0};
|
||||
--gitako-auto-yellow-1: #{variables.$auto-yellow-1};
|
||||
--gitako-auto-yellow-2: #{variables.$auto-yellow-2};
|
||||
--gitako-auto-yellow-3: #{variables.$auto-yellow-3};
|
||||
--gitako-auto-yellow-4: #{variables.$auto-yellow-4};
|
||||
--gitako-auto-yellow-5: #{variables.$auto-yellow-5};
|
||||
--gitako-auto-yellow-6: #{variables.$auto-yellow-6};
|
||||
--gitako-auto-yellow-7: #{variables.$auto-yellow-7};
|
||||
--gitako-auto-yellow-8: #{variables.$auto-yellow-8};
|
||||
--gitako-auto-yellow-9: #{variables.$auto-yellow-9};
|
||||
--gitako-auto-orange-0: #{variables.$auto-orange-0};
|
||||
--gitako-auto-orange-1: #{variables.$auto-orange-1};
|
||||
--gitako-auto-orange-2: #{variables.$auto-orange-2};
|
||||
--gitako-auto-orange-3: #{variables.$auto-orange-3};
|
||||
--gitako-auto-orange-4: #{variables.$auto-orange-4};
|
||||
--gitako-auto-orange-5: #{variables.$auto-orange-5};
|
||||
--gitako-auto-orange-6: #{variables.$auto-orange-6};
|
||||
--gitako-auto-orange-7: #{variables.$auto-orange-7};
|
||||
--gitako-auto-orange-8: #{variables.$auto-orange-8};
|
||||
--gitako-auto-orange-9: #{variables.$auto-orange-9};
|
||||
--gitako-auto-red-0: #{variables.$auto-red-0};
|
||||
--gitako-auto-red-1: #{variables.$auto-red-1};
|
||||
--gitako-auto-red-2: #{variables.$auto-red-2};
|
||||
--gitako-auto-red-3: #{variables.$auto-red-3};
|
||||
--gitako-auto-red-4: #{variables.$auto-red-4};
|
||||
--gitako-auto-red-5: #{variables.$auto-red-5};
|
||||
--gitako-auto-red-6: #{variables.$auto-red-6};
|
||||
--gitako-auto-red-7: #{variables.$auto-red-7};
|
||||
--gitako-auto-red-8: #{variables.$auto-red-8};
|
||||
--gitako-auto-red-9: #{variables.$auto-red-9};
|
||||
--gitako-auto-purple-0: #{variables.$auto-purple-0};
|
||||
--gitako-auto-purple-1: #{variables.$auto-purple-1};
|
||||
--gitako-auto-purple-2: #{variables.$auto-purple-2};
|
||||
--gitako-auto-purple-3: #{variables.$auto-purple-3};
|
||||
--gitako-auto-purple-4: #{variables.$auto-purple-4};
|
||||
--gitako-auto-purple-5: #{variables.$auto-purple-5};
|
||||
--gitako-auto-purple-6: #{variables.$auto-purple-6};
|
||||
--gitako-auto-purple-7: #{variables.$auto-purple-7};
|
||||
--gitako-auto-purple-8: #{variables.$auto-purple-8};
|
||||
--gitako-auto-purple-9: #{variables.$auto-purple-9};
|
||||
--gitako-auto-pink-0: #{variables.$auto-pink-0};
|
||||
--gitako-auto-pink-1: #{variables.$auto-pink-1};
|
||||
--gitako-auto-pink-2: #{variables.$auto-pink-2};
|
||||
--gitako-auto-pink-3: #{variables.$auto-pink-3};
|
||||
--gitako-auto-pink-4: #{variables.$auto-pink-4};
|
||||
--gitako-auto-pink-5: #{variables.$auto-pink-5};
|
||||
--gitako-auto-pink-6: #{variables.$auto-pink-6};
|
||||
--gitako-auto-pink-7: #{variables.$auto-pink-7};
|
||||
--gitako-auto-pink-8: #{variables.$auto-pink-8};
|
||||
--gitako-auto-pink-9: #{variables.$auto-pink-9};
|
||||
--gitako-text-primary: #{variables.$text-primary};
|
||||
--gitako-text-secondary: #{variables.$text-secondary};
|
||||
--gitako-text-tertiary: #{variables.$text-tertiary};
|
||||
--gitako-text-placeholder: #{variables.$text-placeholder};
|
||||
--gitako-text-disabled: #{variables.$text-disabled};
|
||||
--gitako-text-inverse: #{variables.$text-inverse};
|
||||
--gitako-text-link: #{variables.$text-link};
|
||||
--gitako-text-danger: #{variables.$text-danger};
|
||||
--gitako-text-success: #{variables.$text-success};
|
||||
--gitako-text-warning: #{variables.$text-warning};
|
||||
--gitako-text-white: #{variables.$text-white};
|
||||
--gitako-icon-primary: #{variables.$icon-primary};
|
||||
--gitako-icon-secondary: #{variables.$icon-secondary};
|
||||
--gitako-icon-tertiary: #{variables.$icon-tertiary};
|
||||
--gitako-icon-info: #{variables.$icon-info};
|
||||
--gitako-icon-danger: #{variables.$icon-danger};
|
||||
--gitako-icon-success: #{variables.$icon-success};
|
||||
--gitako-icon-warning: #{variables.$icon-warning};
|
||||
--gitako-border-primary: #{variables.$border-primary};
|
||||
--gitako-border-secondary: #{variables.$border-secondary};
|
||||
--gitako-border-tertiary: #{variables.$border-tertiary};
|
||||
--gitako-border-overlay: #{variables.$border-overlay};
|
||||
--gitako-border-inverse: #{variables.$border-inverse};
|
||||
--gitako-border-info: #{variables.$border-info};
|
||||
--gitako-border-danger: #{variables.$border-danger};
|
||||
--gitako-border-success: #{variables.$border-success};
|
||||
--gitako-border-warning: #{variables.$border-warning};
|
||||
--gitako-bg-canvas: #{variables.$bg-canvas};
|
||||
--gitako-bg-canvas-mobile: #{variables.$bg-canvas-mobile};
|
||||
--gitako-bg-canvas-inverse: #{variables.$bg-canvas-inverse};
|
||||
--gitako-bg-canvas-inset: #{variables.$bg-canvas-inset};
|
||||
--gitako-bg-primary: #{variables.$bg-primary};
|
||||
--gitako-bg-secondary: #{variables.$bg-secondary};
|
||||
--gitako-bg-tertiary: #{variables.$bg-tertiary};
|
||||
--gitako-bg-overlay: #{variables.$bg-overlay};
|
||||
--gitako-bg-backdrop: #{variables.$bg-backdrop};
|
||||
--gitako-bg-info: #{variables.$bg-info};
|
||||
--gitako-bg-info-inverse: #{variables.$bg-info-inverse};
|
||||
--gitako-bg-danger: #{variables.$bg-danger};
|
||||
--gitako-bg-danger-inverse: #{variables.$bg-danger-inverse};
|
||||
--gitako-bg-success: #{variables.$bg-success};
|
||||
--gitako-bg-success-inverse: #{variables.$bg-success-inverse};
|
||||
--gitako-bg-warning: #{variables.$bg-warning};
|
||||
--gitako-bg-warning-inverse: #{variables.$bg-warning-inverse};
|
||||
--gitako-shadow-small: #{variables.$shadow-small};
|
||||
--gitako-shadow-medium: #{variables.$shadow-medium};
|
||||
--gitako-shadow-large: #{variables.$shadow-large};
|
||||
--gitako-shadow-extra-large: #{variables.$shadow-extra-large};
|
||||
--gitako-shadow-highlight: #{variables.$shadow-highlight};
|
||||
--gitako-shadow-inset: #{variables.$shadow-inset};
|
||||
--gitako-state-hover-primary-bg: #{variables.$state-hover-primary-bg};
|
||||
--gitako-state-hover-primary-border: #{variables.$state-hover-primary-border};
|
||||
--gitako-state-hover-primary-text: #{variables.$state-hover-primary-text};
|
||||
--gitako-state-hover-primary-icon: #{variables.$state-hover-primary-icon};
|
||||
--gitako-state-hover-secondary-bg: #{variables.$state-hover-secondary-bg};
|
||||
--gitako-state-hover-secondary-border: #{variables.$state-hover-secondary-border};
|
||||
--gitako-state-selected-primary-bg: #{variables.$state-selected-primary-bg};
|
||||
--gitako-state-selected-primary-border: #{variables.$state-selected-primary-border};
|
||||
--gitako-state-selected-primary-text: #{variables.$state-selected-primary-text};
|
||||
--gitako-state-selected-primary-icon: #{variables.$state-selected-primary-icon};
|
||||
--gitako-state-focus-border: #{variables.$state-focus-border};
|
||||
--gitako-state-focus-shadow: #{variables.$state-focus-shadow};
|
||||
--gitako-fade-fg-10: #{variables.$fade-fg-10};
|
||||
--gitako-fade-fg-15: #{variables.$fade-fg-15};
|
||||
--gitako-fade-fg-30: #{variables.$fade-fg-30};
|
||||
--gitako-fade-fg-50: #{variables.$fade-fg-50};
|
||||
--gitako-fade-fg-70: #{variables.$fade-fg-70};
|
||||
--gitako-fade-fg-85: #{variables.$fade-fg-85};
|
||||
--gitako-fade-black-10: #{variables.$fade-black-10};
|
||||
--gitako-fade-black-15: #{variables.$fade-black-15};
|
||||
--gitako-fade-black-30: #{variables.$fade-black-30};
|
||||
--gitako-fade-black-50: #{variables.$fade-black-50};
|
||||
--gitako-fade-black-70: #{variables.$fade-black-70};
|
||||
--gitako-fade-black-85: #{variables.$fade-black-85};
|
||||
--gitako-fade-white-10: #{variables.$fade-white-10};
|
||||
--gitako-fade-white-15: #{variables.$fade-white-15};
|
||||
--gitako-fade-white-30: #{variables.$fade-white-30};
|
||||
--gitako-fade-white-50: #{variables.$fade-white-50};
|
||||
--gitako-fade-white-70: #{variables.$fade-white-70};
|
||||
--gitako-fade-white-85: #{variables.$fade-white-85};
|
||||
--gitako-alert-info-text: #{variables.$alert-info-text};
|
||||
--gitako-alert-info-icon: #{variables.$alert-info-icon};
|
||||
--gitako-alert-info-bg: #{variables.$alert-info-bg};
|
||||
--gitako-alert-info-border: #{variables.$alert-info-border};
|
||||
--gitako-alert-warn-text: #{variables.$alert-warn-text};
|
||||
--gitako-alert-warn-icon: #{variables.$alert-warn-icon};
|
||||
--gitako-alert-warn-bg: #{variables.$alert-warn-bg};
|
||||
--gitako-alert-warn-border: #{variables.$alert-warn-border};
|
||||
--gitako-alert-error-text: #{variables.$alert-error-text};
|
||||
--gitako-alert-error-icon: #{variables.$alert-error-icon};
|
||||
--gitako-alert-error-bg: #{variables.$alert-error-bg};
|
||||
--gitako-alert-error-border: #{variables.$alert-error-border};
|
||||
--gitako-alert-success-text: #{variables.$alert-success-text};
|
||||
--gitako-alert-success-icon: #{variables.$alert-success-icon};
|
||||
--gitako-alert-success-bg: #{variables.$alert-success-bg};
|
||||
--gitako-alert-success-border: #{variables.$alert-success-border};
|
||||
--gitako-autocomplete-shadow: #{variables.$autocomplete-shadow};
|
||||
--gitako-autocomplete-row-border: #{variables.$autocomplete-row-border};
|
||||
--gitako-blankslate-icon: #{variables.$blankslate-icon};
|
||||
--gitako-btn-text: #{variables.$btn-text};
|
||||
--gitako-btn-bg: #{variables.$btn-bg};
|
||||
--gitako-btn-border: #{variables.$btn-border};
|
||||
--gitako-btn-shadow: #{variables.$btn-shadow};
|
||||
--gitako-btn-inset-shadow: #{variables.$btn-inset-shadow};
|
||||
--gitako-btn-hover-bg: #{variables.$btn-hover-bg};
|
||||
--gitako-btn-hover-border: #{variables.$btn-hover-border};
|
||||
--gitako-btn-selected-bg: #{variables.$btn-selected-bg};
|
||||
--gitako-btn-focus-bg: #{variables.$btn-focus-bg};
|
||||
--gitako-btn-focus-border: #{variables.$btn-focus-border};
|
||||
--gitako-btn-focus-shadow: #{variables.$btn-focus-shadow};
|
||||
--gitako-btn-shadow-active: #{variables.$btn-shadow-active};
|
||||
--gitako-btn-shadow-input-focus: #{variables.$btn-shadow-input-focus};
|
||||
--gitako-btn-primary-text: #{variables.$btn-primary-text};
|
||||
--gitako-btn-primary-bg: #{variables.$btn-primary-bg};
|
||||
--gitako-btn-primary-border: #{variables.$btn-primary-border};
|
||||
--gitako-btn-primary-shadow: #{variables.$btn-primary-shadow};
|
||||
--gitako-btn-primary-inset-shadow: #{variables.$btn-primary-inset-shadow};
|
||||
--gitako-btn-primary-hover-bg: #{variables.$btn-primary-hover-bg};
|
||||
--gitako-btn-primary-hover-border: #{variables.$btn-primary-hover-border};
|
||||
--gitako-btn-primary-selected-bg: #{variables.$btn-primary-selected-bg};
|
||||
--gitako-btn-primary-selected-shadow: #{variables.$btn-primary-selected-shadow};
|
||||
--gitako-btn-primary-disabled-text: #{variables.$btn-primary-disabled-text};
|
||||
--gitako-btn-primary-disabled-bg: #{variables.$btn-primary-disabled-bg};
|
||||
--gitako-btn-primary-disabled-border: #{variables.$btn-primary-disabled-border};
|
||||
--gitako-btn-primary-focus-bg: #{variables.$btn-primary-focus-bg};
|
||||
--gitako-btn-primary-focus-border: #{variables.$btn-primary-focus-border};
|
||||
--gitako-btn-primary-focus-shadow: #{variables.$btn-primary-focus-shadow};
|
||||
--gitako-btn-primary-icon: #{variables.$btn-primary-icon};
|
||||
--gitako-btn-primary-counter-bg: #{variables.$btn-primary-counter-bg};
|
||||
--gitako-btn-outline-text: #{variables.$btn-outline-text};
|
||||
--gitako-btn-outline-hover-text: #{variables.$btn-outline-hover-text};
|
||||
--gitako-btn-outline-hover-bg: #{variables.$btn-outline-hover-bg};
|
||||
--gitako-btn-outline-hover-border: #{variables.$btn-outline-hover-border};
|
||||
--gitako-btn-outline-hover-shadow: #{variables.$btn-outline-hover-shadow};
|
||||
--gitako-btn-outline-hover-inset-shadow: #{variables.$btn-outline-hover-inset-shadow};
|
||||
--gitako-btn-outline-hover-counter-bg: #{variables.$btn-outline-hover-counter-bg};
|
||||
--gitako-btn-outline-selected-text: #{variables.$btn-outline-selected-text};
|
||||
--gitako-btn-outline-selected-bg: #{variables.$btn-outline-selected-bg};
|
||||
--gitako-btn-outline-selected-border: #{variables.$btn-outline-selected-border};
|
||||
--gitako-btn-outline-selected-shadow: #{variables.$btn-outline-selected-shadow};
|
||||
--gitako-btn-outline-disabled-text: #{variables.$btn-outline-disabled-text};
|
||||
--gitako-btn-outline-disabled-bg: #{variables.$btn-outline-disabled-bg};
|
||||
--gitako-btn-outline-disabled-counter-bg: #{variables.$btn-outline-disabled-counter-bg};
|
||||
--gitako-btn-outline-focus-border: #{variables.$btn-outline-focus-border};
|
||||
--gitako-btn-outline-focus-shadow: #{variables.$btn-outline-focus-shadow};
|
||||
--gitako-btn-outline-counter-bg: #{variables.$btn-outline-counter-bg};
|
||||
--gitako-btn-danger-text: #{variables.$btn-danger-text};
|
||||
--gitako-btn-danger-hover-text: #{variables.$btn-danger-hover-text};
|
||||
--gitako-btn-danger-hover-bg: #{variables.$btn-danger-hover-bg};
|
||||
--gitako-btn-danger-hover-border: #{variables.$btn-danger-hover-border};
|
||||
--gitako-btn-danger-hover-shadow: #{variables.$btn-danger-hover-shadow};
|
||||
--gitako-btn-danger-hover-inset-shadow: #{variables.$btn-danger-hover-inset-shadow};
|
||||
--gitako-btn-danger-hover-counter-bg: #{variables.$btn-danger-hover-counter-bg};
|
||||
--gitako-btn-danger-selected-text: #{variables.$btn-danger-selected-text};
|
||||
--gitako-btn-danger-selected-bg: #{variables.$btn-danger-selected-bg};
|
||||
--gitako-btn-danger-selected-border: #{variables.$btn-danger-selected-border};
|
||||
--gitako-btn-danger-selected-shadow: #{variables.$btn-danger-selected-shadow};
|
||||
--gitako-btn-danger-disabled-text: #{variables.$btn-danger-disabled-text};
|
||||
--gitako-btn-danger-disabled-bg: #{variables.$btn-danger-disabled-bg};
|
||||
--gitako-btn-danger-disabled-counter-bg: #{variables.$btn-danger-disabled-counter-bg};
|
||||
--gitako-btn-danger-focus-border: #{variables.$btn-danger-focus-border};
|
||||
--gitako-btn-danger-focus-shadow: #{variables.$btn-danger-focus-shadow};
|
||||
--gitako-btn-danger-counter-bg: #{variables.$btn-danger-counter-bg};
|
||||
--gitako-btn-counter-bg: #{variables.$btn-counter-bg};
|
||||
--gitako-counter-text: #{variables.$counter-text};
|
||||
--gitako-counter-bg: #{variables.$counter-bg};
|
||||
--gitako-counter-primary-text: #{variables.$counter-primary-text};
|
||||
--gitako-counter-primary-bg: #{variables.$counter-primary-bg};
|
||||
--gitako-counter-secondary-text: #{variables.$counter-secondary-text};
|
||||
--gitako-dropdown-shadow: #{variables.$dropdown-shadow};
|
||||
--gitako-label-border: #{variables.$label-border};
|
||||
--gitako-label-primary-text: #{variables.$label-primary-text};
|
||||
--gitako-label-primary-border: #{variables.$label-primary-border};
|
||||
--gitako-label-secondary-text: #{variables.$label-secondary-text};
|
||||
--gitako-label-secondary-border: #{variables.$label-secondary-border};
|
||||
--gitako-label-info-text: #{variables.$label-info-text};
|
||||
--gitako-label-info-border: #{variables.$label-info-border};
|
||||
--gitako-label-success-text: #{variables.$label-success-text};
|
||||
--gitako-label-success-border: #{variables.$label-success-border};
|
||||
--gitako-label-warning-text: #{variables.$label-warning-text};
|
||||
--gitako-label-warning-border: #{variables.$label-warning-border};
|
||||
--gitako-label-danger-text: #{variables.$label-danger-text};
|
||||
--gitako-label-danger-border: #{variables.$label-danger-border};
|
||||
--gitako-label-orange-text: #{variables.$label-orange-text};
|
||||
--gitako-label-orange-border: #{variables.$label-orange-border};
|
||||
--gitako-input-bg: #{variables.$input-bg};
|
||||
--gitako-input-contrast-bg: #{variables.$input-contrast-bg};
|
||||
--gitako-input-border: #{variables.$input-border};
|
||||
--gitako-input-shadow: #{variables.$input-shadow};
|
||||
--gitako-input-disabled-bg: #{variables.$input-disabled-bg};
|
||||
--gitako-input-disabled-border: #{variables.$input-disabled-border};
|
||||
--gitako-input-warning-border: #{variables.$input-warning-border};
|
||||
--gitako-input-error-border: #{variables.$input-error-border};
|
||||
--gitako-input-tooltip-success-text: #{variables.$input-tooltip-success-text};
|
||||
--gitako-input-tooltip-success-bg: #{variables.$input-tooltip-success-bg};
|
||||
--gitako-input-tooltip-success-border: #{variables.$input-tooltip-success-border};
|
||||
--gitako-input-tooltip-warning-text: #{variables.$input-tooltip-warning-text};
|
||||
--gitako-input-tooltip-warning-bg: #{variables.$input-tooltip-warning-bg};
|
||||
--gitako-input-tooltip-warning-border: #{variables.$input-tooltip-warning-border};
|
||||
--gitako-input-tooltip-error-text: #{variables.$input-tooltip-error-text};
|
||||
--gitako-input-tooltip-error-bg: #{variables.$input-tooltip-error-bg};
|
||||
--gitako-input-tooltip-error-border: #{variables.$input-tooltip-error-border};
|
||||
--gitako-avatar-bg: #{variables.$avatar-bg};
|
||||
--gitako-avatar-border: #{variables.$avatar-border};
|
||||
--gitako-avatar-stack-fade: #{variables.$avatar-stack-fade};
|
||||
--gitako-avatar-stack-fade-more: #{variables.$avatar-stack-fade-more};
|
||||
--gitako-avatar-child-shadow: #{variables.$avatar-child-shadow};
|
||||
--gitako-toast-text: #{variables.$toast-text};
|
||||
--gitako-toast-bg: #{variables.$toast-bg};
|
||||
--gitako-toast-border: #{variables.$toast-border};
|
||||
--gitako-toast-shadow: #{variables.$toast-shadow};
|
||||
--gitako-toast-icon: #{variables.$toast-icon};
|
||||
--gitako-toast-icon-bg: #{variables.$toast-icon-bg};
|
||||
--gitako-toast-icon-border: #{variables.$toast-icon-border};
|
||||
--gitako-toast-success-text: #{variables.$toast-success-text};
|
||||
--gitako-toast-success-border: #{variables.$toast-success-border};
|
||||
--gitako-toast-success-icon: #{variables.$toast-success-icon};
|
||||
--gitako-toast-success-icon-bg: #{variables.$toast-success-icon-bg};
|
||||
--gitako-toast-success-icon-border: #{variables.$toast-success-icon-border};
|
||||
--gitako-toast-warning-text: #{variables.$toast-warning-text};
|
||||
--gitako-toast-warning-border: #{variables.$toast-warning-border};
|
||||
--gitako-toast-warning-icon: #{variables.$toast-warning-icon};
|
||||
--gitako-toast-warning-icon-bg: #{variables.$toast-warning-icon-bg};
|
||||
--gitako-toast-warning-icon-border: #{variables.$toast-warning-icon-border};
|
||||
--gitako-toast-danger-text: #{variables.$toast-danger-text};
|
||||
--gitako-toast-danger-border: #{variables.$toast-danger-border};
|
||||
--gitako-toast-danger-icon: #{variables.$toast-danger-icon};
|
||||
--gitako-toast-danger-icon-bg: #{variables.$toast-danger-icon-bg};
|
||||
--gitako-toast-danger-icon-border: #{variables.$toast-danger-icon-border};
|
||||
--gitako-toast-loading-text: #{variables.$toast-loading-text};
|
||||
--gitako-toast-loading-border: #{variables.$toast-loading-border};
|
||||
--gitako-toast-loading-icon: #{variables.$toast-loading-icon};
|
||||
--gitako-toast-loading-icon-bg: #{variables.$toast-loading-icon-bg};
|
||||
--gitako-toast-loading-icon-border: #{variables.$toast-loading-icon-border};
|
||||
--gitako-timeline-text: #{variables.$timeline-text};
|
||||
--gitako-timeline-badge-bg: #{variables.$timeline-badge-bg};
|
||||
--gitako-timeline-target-badge-border: #{variables.$timeline-target-badge-border};
|
||||
--gitako-timeline-target-badge-shadow: #{variables.$timeline-target-badge-shadow};
|
||||
--gitako-select-menu-border-secondary: #{variables.$select-menu-border-secondary};
|
||||
--gitako-select-menu-shadow: #{variables.$select-menu-shadow};
|
||||
--gitako-select-menu-backdrop-bg: #{variables.$select-menu-backdrop-bg};
|
||||
--gitako-select-menu-backdrop-border: #{variables.$select-menu-backdrop-border};
|
||||
--gitako-select-menu-tap-highlight: #{variables.$select-menu-tap-highlight};
|
||||
--gitako-select-menu-tap-focus-bg: #{variables.$select-menu-tap-focus-bg};
|
||||
--gitako-box-blue-border: #{variables.$box-blue-border};
|
||||
--gitako-box-row-yellow-bg: #{variables.$box-row-yellow-bg};
|
||||
--gitako-box-row-blue-bg: #{variables.$box-row-blue-bg};
|
||||
--gitako-box-header-blue-bg: #{variables.$box-header-blue-bg};
|
||||
--gitako-box-header-blue-border: #{variables.$box-header-blue-border};
|
||||
--gitako-box-border-info: #{variables.$box-border-info};
|
||||
--gitako-box-bg-info: #{variables.$box-bg-info};
|
||||
--gitako-box-border-warning: #{variables.$box-border-warning};
|
||||
--gitako-box-bg-warning: #{variables.$box-bg-warning};
|
||||
--gitako-branch-name-text: #{variables.$branch-name-text};
|
||||
--gitako-branch-name-icon: #{variables.$branch-name-icon};
|
||||
--gitako-branch-name-bg: #{variables.$branch-name-bg};
|
||||
--gitako-branch-name-link-text: #{variables.$branch-name-link-text};
|
||||
--gitako-branch-name-link-icon: #{variables.$branch-name-link-icon};
|
||||
--gitako-branch-name-link-bg: #{variables.$branch-name-link-bg};
|
||||
--gitako-markdown-code-bg: #{variables.$markdown-code-bg};
|
||||
--gitako-markdown-frame-border: #{variables.$markdown-frame-border};
|
||||
--gitako-markdown-blockquote-border: #{variables.$markdown-blockquote-border};
|
||||
--gitako-markdown-table-border: #{variables.$markdown-table-border};
|
||||
--gitako-markdown-table-tr-border: #{variables.$markdown-table-tr-border};
|
||||
--gitako-menu-heading-text: #{variables.$menu-heading-text};
|
||||
--gitako-menu-border-active: #{variables.$menu-border-active};
|
||||
--gitako-menu-bg-active: #{variables.$menu-bg-active};
|
||||
--gitako-sidenav-selected-bg: #{variables.$sidenav-selected-bg};
|
||||
--gitako-sidenav-border-active: #{variables.$sidenav-border-active};
|
||||
--gitako-header-text: #{variables.$header-text};
|
||||
--gitako-header-bg: #{variables.$header-bg};
|
||||
--gitako-header-logo: #{variables.$header-logo};
|
||||
--gitako-filter-item-bar-bg: #{variables.$filter-item-bar-bg};
|
||||
--gitako-hidden-text-expander-bg: #{variables.$hidden-text-expander-bg};
|
||||
--gitako-hidden-text-expander-bg-hover: #{variables.$hidden-text-expander-bg-hover};
|
||||
--gitako-drag-and-drop-border: #{variables.$drag-and-drop-border};
|
||||
--gitako-upload-enabled-border: #{variables.$upload-enabled-border};
|
||||
--gitako-upload-enabled-border-focused: #{variables.$upload-enabled-border-focused};
|
||||
--gitako-previewable-comment-form-border: #{variables.$previewable-comment-form-border};
|
||||
--gitako-underlinenav-border: #{variables.$underlinenav-border};
|
||||
--gitako-underlinenav-border-hover: #{variables.$underlinenav-border-hover};
|
||||
--gitako-underlinenav-border-active: #{variables.$underlinenav-border-active};
|
||||
--gitako-underlinenav-text: #{variables.$underlinenav-text};
|
||||
--gitako-underlinenav-text-hover: #{variables.$underlinenav-text-hover};
|
||||
--gitako-underlinenav-text-active: #{variables.$underlinenav-text-active};
|
||||
--gitako-underlinenav-icon: #{variables.$underlinenav-icon};
|
||||
--gitako-underlinenav-icon-hover: #{variables.$underlinenav-icon-hover};
|
||||
--gitako-underlinenav-icon-active: #{variables.$underlinenav-icon-active};
|
||||
--gitako-underlinenav-counter-text: #{variables.$underlinenav-counter-text};
|
||||
--gitako-verified-badge-text: #{variables.$verified-badge-text};
|
||||
--gitako-verified-badge-bg: #{variables.$verified-badge-bg};
|
||||
--gitako-verified-badge-border: #{variables.$verified-badge-border};
|
||||
--gitako-social-count-bg: #{variables.$social-count-bg};
|
||||
--gitako-tooltip-text: #{variables.$tooltip-text};
|
||||
--gitako-tooltip-bg: #{variables.$tooltip-bg};
|
||||
--gitako-header-search-bg: #{variables.$header-search-bg};
|
||||
--gitako-header-search-border: #{variables.$header-search-border};
|
||||
--gitako-search-keyword-hl: #{variables.$search-keyword-hl};
|
||||
--gitako-diffstat-neutral-bg: #{variables.$diffstat-neutral-bg};
|
||||
--gitako-diffstat-neutral-border: #{variables.$diffstat-neutral-border};
|
||||
--gitako-diffstat-deletion-bg: #{variables.$diffstat-deletion-bg};
|
||||
--gitako-diffstat-deletion-border: #{variables.$diffstat-deletion-border};
|
||||
--gitako-diffstat-addition-bg: #{variables.$diffstat-addition-bg};
|
||||
--gitako-diffstat-addition-border: #{variables.$diffstat-addition-border};
|
||||
--gitako-files-explorer-icon: #{variables.$files-explorer-icon};
|
||||
--gitako-hl-author-bg: #{variables.$hl-author-bg};
|
||||
--gitako-hl-author-border: #{variables.$hl-author-border};
|
||||
--gitako-logo-subdued: #{variables.$logo-subdued};
|
||||
--gitako-discussion-border: #{variables.$discussion-border};
|
||||
--gitako-discussion-bg-success: #{variables.$discussion-bg-success};
|
||||
--gitako-actions-workflow-table-sticky-bg: #{variables.$actions-workflow-table-sticky-bg};
|
||||
--gitako-repo-language-color-border: #{variables.$repo-language-color-border};
|
||||
--gitako-code-selection-bg: #{variables.$code-selection-bg};
|
||||
--gitako-blob-line-highlight-bg: #{variables.$blob-line-highlight-bg};
|
||||
--gitako-blob-line-highlight-border: #{variables.$blob-line-highlight-border};
|
||||
--gitako-diff-addition-text: #{variables.$diff-addition-text};
|
||||
--gitako-diff-addition-bg: #{variables.$diff-addition-bg};
|
||||
--gitako-diff-addition-border: #{variables.$diff-addition-border};
|
||||
--gitako-diff-deletion-text: #{variables.$diff-deletion-text};
|
||||
--gitako-diff-deletion-bg: #{variables.$diff-deletion-bg};
|
||||
--gitako-diff-deletion-border: #{variables.$diff-deletion-border};
|
||||
--gitako-diff-change-text: #{variables.$diff-change-text};
|
||||
--gitako-diff-change-bg: #{variables.$diff-change-bg};
|
||||
--gitako-diff-change-border: #{variables.$diff-change-border};
|
||||
--gitako-diff-blob-num-text: #{variables.$diff-blob-num-text};
|
||||
--gitako-diff-blob-num-hover-text: #{variables.$diff-blob-num-hover-text};
|
||||
--gitako-diff-blob-addition-num-text: #{variables.$diff-blob-addition-num-text};
|
||||
--gitako-diff-blob-addition-num-hover-text: #{variables.$diff-blob-addition-num-hover-text};
|
||||
--gitako-diff-blob-addition-num-bg: #{variables.$diff-blob-addition-num-bg};
|
||||
--gitako-diff-blob-addition-line-bg: #{variables.$diff-blob-addition-line-bg};
|
||||
--gitako-diff-blob-addition-word-bg: #{variables.$diff-blob-addition-word-bg};
|
||||
--gitako-diff-blob-deletion-num-text: #{variables.$diff-blob-deletion-num-text};
|
||||
--gitako-diff-blob-deletion-num-hover-text: #{variables.$diff-blob-deletion-num-hover-text};
|
||||
--gitako-diff-blob-deletion-num-bg: #{variables.$diff-blob-deletion-num-bg};
|
||||
--gitako-diff-blob-deletion-line-bg: #{variables.$diff-blob-deletion-line-bg};
|
||||
--gitako-diff-blob-deletion-word-bg: #{variables.$diff-blob-deletion-word-bg};
|
||||
--gitako-diff-blob-hunk-text: #{variables.$diff-blob-hunk-text};
|
||||
--gitako-diff-blob-hunk-num-bg: #{variables.$diff-blob-hunk-num-bg};
|
||||
--gitako-diff-blob-hunk-line-bg: #{variables.$diff-blob-hunk-line-bg};
|
||||
--gitako-diff-blob-empty-block-bg: #{variables.$diff-blob-empty-block-bg};
|
||||
--gitako-diff-blob-selected-line-highlight-bg: #{variables.$diff-blob-selected-line-highlight-bg};
|
||||
--gitako-diff-blob-selected-line-highlight-border: #{variables.$diff-blob-selected-line-highlight-border};
|
||||
--gitako-diff-blob-selected-line-highlight-mix-blend-mode: #{variables.$diff-blob-selected-line-highlight-mix-blend-mode};
|
||||
--gitako-diff-blob-expander-icon: #{variables.$diff-blob-expander-icon};
|
||||
--gitako-diff-blob-expander-hover-icon: #{variables.$diff-blob-expander-hover-icon};
|
||||
--gitako-diff-blob-expander-hover-bg: #{variables.$diff-blob-expander-hover-bg};
|
||||
--gitako-diff-blob-comment-button-icon: #{variables.$diff-blob-comment-button-icon};
|
||||
--gitako-diff-blob-comment-button-bg: #{variables.$diff-blob-comment-button-bg};
|
||||
--gitako-diff-blob-comment-button-gradient-bg: #{variables.$diff-blob-comment-button-gradient-bg};
|
||||
--gitako-global-nav-logo: #{variables.$global-nav-logo};
|
||||
--gitako-global-nav-bg: #{variables.$global-nav-bg};
|
||||
--gitako-global-nav-text: #{variables.$global-nav-text};
|
||||
--gitako-global-nav-icon: #{variables.$global-nav-icon};
|
||||
--gitako-global-nav-input-bg: #{variables.$global-nav-input-bg};
|
||||
--gitako-global-nav-input-border: #{variables.$global-nav-input-border};
|
||||
--gitako-global-nav-input-icon: #{variables.$global-nav-input-icon};
|
||||
--gitako-global-nav-input-placeholder: #{variables.$global-nav-input-placeholder};
|
||||
--gitako-calendar-graph-day-bg: #{variables.$calendar-graph-day-bg};
|
||||
--gitako-calendar-graph-day-border: #{variables.$calendar-graph-day-border};
|
||||
--gitako-calendar-graph-day-l1-bg: #{variables.$calendar-graph-day-l1-bg};
|
||||
--gitako-calendar-graph-day-l2-bg: #{variables.$calendar-graph-day-l2-bg};
|
||||
--gitako-calendar-graph-day-l3-bg: #{variables.$calendar-graph-day-l3-bg};
|
||||
--gitako-calendar-graph-day-l4-bg: #{variables.$calendar-graph-day-l4-bg};
|
||||
--gitako-calendar-graph-day-l4-border: #{variables.$calendar-graph-day-l4-border};
|
||||
--gitako-calendar-graph-day-l3-border: #{variables.$calendar-graph-day-l3-border};
|
||||
--gitako-calendar-graph-day-l2-border: #{variables.$calendar-graph-day-l2-border};
|
||||
--gitako-calendar-graph-day-l1-border: #{variables.$calendar-graph-day-l1-border};
|
||||
--gitako-footer-invertocat-octicon: #{variables.$footer-invertocat-octicon};
|
||||
--gitako-footer-invertocat-octicon-hover: #{variables.$footer-invertocat-octicon-hover};
|
||||
--gitako-pr-state-draft-text: #{variables.$pr-state-draft-text};
|
||||
--gitako-pr-state-draft-bg: #{variables.$pr-state-draft-bg};
|
||||
--gitako-pr-state-draft-border: #{variables.$pr-state-draft-border};
|
||||
--gitako-pr-state-open-text: #{variables.$pr-state-open-text};
|
||||
--gitako-pr-state-open-bg: #{variables.$pr-state-open-bg};
|
||||
--gitako-pr-state-open-border: #{variables.$pr-state-open-border};
|
||||
--gitako-pr-state-merged-text: #{variables.$pr-state-merged-text};
|
||||
--gitako-pr-state-merged-bg: #{variables.$pr-state-merged-bg};
|
||||
--gitako-pr-state-merged-border: #{variables.$pr-state-merged-border};
|
||||
--gitako-pr-state-closed-text: #{variables.$pr-state-closed-text};
|
||||
--gitako-pr-state-closed-bg: #{variables.$pr-state-closed-bg};
|
||||
--gitako-pr-state-closed-border: #{variables.$pr-state-closed-border};
|
||||
--gitako-topic-tag-text: #{variables.$topic-tag-text};
|
||||
--gitako-topic-tag-bg: #{variables.$topic-tag-bg};
|
||||
--gitako-topic-tag-hover-bg: #{variables.$topic-tag-hover-bg};
|
||||
--gitako-topic-tag-active-bg: #{variables.$topic-tag-active-bg};
|
||||
--gitako-merge-box-success-icon-bg: #{variables.$merge-box-success-icon-bg};
|
||||
--gitako-merge-box-success-icon-text: #{variables.$merge-box-success-icon-text};
|
||||
--gitako-merge-box-success-icon-border: #{variables.$merge-box-success-icon-border};
|
||||
--gitako-merge-box-success-indicator-bg: #{variables.$merge-box-success-indicator-bg};
|
||||
--gitako-merge-box-success-indicator-border: #{variables.$merge-box-success-indicator-border};
|
||||
--gitako-merge-box-merged-icon-bg: #{variables.$merge-box-merged-icon-bg};
|
||||
--gitako-merge-box-merged-icon-text: #{variables.$merge-box-merged-icon-text};
|
||||
--gitako-merge-box-merged-icon-border: #{variables.$merge-box-merged-icon-border};
|
||||
--gitako-merge-box-merged-box-border: #{variables.$merge-box-merged-box-border};
|
||||
--gitako-merge-box-neutral-icon-bg: #{variables.$merge-box-neutral-icon-bg};
|
||||
--gitako-merge-box-neutral-icon-text: #{variables.$merge-box-neutral-icon-text};
|
||||
--gitako-merge-box-neutral-icon-border: #{variables.$merge-box-neutral-icon-border};
|
||||
--gitako-merge-box-neutral-indicator-bg: #{variables.$merge-box-neutral-indicator-bg};
|
||||
--gitako-merge-box-neutral-indicator-border: #{variables.$merge-box-neutral-indicator-border};
|
||||
--gitako-merge-box-warning-icon-bg: #{variables.$merge-box-warning-icon-bg};
|
||||
--gitako-merge-box-warning-icon-text: #{variables.$merge-box-warning-icon-text};
|
||||
--gitako-merge-box-warning-icon-border: #{variables.$merge-box-warning-icon-border};
|
||||
--gitako-merge-box-warning-box-border: #{variables.$merge-box-warning-box-border};
|
||||
--gitako-merge-box-warning-merge-highlight: #{variables.$merge-box-warning-merge-highlight};
|
||||
--gitako-merge-box-error-icon-bg: #{variables.$merge-box-error-icon-bg};
|
||||
--gitako-merge-box-error-icon-text: #{variables.$merge-box-error-icon-text};
|
||||
--gitako-merge-box-error-icon-border: #{variables.$merge-box-error-icon-border};
|
||||
--gitako-merge-box-error-indicator-bg: #{variables.$merge-box-error-indicator-bg};
|
||||
--gitako-merge-box-error-indicator-border: #{variables.$merge-box-error-indicator-border};
|
||||
--gitako-project-card-bg: #{variables.$project-card-bg};
|
||||
--gitako-project-header-bg: #{variables.$project-header-bg};
|
||||
--gitako-project-sidebar-bg: #{variables.$project-sidebar-bg};
|
||||
--gitako-project-gradient-in: #{variables.$project-gradient-in};
|
||||
--gitako-project-gradient-out: #{variables.$project-gradient-out};
|
||||
--gitako-marketing-icon-primary: #{variables.$marketing-icon-primary};
|
||||
--gitako-marketing-icon-secondary: #{variables.$marketing-icon-secondary};
|
||||
--gitako-prettylights-syntax-comment: #{variables.$prettylights-syntax-comment};
|
||||
--gitako-prettylights-syntax-constant: #{variables.$prettylights-syntax-constant};
|
||||
--gitako-prettylights-syntax-entity: #{variables.$prettylights-syntax-entity};
|
||||
--gitako-prettylights-syntax-storage-modifier-import: #{variables.$prettylights-syntax-storage-modifier-import};
|
||||
--gitako-prettylights-syntax-entity-tag: #{variables.$prettylights-syntax-entity-tag};
|
||||
--gitako-prettylights-syntax-keyword: #{variables.$prettylights-syntax-keyword};
|
||||
--gitako-prettylights-syntax-string: #{variables.$prettylights-syntax-string};
|
||||
--gitako-prettylights-syntax-variable: #{variables.$prettylights-syntax-variable};
|
||||
--gitako-prettylights-syntax-brackethighlighter-unmatched: #{variables.$prettylights-syntax-brackethighlighter-unmatched};
|
||||
--gitako-prettylights-syntax-invalid-illegal-text: #{variables.$prettylights-syntax-invalid-illegal-text};
|
||||
--gitako-prettylights-syntax-invalid-illegal-bg: #{variables.$prettylights-syntax-invalid-illegal-bg};
|
||||
--gitako-prettylights-syntax-carriage-return-text: #{variables.$prettylights-syntax-carriage-return-text};
|
||||
--gitako-prettylights-syntax-carriage-return-bg: #{variables.$prettylights-syntax-carriage-return-bg};
|
||||
--gitako-prettylights-syntax-string-regexp: #{variables.$prettylights-syntax-string-regexp};
|
||||
--gitako-prettylights-syntax-markup-list: #{variables.$prettylights-syntax-markup-list};
|
||||
--gitako-prettylights-syntax-markup-heading: #{variables.$prettylights-syntax-markup-heading};
|
||||
--gitako-prettylights-syntax-markup-italic: #{variables.$prettylights-syntax-markup-italic};
|
||||
--gitako-prettylights-syntax-markup-bold: #{variables.$prettylights-syntax-markup-bold};
|
||||
--gitako-prettylights-syntax-markup-deleted-text: #{variables.$prettylights-syntax-markup-deleted-text};
|
||||
--gitako-prettylights-syntax-markup-deleted-bg: #{variables.$prettylights-syntax-markup-deleted-bg};
|
||||
--gitako-prettylights-syntax-markup-inserted-text: #{variables.$prettylights-syntax-markup-inserted-text};
|
||||
--gitako-prettylights-syntax-markup-inserted-bg: #{variables.$prettylights-syntax-markup-inserted-bg};
|
||||
--gitako-prettylights-syntax-markup-changed-text: #{variables.$prettylights-syntax-markup-changed-text};
|
||||
--gitako-prettylights-syntax-markup-changed-bg: #{variables.$prettylights-syntax-markup-changed-bg};
|
||||
--gitako-prettylights-syntax-markup-ignored-text: #{variables.$prettylights-syntax-markup-ignored-text};
|
||||
--gitako-prettylights-syntax-markup-ignored-bg: #{variables.$prettylights-syntax-markup-ignored-bg};
|
||||
--gitako-prettylights-syntax-meta-diff-range: #{variables.$prettylights-syntax-meta-diff-range};
|
||||
--gitako-prettylights-syntax-brackethighlighter-angle: #{variables.$prettylights-syntax-brackethighlighter-angle};
|
||||
--gitako-prettylights-syntax-sublimelinter-gutter-mark: #{variables.$prettylights-syntax-sublimelinter-gutter-mark};
|
||||
--gitako-prettylights-syntax-constant-other-reference-link: #{variables.$prettylights-syntax-constant-other-reference-link};
|
||||
--gitako-codemirror-text: #{variables.$codemirror-text};
|
||||
--gitako-codemirror-bg: #{variables.$codemirror-bg};
|
||||
--gitako-codemirror-gutters-bg: #{variables.$codemirror-gutters-bg};
|
||||
--gitako-codemirror-guttermarker-text: #{variables.$codemirror-guttermarker-text};
|
||||
--gitako-codemirror-guttermarker-subtle-text: #{variables.$codemirror-guttermarker-subtle-text};
|
||||
--gitako-codemirror-linenumber-text: #{variables.$codemirror-linenumber-text};
|
||||
--gitako-codemirror-cursor: #{variables.$codemirror-cursor};
|
||||
--gitako-codemirror-selection-bg: #{variables.$codemirror-selection-bg};
|
||||
--gitako-codemirror-activeline-bg: #{variables.$codemirror-activeline-bg};
|
||||
--gitako-codemirror-matchingbracket-text: #{variables.$codemirror-matchingbracket-text};
|
||||
--gitako-codemirror-lines-bg: #{variables.$codemirror-lines-bg};
|
||||
--gitako-codemirror-syntax-comment: #{variables.$codemirror-syntax-comment};
|
||||
--gitako-codemirror-syntax-constant: #{variables.$codemirror-syntax-constant};
|
||||
--gitako-codemirror-syntax-entity: #{variables.$codemirror-syntax-entity};
|
||||
--gitako-codemirror-syntax-keyword: #{variables.$codemirror-syntax-keyword};
|
||||
--gitako-codemirror-syntax-storage: #{variables.$codemirror-syntax-storage};
|
||||
--gitako-codemirror-syntax-string: #{variables.$codemirror-syntax-string};
|
||||
--gitako-codemirror-syntax-support: #{variables.$codemirror-syntax-support};
|
||||
--gitako-codemirror-syntax-variable: #{variables.$codemirror-syntax-variable};
|
||||
--gitako-ansi-black: #{variables.$ansi-black};
|
||||
--gitako-ansi-black-bright: #{variables.$ansi-black-bright};
|
||||
--gitako-ansi-white: #{variables.$ansi-white};
|
||||
--gitako-ansi-white-bright: #{variables.$ansi-white-bright};
|
||||
--gitako-ansi-gray: #{variables.$ansi-gray};
|
||||
--gitako-ansi-red: #{variables.$ansi-red};
|
||||
--gitako-ansi-red-bright: #{variables.$ansi-red-bright};
|
||||
--gitako-ansi-green: #{variables.$ansi-green};
|
||||
--gitako-ansi-green-bright: #{variables.$ansi-green-bright};
|
||||
--gitako-ansi-yellow: #{variables.$ansi-yellow};
|
||||
--gitako-ansi-yellow-bright: #{variables.$ansi-yellow-bright};
|
||||
--gitako-ansi-blue: #{variables.$ansi-blue};
|
||||
--gitako-ansi-blue-bright: #{variables.$ansi-blue-bright};
|
||||
--gitako-ansi-magenta: #{variables.$ansi-magenta};
|
||||
--gitako-ansi-magenta-bright: #{variables.$ansi-magenta-bright};
|
||||
--gitako-ansi-cyan: #{variables.$ansi-cyan};
|
||||
--gitako-ansi-cyan-bright: #{variables.$ansi-cyan-bright};
|
||||
}
|
||||
File diff suppressed because it is too large
Load diff
64
src/styles/themes.scss
Normal file
64
src/styles/themes.scss
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
@use './light/variables.scss' as light;
|
||||
@use './dark/variables.scss' as dark;
|
||||
@use './darkDimmed/variables.scss' as darkDimmed;
|
||||
|
||||
@mixin setVariables($variables) {
|
||||
@each $name, $value in $variables {
|
||||
--gitako-#{$name}: #{$value};
|
||||
}
|
||||
}
|
||||
|
||||
// Following rules are organized according to common variables to reduce output CSS size
|
||||
:root {
|
||||
// default, e.g. when not login
|
||||
@include setVariables(light.$variables);
|
||||
}
|
||||
|
||||
:root {
|
||||
&[data-color-mode='light'][data-light-theme='light'],
|
||||
&[data-color-mode='dark'][data-dark-theme='light'] {
|
||||
@include setVariables(light.$variables);
|
||||
}
|
||||
|
||||
&[data-color-mode='light'][data-light-theme='dark'],
|
||||
&[data-color-mode='dark'][data-dark-theme='dark'] {
|
||||
@include setVariables(dark.$variables);
|
||||
}
|
||||
|
||||
&[data-color-mode='light'][data-light-theme='dark_dimmed'],
|
||||
&[data-color-mode='dark'][data-dark-theme='dark_dimmed'] {
|
||||
@include setVariables(darkDimmed.$variables);
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: light) {
|
||||
:root[data-color-mode='auto'] {
|
||||
&[data-light-theme='light'] {
|
||||
@include setVariables(light.$variables);
|
||||
}
|
||||
|
||||
&[data-light-theme='dark'] {
|
||||
@include setVariables(dark.$variables);
|
||||
}
|
||||
|
||||
&[data-light-theme='dark_dimmed'] {
|
||||
@include setVariables(darkDimmed.$variables);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root[data-color-mode='auto'] {
|
||||
&[data-dark-theme='light'] {
|
||||
@include setVariables(light.$variables);
|
||||
}
|
||||
|
||||
&[data-dark-theme='dark'] {
|
||||
@include setVariables(dark.$variables);
|
||||
}
|
||||
|
||||
&[data-dark-theme='dark_dimmed'] {
|
||||
@include setVariables(darkDimmed.$variables);
|
||||
}
|
||||
}
|
||||
}
|
||||
91
src/utils/config/helper.ts
Normal file
91
src/utils/config/helper.ts
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
import { SearchMode } from 'components/searchModes'
|
||||
import { platform, platformName } from 'platforms'
|
||||
import { storageHelper } from 'utils/storageHelper'
|
||||
import { migrateConfig } from './migrations'
|
||||
|
||||
export type Config = {
|
||||
sideBarWidth: number
|
||||
shortcut: string | undefined
|
||||
accessToken: string | undefined
|
||||
compressSingletonFolder: boolean
|
||||
copyFileButton: boolean
|
||||
copySnippetButton: boolean
|
||||
intelligentToggle: boolean | null // `null` stands for intelligent, boolean for sidebar open state
|
||||
icons: 'rich' | 'dim' | 'native'
|
||||
toggleButtonVerticalDistance: number
|
||||
toggleButtonContent: 'logo' | 'octoface'
|
||||
recursiveToggleFolder: 'shift' | 'alt'
|
||||
searchMode: SearchMode
|
||||
sidebarToggleMode: 'persistent' | 'float'
|
||||
commentToggle: boolean
|
||||
codeFolding: boolean
|
||||
compactFileTree: boolean
|
||||
}
|
||||
|
||||
enum configKeys {
|
||||
sideBarWidth = 'sideBarWidth',
|
||||
shortcut = 'shortcut',
|
||||
accessToken = 'accessToken',
|
||||
compressSingletonFolder = 'compressSingletonFolder',
|
||||
copyFileButton = 'copyFileButton',
|
||||
copySnippetButton = 'copySnippetButton',
|
||||
intelligentToggle = 'intelligentToggle',
|
||||
icons = 'icons',
|
||||
toggleButtonVerticalDistance = 'toggleButtonVerticalDistance',
|
||||
toggleButtonContent = 'toggleButtonContent',
|
||||
recursiveToggleFolder = 'recursiveToggleFolder',
|
||||
searchMode = 'searchMode',
|
||||
sidebarToggleMode = 'sidebarToggleMode',
|
||||
commentToggle = 'commentToggle',
|
||||
codeFolding = 'codeFolding',
|
||||
compactFileTree = 'compactFileTree',
|
||||
}
|
||||
|
||||
export const defaultConfigs: Config = {
|
||||
sideBarWidth: 260,
|
||||
shortcut: undefined,
|
||||
accessToken: '',
|
||||
compressSingletonFolder: true,
|
||||
copyFileButton: true,
|
||||
copySnippetButton: !(platformName === 'GitHub' && !platform.isEnterprise()), // false when on github.com
|
||||
intelligentToggle: null,
|
||||
icons: 'rich',
|
||||
toggleButtonVerticalDistance: 124, // align with GitHub's navbar items
|
||||
toggleButtonContent: 'logo',
|
||||
recursiveToggleFolder: 'shift',
|
||||
searchMode: 'fuzzy',
|
||||
sidebarToggleMode: 'float',
|
||||
commentToggle: true,
|
||||
codeFolding: true,
|
||||
compactFileTree: false,
|
||||
}
|
||||
|
||||
const configKeyArray = Object.values(configKeys)
|
||||
|
||||
function applyDefaultConfigs(configs: Partial<Config>) {
|
||||
return configKeyArray.reduce((applied, key) => {
|
||||
Object.assign(applied, { [key]: key in configs ? configs[key] : defaultConfigs[key] })
|
||||
return applied
|
||||
}, {} as Config)
|
||||
}
|
||||
|
||||
export type VersionedConfig<SiteConfig> = Record<string, SiteConfig> & { configVersion: string }
|
||||
|
||||
// do NOT use platform name
|
||||
const platformStorageKey = `platform_` + window.location.host.toLowerCase()
|
||||
const prepareConfig = new Promise<void>(async resolve => {
|
||||
await migrateConfig()
|
||||
resolve()
|
||||
})
|
||||
|
||||
async function get(): Promise<Config> {
|
||||
await prepareConfig
|
||||
const config = await storageHelper.get<Record<string, Config>>([platformStorageKey])
|
||||
return applyDefaultConfigs(config?.[platformStorageKey] || {})
|
||||
}
|
||||
|
||||
async function set(config: Config) {
|
||||
return await storageHelper.set({ [platformStorageKey]: config })
|
||||
}
|
||||
|
||||
export const configHelper = { get, set }
|
||||
23
src/utils/config/migrations/1.0.1.ts
Normal file
23
src/utils/config/migrations/1.0.1.ts
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
import { storageHelper } from 'utils/storageHelper'
|
||||
import { Migration } from '.'
|
||||
import { Storage } from '../../storageHelper'
|
||||
|
||||
export const migration: Migration = {
|
||||
version: '1.0.1',
|
||||
async migrate(version) {
|
||||
const config: any | void = await storageHelper.get<Storage>([
|
||||
'configVersion',
|
||||
'sideBarWidth',
|
||||
'shortcut',
|
||||
'access_token',
|
||||
'compressSingletonFolder',
|
||||
'copyFileButton',
|
||||
'copySnippetButton',
|
||||
'intelligentToggle',
|
||||
'icons',
|
||||
])
|
||||
if (config && (!('configVersion' in config) || config.configVersion < version)) {
|
||||
await storageHelper.set({ platform_GitHub: config, configVersion: version })
|
||||
}
|
||||
},
|
||||
}
|
||||
28
src/utils/config/migrations/1.3.4.ts
Normal file
28
src/utils/config/migrations/1.3.4.ts
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
import { storageHelper } from 'utils/storageHelper'
|
||||
import { Migration } from '.'
|
||||
import { Storage } from '../../storageHelper'
|
||||
import { Config, VersionedConfig } from '../helper'
|
||||
|
||||
export const migration: Migration = {
|
||||
version: '1.3.4',
|
||||
async migrate(version) {
|
||||
const config: any | void = await storageHelper.get<VersionedConfig<Config> & Storage>([
|
||||
'configVersion',
|
||||
'platform_undefined',
|
||||
'platform_GitHub',
|
||||
'platform_github.com',
|
||||
])
|
||||
if (
|
||||
config &&
|
||||
'configVersion' in config &&
|
||||
config.configVersion < version &&
|
||||
(config.platform_GitHub || config.platform_undefined) &&
|
||||
!config['platform_github.com']
|
||||
) {
|
||||
await storageHelper.set({
|
||||
['platform_github.com']: config.platform_GitHub || config.platform_undefined,
|
||||
configVersion: version,
|
||||
})
|
||||
}
|
||||
},
|
||||
}
|
||||
34
src/utils/config/migrations/2.6.0.ts
Normal file
34
src/utils/config/migrations/2.6.0.ts
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
import { storageHelper } from 'utils/storageHelper'
|
||||
import { Migration, onConfigOutdated } from '.'
|
||||
|
||||
export const migration: Migration = {
|
||||
version: '2.6.0',
|
||||
async migrate(version) {
|
||||
type ConfigBeforeMigrate = {
|
||||
access_token?: string
|
||||
}
|
||||
type ConfigAfterMigrate = {
|
||||
accessToken?: string
|
||||
}
|
||||
|
||||
await onConfigOutdated(version, async configs => {
|
||||
for (const key of Object.keys(configs)) {
|
||||
if (
|
||||
typeof configs[key] === 'object' &&
|
||||
configs[key] !== null &&
|
||||
'access_token' in configs[key]
|
||||
) {
|
||||
const configBeforeMigrate: ConfigBeforeMigrate = configs[key]
|
||||
const { access_token: accessToken, ...rest } = configBeforeMigrate
|
||||
const configAfterMigrate: ConfigAfterMigrate = {
|
||||
...rest,
|
||||
accessToken,
|
||||
}
|
||||
await storageHelper.set({
|
||||
[key]: configAfterMigrate,
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
}
|
||||
33
src/utils/config/migrations/3.0.0.ts
Normal file
33
src/utils/config/migrations/3.0.0.ts
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
import { storageHelper } from 'utils/storageHelper'
|
||||
import { Migration, onConfigOutdated } from '.'
|
||||
|
||||
export const migration: Migration = {
|
||||
version: '3.0.0',
|
||||
async migrate(version) {
|
||||
// disable copy snippet button for github.com
|
||||
type ConfigBeforeMigrate = {
|
||||
copySnippetButton: boolean
|
||||
}
|
||||
type ConfigAfterMigrate = {
|
||||
copySnippetButton: boolean
|
||||
}
|
||||
|
||||
await onConfigOutdated(version, async configs => {
|
||||
const key = 'platform_github.com'
|
||||
const config = configs[key]
|
||||
if (typeof config === 'object' && config !== null && 'copySnippetButton' in config) {
|
||||
const configBeforeMigrate: ConfigBeforeMigrate = config
|
||||
const { copySnippetButton, ...rest } = configBeforeMigrate
|
||||
if (copySnippetButton) {
|
||||
const configAfterMigrate: ConfigAfterMigrate = {
|
||||
...rest,
|
||||
copySnippetButton: false,
|
||||
}
|
||||
await storageHelper.set({
|
||||
[key]: configAfterMigrate,
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
}
|
||||
32
src/utils/config/migrations/index.ts
Normal file
32
src/utils/config/migrations/index.ts
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
import { storageHelper } from 'utils/storageHelper'
|
||||
import { Storage } from '../../storageHelper'
|
||||
import { migration as v1v0v1 } from './1.0.1'
|
||||
import { migration as v1v3v4 } from './1.3.4'
|
||||
import { migration as v2v6v0 } from './2.6.0'
|
||||
import { migration as v3v0v0 } from './3.0.0'
|
||||
|
||||
export type Migration = {
|
||||
version: string
|
||||
migrate(version: Migration['version']): Async<void>
|
||||
}
|
||||
|
||||
export async function migrateConfig() {
|
||||
const migrations: Migration[] = [v1v0v1, v1v3v4, v2v6v0, v3v0v0]
|
||||
|
||||
for (const { version, migrate } of migrations) {
|
||||
await migrate(version)
|
||||
}
|
||||
}
|
||||
|
||||
export async function onConfigOutdated<T extends { [key: string]: any }>(
|
||||
configVersion: string,
|
||||
runIfOutdated: (config: T) => Async<void>,
|
||||
) {
|
||||
const config = await storageHelper.get<Storage>()
|
||||
|
||||
if (config && config.configVersion < configVersion) {
|
||||
const { configVersion: $configVersion, ...restConfig } = config
|
||||
await runIfOutdated(restConfig as T)
|
||||
await storageHelper.set({ configVersion })
|
||||
}
|
||||
}
|
||||
|
|
@ -1,175 +0,0 @@
|
|||
import { SearchMode } from 'components/searchModes'
|
||||
import * as storageHelper from 'utils/storageHelper'
|
||||
|
||||
export type Config = {
|
||||
sideBarWidth: number
|
||||
shortcut: string | undefined
|
||||
accessToken: string | undefined
|
||||
compressSingletonFolder: boolean
|
||||
copyFileButton: boolean
|
||||
copySnippetButton: boolean
|
||||
intelligentToggle: boolean | null // `null` stands for intelligent, boolean for sidebar open status
|
||||
icons: 'rich' | 'dim' | 'native'
|
||||
toggleButtonVerticalDistance: number
|
||||
toggleButtonContent: 'logo' | 'octoface'
|
||||
recursiveToggleFolder: 'shift' | 'alt'
|
||||
searchMode: SearchMode
|
||||
}
|
||||
|
||||
enum configKeys {
|
||||
sideBarWidth = 'sideBarWidth',
|
||||
shortcut = 'shortcut',
|
||||
accessToken = 'accessToken',
|
||||
compressSingletonFolder = 'compressSingletonFolder',
|
||||
copyFileButton = 'copyFileButton',
|
||||
copySnippetButton = 'copySnippetButton',
|
||||
intelligentToggle = 'intelligentToggle',
|
||||
icons = 'icons',
|
||||
toggleButtonVerticalDistance = 'toggleButtonVerticalDistance',
|
||||
toggleButtonContent = 'toggleButtonContent',
|
||||
recursiveToggleFolder = 'recursiveToggleFolder',
|
||||
searchMode = 'searchMode',
|
||||
}
|
||||
|
||||
const defaultConfigs: Config = {
|
||||
sideBarWidth: 260,
|
||||
shortcut: undefined,
|
||||
accessToken: '',
|
||||
compressSingletonFolder: true,
|
||||
copyFileButton: true,
|
||||
copySnippetButton: true,
|
||||
intelligentToggle: null,
|
||||
icons: 'rich',
|
||||
toggleButtonVerticalDistance: 124, // align with GitHub's navbar items
|
||||
toggleButtonContent: 'logo',
|
||||
recursiveToggleFolder: 'shift',
|
||||
searchMode: 'fuzzy',
|
||||
}
|
||||
|
||||
const configKeyArray = Object.values(configKeys)
|
||||
|
||||
function applyDefaultConfigs(configs: Partial<Config>) {
|
||||
return configKeyArray.reduce((applied, key) => {
|
||||
Object.assign(applied, { [key]: key in configs ? configs[key] : defaultConfigs[key] })
|
||||
return applied
|
||||
}, {} as Config)
|
||||
}
|
||||
|
||||
type VersionedConfig<SiteConfig> = Record<string, SiteConfig> & { configVersion: string }
|
||||
|
||||
type Storage = {
|
||||
// save root level `configVersion` for easier future migrating
|
||||
[key in 'configVersion' | string]: string
|
||||
|
||||
// separate different platform configs to simplify interactions with browser storage API
|
||||
// e.g.
|
||||
// platform_github.com?: Config
|
||||
}
|
||||
|
||||
async function migrateConfig() {
|
||||
// not referencing to enum above to prevent migrate future configs
|
||||
const migrations: {
|
||||
version: string
|
||||
migrate(version: string): Promise<void>
|
||||
}[] = [
|
||||
{
|
||||
version: '1.0.1',
|
||||
async migrate(version) {
|
||||
const config: any | void = await storageHelper.get<Storage>([
|
||||
'configVersion',
|
||||
'sideBarWidth',
|
||||
'shortcut',
|
||||
'access_token',
|
||||
'compressSingletonFolder',
|
||||
'copyFileButton',
|
||||
'copySnippetButton',
|
||||
'intelligentToggle',
|
||||
'icons',
|
||||
])
|
||||
if (config && (!('configVersion' in config) || config.configVersion < version)) {
|
||||
await storageHelper.set({ platform_GitHub: config, configVersion: version })
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
version: '1.3.4',
|
||||
async migrate(version) {
|
||||
const config: any | void = await storageHelper.get<VersionedConfig<Config> & Storage>([
|
||||
'configVersion',
|
||||
'platform_undefined', // this was a mistake :(
|
||||
'platform_GitHub',
|
||||
'platform_github.com',
|
||||
])
|
||||
if (
|
||||
config &&
|
||||
'configVersion' in config &&
|
||||
config.configVersion < version &&
|
||||
(config.platform_GitHub || config.platform_undefined) &&
|
||||
!config['platform_github.com']
|
||||
) {
|
||||
await storageHelper.set({
|
||||
['platform_github.com']: config.platform_GitHub || config.platform_undefined,
|
||||
configVersion: version,
|
||||
})
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
version: '2.6.0',
|
||||
async migrate(version) {
|
||||
type LegacySiteConfig = {
|
||||
access_token?: string
|
||||
}
|
||||
type MigratedSiteConfig = {
|
||||
accessToken?: string
|
||||
}
|
||||
|
||||
const config = await storageHelper.get<VersionedConfig<LegacySiteConfig> & Storage>()
|
||||
if (config && config.configVersion < version) {
|
||||
const { configVersion, ...restConfig } = config
|
||||
for (const key of Object.keys(restConfig)) {
|
||||
if (
|
||||
typeof restConfig[key] === 'object' &&
|
||||
restConfig[key] &&
|
||||
'access_token' in restConfig[key]
|
||||
) {
|
||||
const config: LegacySiteConfig = restConfig[key]
|
||||
const { access_token: accessToken, ...legacy } = config
|
||||
const migrated: MigratedSiteConfig = {
|
||||
...legacy,
|
||||
accessToken,
|
||||
}
|
||||
await storageHelper.set({
|
||||
[key]: migrated,
|
||||
})
|
||||
}
|
||||
}
|
||||
await storageHelper.set({
|
||||
configVersion: version,
|
||||
})
|
||||
}
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
for (const { version, migrate } of migrations) {
|
||||
await migrate(version)
|
||||
}
|
||||
}
|
||||
|
||||
// do NOT use platform name
|
||||
const platformStorageKey = `platform_` + window.location.host.toLowerCase()
|
||||
const prepareConfig = new Promise(async resolve => {
|
||||
await migrateConfig()
|
||||
resolve()
|
||||
})
|
||||
|
||||
export async function get(): Promise<Config> {
|
||||
await prepareConfig
|
||||
const config = await storageHelper.get<Record<string, Config>>([platformStorageKey])
|
||||
return applyDefaultConfigs(config?.[platformStorageKey] || {})
|
||||
}
|
||||
|
||||
export async function set(config: Config) {
|
||||
return await storageHelper.set({ [platformStorageKey]: config })
|
||||
}
|
||||
|
|
@ -1,18 +1,28 @@
|
|||
type CXValue = string | boolean | null | undefined
|
||||
|
||||
/**
|
||||
* cx('class1', { class2: true, class3: false }) --> 'class1 class2'
|
||||
*/
|
||||
export function cx(...classNames: any[]): string {
|
||||
return classNames
|
||||
.filter(Boolean)
|
||||
.map(className => {
|
||||
switch (typeof className) {
|
||||
case 'string':
|
||||
return className
|
||||
case 'object':
|
||||
return cx(...Object.entries(className).map(([key, value]) => (value ? key : null)))
|
||||
default:
|
||||
return ''
|
||||
export function cx(
|
||||
...classNames: (
|
||||
| CXValue
|
||||
| {
|
||||
[className: string]: CXValue
|
||||
}
|
||||
})
|
||||
.join(' ')
|
||||
)[]
|
||||
): string {
|
||||
return classNames.map(handleClassName).filter(Boolean).join(' ')
|
||||
}
|
||||
|
||||
function handleClassName(className: Parameters<typeof cx>[number]): string | false {
|
||||
switch (typeof className) {
|
||||
case 'string':
|
||||
return className
|
||||
case 'object':
|
||||
return className === null
|
||||
? false
|
||||
: cx(...Object.entries(className).map(([key, value]) => (value ? key : false)))
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -105,23 +105,8 @@ export function setStyleSheetMedia(style: HTMLStyleElement, media: string) {
|
|||
style.setAttribute('media', media)
|
||||
}
|
||||
|
||||
export function parseURLSearch(search: string = window.location.search) {
|
||||
const parsed: any = {}
|
||||
if (search.startsWith('?')) {
|
||||
const pairs = search
|
||||
.slice(1)
|
||||
.split('&')
|
||||
.map(rawPair => rawPair.split('=').map(raw => decodeURIComponent(raw))) // [key, value?][]
|
||||
pairs.forEach(([key, value]) => {
|
||||
if (Object.prototype.hasOwnProperty.call(parsed, key)) {
|
||||
if (Array.isArray(parsed[key])) parsed[key].push(value)
|
||||
else parsed[key] = [parsed[key], value]
|
||||
} else {
|
||||
parsed[key] = value
|
||||
}
|
||||
})
|
||||
}
|
||||
return parsed
|
||||
export function parseURLSearch(search = window.location.search) {
|
||||
return new URLSearchParams(search)
|
||||
}
|
||||
|
||||
export async function JSONRequest(url: string, data: any, extra: RequestInit = { method: 'post' }) {
|
||||
|
|
|
|||
45
src/utils/hooks/useCatchNetworkError.ts
Normal file
45
src/utils/hooks/useCatchNetworkError.ts
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
import { useConfigs } from 'containers/ConfigsContext'
|
||||
import { errors, platformName } from 'platforms'
|
||||
import { useCallback } from 'react'
|
||||
import { useLoadedContext } from 'utils/hooks/useLoadedContext'
|
||||
import { SideBarErrorContext } from '../../containers/ErrorContext'
|
||||
import { SideBarStateContext } from '../../containers/SideBarState'
|
||||
|
||||
export function useCatchNetworkError() {
|
||||
const { accessToken } = useConfigs().value
|
||||
const stateContext = useLoadedContext(SideBarStateContext)
|
||||
const errorContext = useLoadedContext(SideBarErrorContext)
|
||||
|
||||
return useCallback(
|
||||
async function <T>(fn: () => T) {
|
||||
try {
|
||||
return await fn() // keep the await so that catch block can catch async errors
|
||||
} catch (err) {
|
||||
if (err.message === errors.EMPTY_PROJECT) {
|
||||
errorContext.onChange('This project seems to be empty.')
|
||||
} else if (err.message === errors.BLOCKED_PROJECT) {
|
||||
errorContext.onChange('Access to the project is blocked.')
|
||||
} else if (
|
||||
err.message === errors.NOT_FOUND ||
|
||||
err.message === errors.BAD_CREDENTIALS ||
|
||||
err.message === errors.API_RATE_LIMIT
|
||||
) {
|
||||
stateContext.onChange('error-due-to-auth')
|
||||
} else if (err.message === errors.CONNECTION_BLOCKED) {
|
||||
if (accessToken) {
|
||||
errorContext.onChange(`Cannot connect to ${platformName}.`)
|
||||
} else {
|
||||
stateContext.onChange('error-due-to-auth')
|
||||
}
|
||||
} else if (err.message === errors.SERVER_FAULT) {
|
||||
errorContext.onChange(`${platformName} server went down.`)
|
||||
} else {
|
||||
stateContext.onChange('disabled')
|
||||
errorContext.onChange('Something unexpected happened.')
|
||||
throw err
|
||||
}
|
||||
}
|
||||
},
|
||||
[accessToken /* , stateContext.value, errorContext.value */],
|
||||
)
|
||||
}
|
||||
9
src/utils/hooks/useEffectOnSerializableUpdates.ts
Normal file
9
src/utils/hooks/useEffectOnSerializableUpdates.ts
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
import * as React from 'react'
|
||||
|
||||
export function useEffectOnSerializableUpdates<T>(
|
||||
value: T,
|
||||
serialize: (value: T) => string,
|
||||
onChange: (value: T) => void,
|
||||
) {
|
||||
React.useEffect(() => onChange(value), [onChange, serialize(value)])
|
||||
}
|
||||
7
src/utils/hooks/useLoadedContext.ts
Normal file
7
src/utils/hooks/useLoadedContext.ts
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
import * as React from 'react'
|
||||
|
||||
export function useLoadedContext<T>(context: React.Context<T | null>): T {
|
||||
const ctx = React.useContext(context)
|
||||
if (ctx === null) throw new Error(`Context not loaded`)
|
||||
return ctx
|
||||
}
|
||||
27
src/utils/hooks/useToggleSideBarWithKeyboard.ts
Normal file
27
src/utils/hooks/useToggleSideBarWithKeyboard.ts
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
import { ConfigsContextShape } from 'containers/ConfigsContext'
|
||||
import * as React from 'react'
|
||||
import * as keyHelper from 'utils/keyHelper'
|
||||
import { SideBarState } from '../../containers/SideBarState'
|
||||
|
||||
export function useToggleSideBarWithKeyboard(
|
||||
state: SideBarState,
|
||||
configContext: ConfigsContextShape,
|
||||
toggleShowSideBar: () => void,
|
||||
) {
|
||||
const isDisabled = state === 'disabled'
|
||||
React.useEffect(
|
||||
function attachKeyDown() {
|
||||
if (isDisabled || !configContext.value.shortcut) return
|
||||
|
||||
function onKeyDown(e: KeyboardEvent) {
|
||||
const keys = keyHelper.parseEvent(e)
|
||||
if (keys === configContext.value.shortcut) {
|
||||
toggleShowSideBar()
|
||||
}
|
||||
}
|
||||
window.addEventListener('keydown', onKeyDown)
|
||||
return () => window.removeEventListener('keydown', onKeyDown)
|
||||
},
|
||||
[toggleShowSideBar, isDisabled, configContext.value.shortcut],
|
||||
)
|
||||
}
|
||||
|
|
@ -1,6 +1,15 @@
|
|||
const localStorage = browser.storage.local
|
||||
|
||||
export async function get<
|
||||
export type Storage = {
|
||||
// save root level `configVersion` for easier future migrating
|
||||
[key in EnumString<'configVersion'>]: string
|
||||
|
||||
// separate different platform configs to simplify interactions with browser storage API
|
||||
// e.g.
|
||||
// ['platform_github.com']?: Config
|
||||
}
|
||||
|
||||
async function get<
|
||||
T extends {
|
||||
[key: string]: any
|
||||
}
|
||||
|
|
@ -10,8 +19,10 @@ export async function get<
|
|||
} catch (err) {}
|
||||
}
|
||||
|
||||
export function set(value: any): Promise<void> | void {
|
||||
function set(value: any): Promise<void> | void {
|
||||
try {
|
||||
return localStorage.set(value)
|
||||
} catch (err) {}
|
||||
}
|
||||
|
||||
export const storageHelper = { get, set }
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
"strict": true,
|
||||
"lib": ["dom", "es2017.object", "es2016", "ES2020.String"],
|
||||
"baseUrl": "src",
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"outDir": "dist"
|
||||
},
|
||||
"include": ["src"]
|
||||
|
|
|
|||
226
yarn.lock
226
yarn.lock
|
|
@ -1428,68 +1428,68 @@
|
|||
resolved "https://registry.yarnpkg.com/@reach/utils/-/utils-0.3.0.tgz#2098181aab751f2275cacf219b02a6a8b455be85"
|
||||
integrity sha512-dQA1acyNpwqy5ia5yt1lNjaAhm9rrzSurFtlJPoz7ARVPMV1yZ0yfmNotMwwgVbE5q1HnONqszK7oagH86m7Qw==
|
||||
|
||||
"@sentry/browser@^5.12.1":
|
||||
version "5.12.1"
|
||||
resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-5.12.1.tgz#dc1f268595269fb7277f55eb625c7e92d76dc01b"
|
||||
integrity sha512-Zl7VdppUxctyaoqMSEhnDJp2rrupx8n8N2n3PSooH74yhB2Z91nt84mouczprBsw3JU1iggGyUw9seRFzDI1hw==
|
||||
"@sentry/browser@^6.3.6":
|
||||
version "6.3.6"
|
||||
resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-6.3.6.tgz#bba07033efded6c844de88dcc47f99548a29afed"
|
||||
integrity sha512-l4323jxuBOArki6Wf+EHes39IEyJ2Zj/CIUaTY7GWh7CntpfHQAfFmZWQw3Ozq+ka1u8lVp25RPhb4Wng3azNA==
|
||||
dependencies:
|
||||
"@sentry/core" "5.12.0"
|
||||
"@sentry/types" "5.12.0"
|
||||
"@sentry/utils" "5.12.0"
|
||||
"@sentry/core" "6.3.6"
|
||||
"@sentry/types" "6.3.6"
|
||||
"@sentry/utils" "6.3.6"
|
||||
tslib "^1.9.3"
|
||||
|
||||
"@sentry/cli@^1.51.0":
|
||||
version "1.51.0"
|
||||
resolved "https://registry.yarnpkg.com/@sentry/cli/-/cli-1.51.0.tgz#2ce7d03b7aebf3f9e9a7186bac1a777fc3dc0e82"
|
||||
integrity sha512-QXdW3smFW9Wjd5gYHuA9u9tCra87VqpeFljRKdD7D2CwnYCnFDeluVk3l9O8Me6IoVBuL9Uwxx8q1vPtob4n3Q==
|
||||
"@sentry/cli@^1.64.2":
|
||||
version "1.64.2"
|
||||
resolved "https://registry.yarnpkg.com/@sentry/cli/-/cli-1.64.2.tgz#38a68d31692675061fdedd27d4006a249bc915a9"
|
||||
integrity sha512-hBF8cswn878W7YqAgeg/vcQ51BgtpeiklGV6Q5MEXqGXtbjaKTBYBcKTkhzpkkcUtTu5bFkVcdGzVtpl4oBe+g==
|
||||
dependencies:
|
||||
fs-copy-file-sync "^1.1.1"
|
||||
https-proxy-agent "^4.0.0"
|
||||
mkdirp "^0.5.1"
|
||||
node-fetch "^2.1.2"
|
||||
progress "2.0.0"
|
||||
proxy-from-env "^1.0.0"
|
||||
https-proxy-agent "^5.0.0"
|
||||
mkdirp "^0.5.5"
|
||||
node-fetch "^2.6.0"
|
||||
npmlog "^4.1.2"
|
||||
progress "^2.0.3"
|
||||
proxy-from-env "^1.1.0"
|
||||
|
||||
"@sentry/core@5.12.0":
|
||||
version "5.12.0"
|
||||
resolved "https://registry.yarnpkg.com/@sentry/core/-/core-5.12.0.tgz#d6380c4ef7beee5f418ac1d0e5be86a2de2af449"
|
||||
integrity sha512-wY4rsoX71QsGpcs9tF+OxKgDPKzIFMRvFiSRcJoPMfhFsTilQ/CBMn/c3bDtWQd9Bnr/ReQIL6NbnIjUsPHA4Q==
|
||||
"@sentry/core@6.3.6":
|
||||
version "6.3.6"
|
||||
resolved "https://registry.yarnpkg.com/@sentry/core/-/core-6.3.6.tgz#e2ec6ae7e456e61f28000bab2d8ce85f58c59c66"
|
||||
integrity sha512-w6BRizAqh7BaiM9oeKzO6aACXwRijUPacYaVLX/OfhqCSueF9uDxpMRT7+4D/eCeDVqgJYhBJ4Vsu2NSstkk4A==
|
||||
dependencies:
|
||||
"@sentry/hub" "5.12.0"
|
||||
"@sentry/minimal" "5.12.0"
|
||||
"@sentry/types" "5.12.0"
|
||||
"@sentry/utils" "5.12.0"
|
||||
"@sentry/hub" "6.3.6"
|
||||
"@sentry/minimal" "6.3.6"
|
||||
"@sentry/types" "6.3.6"
|
||||
"@sentry/utils" "6.3.6"
|
||||
tslib "^1.9.3"
|
||||
|
||||
"@sentry/hub@5.12.0":
|
||||
version "5.12.0"
|
||||
resolved "https://registry.yarnpkg.com/@sentry/hub/-/hub-5.12.0.tgz#5e8c8f249f5bdbeb8cc4ec02c2ccc53a67f2cc02"
|
||||
integrity sha512-3k7yE8BEVJsKx8mR4LcI4IN0O8pngmq44OcJ/fRUUBAPqsT38jsJdP2CaWhdlM1jiNUzUDB1ktBv6/lY+VgcoQ==
|
||||
"@sentry/hub@6.3.6":
|
||||
version "6.3.6"
|
||||
resolved "https://registry.yarnpkg.com/@sentry/hub/-/hub-6.3.6.tgz#e7bc6960e30d8731e23c6e77f31af0bfb1d5af3c"
|
||||
integrity sha512-foBZ3ilMnm9Gf9OolrAxYHK8jrA6IF72faDdJ3Al+1H27qcpnBaMdrdEp2/jzwu/dgmwuLmbBaMjEPXaGH/0JQ==
|
||||
dependencies:
|
||||
"@sentry/types" "5.12.0"
|
||||
"@sentry/utils" "5.12.0"
|
||||
"@sentry/types" "6.3.6"
|
||||
"@sentry/utils" "6.3.6"
|
||||
tslib "^1.9.3"
|
||||
|
||||
"@sentry/minimal@5.12.0":
|
||||
version "5.12.0"
|
||||
resolved "https://registry.yarnpkg.com/@sentry/minimal/-/minimal-5.12.0.tgz#2611e2aa520c1edb7999e6de51bd65ec66341757"
|
||||
integrity sha512-fk73meyz4k4jCg9yzbma+WkggsfEIQWI2e2TWfYsRGcrV3RnlSrXyM4D91/A8Bjx10SNezHPUFHjasjlHXOkyA==
|
||||
"@sentry/minimal@6.3.6":
|
||||
version "6.3.6"
|
||||
resolved "https://registry.yarnpkg.com/@sentry/minimal/-/minimal-6.3.6.tgz#aebcebd2ee9007b0ec505b9fcefd10f10fc5d43d"
|
||||
integrity sha512-uM2/dH0a6zfvI5f+vg+/mST+uTBdN6Jgpm585ipH84ckCYQwIIDRg6daqsen4S1sy/xgg1P1YyC3zdEC4G6b1Q==
|
||||
dependencies:
|
||||
"@sentry/hub" "5.12.0"
|
||||
"@sentry/types" "5.12.0"
|
||||
"@sentry/hub" "6.3.6"
|
||||
"@sentry/types" "6.3.6"
|
||||
tslib "^1.9.3"
|
||||
|
||||
"@sentry/types@5.12.0":
|
||||
version "5.12.0"
|
||||
resolved "https://registry.yarnpkg.com/@sentry/types/-/types-5.12.0.tgz#5367e53c74261beea01502e3f7b6f3d822682a31"
|
||||
integrity sha512-aZbBouBLrKB8wXlztriIagZNmsB+wegk1Jkl6eprqRW/w24Sl/47tiwH8c5S4jYTxdAiJk+SAR10AAuYmIN3zg==
|
||||
"@sentry/types@6.3.6":
|
||||
version "6.3.6"
|
||||
resolved "https://registry.yarnpkg.com/@sentry/types/-/types-6.3.6.tgz#aa3687051af1dc04ebc4eaf7f9562872da67aa5c"
|
||||
integrity sha512-93cFJdJkWyCfyZeWFARSU11qnoHVOS/R2h5WIsEf+jbQmkqG2C+TXVz/19s6nHVsfDrwpvYpwALPv4/nrxfU7g==
|
||||
|
||||
"@sentry/utils@5.12.0":
|
||||
version "5.12.0"
|
||||
resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-5.12.0.tgz#62967f934a3ee6d21472eac0219084e37225933e"
|
||||
integrity sha512-fYUadGLbfTCbs4OG5hKCOtv2jrNE4/8LHNABy9DwNJ/t5DVtGqWAZBnxsC+FG6a3nVqCpxjFI9AHlYsJ2wsf7Q==
|
||||
"@sentry/utils@6.3.6":
|
||||
version "6.3.6"
|
||||
resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-6.3.6.tgz#6f619a525f2a94fa6b160500f63f4bd5bd171055"
|
||||
integrity sha512-HnYlDBf8Dq8MEv7AulH7B6R1D/2LAooVclGdjg48tSrr9g+31kmtj+SAj2WWVHP9+bp29BWaC7i5nkfKrOibWw==
|
||||
dependencies:
|
||||
"@sentry/types" "5.12.0"
|
||||
"@sentry/types" "6.3.6"
|
||||
tslib "^1.9.3"
|
||||
|
||||
"@sheerun/mutationobserver-shim@^0.3.2":
|
||||
|
|
@ -1759,6 +1759,11 @@
|
|||
resolved "https://registry.yarnpkg.com/@types/js-base64/-/js-base64-2.3.1.tgz#c39f14f129408a3d96a1105a650d8b2b6eeb4168"
|
||||
integrity sha512-4RKbhIDGC87s4EBy2Cp2/5S2O6kmCRcZnD5KRCq1q9z2GhBte1+BdsfVKCpG8yKpDGNyEE2G6IqFIh6W2YwWPA==
|
||||
|
||||
"@types/js-cookie@2.2.6":
|
||||
version "2.2.6"
|
||||
resolved "https://registry.yarnpkg.com/@types/js-cookie/-/js-cookie-2.2.6.tgz#f1a1cb35aff47bc5cfb05cb0c441ca91e914c26f"
|
||||
integrity sha512-+oY0FDTO2GYKEV0YPvSshGq9t7YozVkgvXLty7zogQNuCxBhT9/3INX9Q7H1aRZ4SUDRXAKlJuA4EA5nTt7SNw==
|
||||
|
||||
"@types/minimatch@^3.0.3":
|
||||
version "3.0.3"
|
||||
resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d"
|
||||
|
|
@ -2044,6 +2049,11 @@
|
|||
"@webassemblyjs/wast-parser" "1.8.5"
|
||||
"@xtuc/long" "4.2.2"
|
||||
|
||||
"@xobotyi/scrollbar-width@1.9.5":
|
||||
version "1.9.5"
|
||||
resolved "https://registry.yarnpkg.com/@xobotyi/scrollbar-width/-/scrollbar-width-1.9.5.tgz#80224a6919272f405b87913ca13b92929bdf3c4d"
|
||||
integrity sha512-N8tkAACJx2ww8vFMneJmaAgmjAG1tnVBZJRLRcx061tmsLRZHSEZSLuGWnwPtunsSLvSqXQ2wfp7Mgqg1I+2dQ==
|
||||
|
||||
"@xtuc/ieee754@^1.2.0":
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790"
|
||||
|
|
@ -2209,6 +2219,13 @@ agent-base@5:
|
|||
resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-5.1.1.tgz#e8fb3f242959db44d63be665db7a8e739537a32c"
|
||||
integrity sha512-TMeqbNl2fMW0nMjTEPOwe3J/PRFP4vqeoNuQMG0HlMrtm5QxKqdvAkZ1pRBQ/ulIyDD5Yq0nJ7YbdD8ey0TO3g==
|
||||
|
||||
agent-base@6:
|
||||
version "6.0.2"
|
||||
resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77"
|
||||
integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==
|
||||
dependencies:
|
||||
debug "4"
|
||||
|
||||
ajv-errors@^1.0.0:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/ajv-errors/-/ajv-errors-1.0.1.tgz#f35986aceb91afadec4102fbd85014950cefa64d"
|
||||
|
|
@ -4898,6 +4915,11 @@ fast-deep-equal@^3.1.1:
|
|||
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz#545145077c501491e33b15ec408c294376e94ae4"
|
||||
integrity sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==
|
||||
|
||||
fast-deep-equal@^3.1.3:
|
||||
version "3.1.3"
|
||||
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525"
|
||||
integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==
|
||||
|
||||
fast-json-patch@^2.0.6:
|
||||
version "2.2.1"
|
||||
resolved "https://registry.yarnpkg.com/fast-json-patch/-/fast-json-patch-2.2.1.tgz#18150d36c9ab65c7209e7d4eb113f4f8eaabe6d9"
|
||||
|
|
@ -4925,6 +4947,11 @@ fast-safe-stringify@^2.0.7:
|
|||
resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.0.7.tgz#124aa885899261f68aedb42a7c080de9da608743"
|
||||
integrity sha512-Utm6CdzT+6xsDk2m8S6uL8VHxNwI6Jub+e9NYTcAms28T84pTa25GJQV9j0CY0N1rM8hK4x6grpF2BQf+2qwVA==
|
||||
|
||||
fast-shallow-equal@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/fast-shallow-equal/-/fast-shallow-equal-1.0.0.tgz#d4dcaf6472440dcefa6f88b98e3251e27f25628b"
|
||||
integrity sha512-HPtaa38cPgWvaCFmRNhlc6NG7pv6NUHqjPgVAkWGoB9mQMwYB27/K0CvOM5Czy+qpT3e8XJ6Q4aPAnzpNpzNaw==
|
||||
|
||||
fastest-stable-stringify@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/fastest-stable-stringify/-/fastest-stable-stringify-1.0.1.tgz#9122d406d4c9d98bea644a6b6853d5874b87b028"
|
||||
|
|
@ -5222,11 +5249,6 @@ fs-constants@^1.0.0:
|
|||
resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad"
|
||||
integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==
|
||||
|
||||
fs-copy-file-sync@^1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/fs-copy-file-sync/-/fs-copy-file-sync-1.1.1.tgz#11bf32c096c10d126e5f6b36d06eece776062918"
|
||||
integrity sha512-2QY5eeqVv4m2PfyMiEuy9adxNP+ajf+8AR05cEi+OAzPcOj90hvFImeZhTmKLBgSd9EvG33jsD7ZRxsx9dThkQ==
|
||||
|
||||
fs-exists-sync@^0.1.0:
|
||||
version "0.1.0"
|
||||
resolved "https://registry.yarnpkg.com/fs-exists-sync/-/fs-exists-sync-0.1.0.tgz#982d6893af918e72d08dec9e8673ff2b5a8d6add"
|
||||
|
|
@ -5776,6 +5798,14 @@ https-proxy-agent@^4.0.0:
|
|||
agent-base "5"
|
||||
debug "4"
|
||||
|
||||
https-proxy-agent@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz#e2a90542abb68a762e0a0850f6c9edadfd8506b2"
|
||||
integrity sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==
|
||||
dependencies:
|
||||
agent-base "6"
|
||||
debug "4"
|
||||
|
||||
human-signals@^1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-1.1.1.tgz#c5b1cd14f50aeae09ab6c59fe63ba3395fe4dfa3"
|
||||
|
|
@ -6758,6 +6788,11 @@ js-base64@^2.5.1:
|
|||
resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.5.1.tgz#1efa39ef2c5f7980bb1784ade4a8af2de3291121"
|
||||
integrity sha512-M7kLczedRMYX4L8Mdh4MzyAMM9O5osx+4FcOQuTvr3A9F2D9S5JXheN0ewNbrvK2UatkTRhL5ejGmGSjNMiZuw==
|
||||
|
||||
js-cookie@^2.2.1:
|
||||
version "2.2.1"
|
||||
resolved "https://registry.yarnpkg.com/js-cookie/-/js-cookie-2.2.1.tgz#69e106dc5d5806894562902aa5baec3744e9b2b8"
|
||||
integrity sha512-HvdH2LzI/EAZcUwA8+0nKNtWHqS+ZmijLA30RwZA0bo7ToCckjK5MkGhjED9KoRcXO6BaGI3I9UIzSA1FKFPOQ==
|
||||
|
||||
js-levenshtein@^1.1.3:
|
||||
version "1.1.6"
|
||||
resolved "https://registry.yarnpkg.com/js-levenshtein/-/js-levenshtein-1.1.6.tgz#c6cee58eb3550372df8deb85fad5ce66ce01d59d"
|
||||
|
|
@ -7500,7 +7535,7 @@ mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.1:
|
|||
dependencies:
|
||||
minimist "0.0.8"
|
||||
|
||||
mkdirp@^0.5.3:
|
||||
mkdirp@^0.5.3, mkdirp@^0.5.5:
|
||||
version "0.5.5"
|
||||
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def"
|
||||
integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==
|
||||
|
|
@ -7658,12 +7693,7 @@ nice-try@^1.0.4:
|
|||
resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366"
|
||||
integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==
|
||||
|
||||
node-fetch@^2.1.2:
|
||||
version "2.6.0"
|
||||
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.0.tgz#e633456386d4aa55863f676a7ab0daa8fdecb0fd"
|
||||
integrity sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA==
|
||||
|
||||
node-fetch@^2.6.1:
|
||||
node-fetch@^2.6.0, node-fetch@^2.6.1:
|
||||
version "2.6.1"
|
||||
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052"
|
||||
integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==
|
||||
|
|
@ -7829,7 +7859,7 @@ npm-run-path@^4.0.0:
|
|||
dependencies:
|
||||
path-key "^3.0.0"
|
||||
|
||||
npmlog@^4.0.2:
|
||||
npmlog@^4.0.2, npmlog@^4.1.2:
|
||||
version "4.1.2"
|
||||
resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b"
|
||||
integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==
|
||||
|
|
@ -8492,17 +8522,12 @@ process@^0.11.10:
|
|||
resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182"
|
||||
integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI=
|
||||
|
||||
progress@2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.0.tgz#8a1be366bf8fc23db2bd23f10c6fe920b4389d1f"
|
||||
integrity sha1-ihvjZr+Pwj2yvSPxDG/pILQ4nR8=
|
||||
|
||||
progress@^1.1.8:
|
||||
version "1.1.8"
|
||||
resolved "https://registry.yarnpkg.com/progress/-/progress-1.1.8.tgz#e260c78f6161cdd9b0e56cc3e0a85de17c7a57be"
|
||||
integrity sha1-4mDHj2Fhzdmw5WzD4Khd4Xx6V74=
|
||||
|
||||
progress@^2.0.0, progress@^2.0.1:
|
||||
progress@^2.0.0, progress@^2.0.1, progress@^2.0.3:
|
||||
version "2.0.3"
|
||||
resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8"
|
||||
integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==
|
||||
|
|
@ -8542,6 +8567,11 @@ proxy-from-env@^1.0.0:
|
|||
resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.0.0.tgz#33c50398f70ea7eb96d21f7b817630a55791c7ee"
|
||||
integrity sha1-M8UDmPcOp+uW0h97gXYwpVeRx+4=
|
||||
|
||||
proxy-from-env@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2"
|
||||
integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==
|
||||
|
||||
prr@~1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476"
|
||||
|
|
@ -8715,19 +8745,14 @@ react-clientside-effect@^1.2.2:
|
|||
dependencies:
|
||||
"@babel/runtime" "^7.0.0"
|
||||
|
||||
react-dom@^17.0.1:
|
||||
version "17.0.1"
|
||||
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-17.0.1.tgz#1de2560474ec9f0e334285662ede52dbc5426fc6"
|
||||
integrity sha512-6eV150oJZ9U2t9svnsspTMrWNyHc6chX0KzDeAOXftRa8bNeOKTTfCJ7KorIwenkHd2xqVTBTCZd79yk/lx/Ug==
|
||||
react-dom@^17.0.2:
|
||||
version "17.0.2"
|
||||
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-17.0.2.tgz#ecffb6845e3ad8dbfcdc498f0d0a939736502c23"
|
||||
integrity sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==
|
||||
dependencies:
|
||||
loose-envify "^1.1.0"
|
||||
object-assign "^4.1.1"
|
||||
scheduler "^0.20.1"
|
||||
|
||||
react-fast-compare@^2.0.4:
|
||||
version "2.0.4"
|
||||
resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-2.0.4.tgz#e84b4d455b0fec113e0402c329352715196f81f9"
|
||||
integrity sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw==
|
||||
scheduler "^0.20.2"
|
||||
|
||||
react-focus-lock@^2.1.0:
|
||||
version "2.2.1"
|
||||
|
|
@ -8783,20 +8808,30 @@ react-style-singleton@^2.0.0:
|
|||
invariant "^2.2.4"
|
||||
tslib "^1.0.0"
|
||||
|
||||
react-use@^13.8.0:
|
||||
version "13.8.0"
|
||||
resolved "https://registry.yarnpkg.com/react-use/-/react-use-13.8.0.tgz#5e8badaaa5614a1925fd28ad22d01cc1c52e0ff1"
|
||||
integrity sha512-J4ZWIqC1h2eSS6ObmHJUWDQeJSKZvHdBEINCu51plz7RS+ijrt6JEHfDWbNXx+aAoR5AmbRK+mzYwd3jiu3xpA==
|
||||
react-universal-interface@^0.6.2:
|
||||
version "0.6.2"
|
||||
resolved "https://registry.yarnpkg.com/react-universal-interface/-/react-universal-interface-0.6.2.tgz#5e8d438a01729a4dbbcbeeceb0b86be146fe2b3b"
|
||||
integrity sha512-dg8yXdcQmvgR13RIlZbTRQOoUrDciFVoSBZILwjE2LFISxZZ8loVJKAkuzswl5js8BHda79bIb2b84ehU8IjXw==
|
||||
|
||||
react-use@^15.3.0:
|
||||
version "15.3.8"
|
||||
resolved "https://registry.yarnpkg.com/react-use/-/react-use-15.3.8.tgz#ca839ac7fb3d696e5ccbeabbc8dadc2698969d30"
|
||||
integrity sha512-GeGcrmGuUvZrY5wER3Lnph9DSYhZt5nEjped4eKDq8BRGr2CnLf9bDQWG9RFc7oCPphnscUUdOovzq0E5F2c6Q==
|
||||
dependencies:
|
||||
"@types/js-cookie" "2.2.6"
|
||||
"@xobotyi/scrollbar-width" "1.9.5"
|
||||
copy-to-clipboard "^3.2.0"
|
||||
fast-deep-equal "^3.1.3"
|
||||
fast-shallow-equal "^1.0.0"
|
||||
js-cookie "^2.2.1"
|
||||
nano-css "^5.2.1"
|
||||
react-fast-compare "^2.0.4"
|
||||
react-universal-interface "^0.6.2"
|
||||
resize-observer-polyfill "^1.5.1"
|
||||
screenfull "^5.0.0"
|
||||
set-harmonic-interval "^1.0.1"
|
||||
throttle-debounce "^2.1.0"
|
||||
ts-easing "^0.2.0"
|
||||
tslib "^1.10.0"
|
||||
tslib "^2.0.0"
|
||||
|
||||
react-window@^1.8.5:
|
||||
version "1.8.5"
|
||||
|
|
@ -8807,9 +8842,9 @@ react-window@^1.8.5:
|
|||
memoize-one ">=3.1.1 <6"
|
||||
|
||||
react@^16.10.2, react@^17, react@^17.0.1:
|
||||
version "17.0.1"
|
||||
resolved "https://registry.yarnpkg.com/react/-/react-17.0.1.tgz#6e0600416bd57574e3f86d92edba3d9008726127"
|
||||
integrity sha512-lG9c9UuMHdcAexXtigOZLX8exLWkW0Ku29qPRU8uhF2R9BN96dLCt0psvzPLlHc5OWkgymP3qwTRgbnw5BKx3w==
|
||||
version "17.0.2"
|
||||
resolved "https://registry.yarnpkg.com/react/-/react-17.0.2.tgz#d0b5cc516d29eb3eee383f75b62864cfb6800037"
|
||||
integrity sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==
|
||||
dependencies:
|
||||
loose-envify "^1.1.0"
|
||||
object-assign "^4.1.1"
|
||||
|
|
@ -9354,10 +9389,10 @@ sax@>=0.6.0, sax@^1.2.4:
|
|||
resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9"
|
||||
integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==
|
||||
|
||||
scheduler@^0.20.1:
|
||||
version "0.20.1"
|
||||
resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.20.1.tgz#da0b907e24026b01181ecbc75efdc7f27b5a000c"
|
||||
integrity sha512-LKTe+2xNJBNxu/QhHvDR14wUXHRQbVY5ZOYpOGWRzhydZUqrLb2JBvLPY7cAqFmqrWuDED0Mjk7013SZiOz6Bw==
|
||||
scheduler@^0.20.2:
|
||||
version "0.20.2"
|
||||
resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.20.2.tgz#4baee39436e34aa93b4874bddcbf0fe8b8b50e91"
|
||||
integrity sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ==
|
||||
dependencies:
|
||||
loose-envify "^1.1.0"
|
||||
object-assign "^4.1.1"
|
||||
|
|
@ -10471,11 +10506,16 @@ tslib@^1.0.0:
|
|||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.11.1.tgz#eb15d128827fbee2841549e171f45ed338ac7e35"
|
||||
integrity sha512-aZW88SY8kQbU7gpV19lN24LtXh/yD4ZZg6qieAJDDg+YBsJcSmLGK9QpnUjAKVG/xefmvJGd1WUmfpT/g6AJGA==
|
||||
|
||||
tslib@^1.10.0, tslib@^1.9.0, tslib@^1.9.3:
|
||||
tslib@^1.9.0, tslib@^1.9.3:
|
||||
version "1.10.0"
|
||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a"
|
||||
integrity sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==
|
||||
|
||||
tslib@^2.0.0:
|
||||
version "2.2.0"
|
||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.2.0.tgz#fb2c475977e35e241311ede2693cee1ec6698f5c"
|
||||
integrity sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w==
|
||||
|
||||
tty-browserify@0.0.0:
|
||||
version "0.0.0"
|
||||
resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6"
|
||||
|
|
@ -10540,10 +10580,10 @@ typedarray@^0.0.6:
|
|||
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
|
||||
integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=
|
||||
|
||||
typescript@^4.0.3:
|
||||
version "4.0.3"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.0.3.tgz#153bbd468ef07725c1df9c77e8b453f8d36abba5"
|
||||
integrity sha512-tEu6DGxGgRJPb/mVPIZ48e69xCn2yRmCgYmDugAVwmJ6o+0u1RI18eO7E7WBTLYLaEVVOhwQmcdhQHweux/WPg==
|
||||
typescript@^4.2.4:
|
||||
version "4.2.4"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.2.4.tgz#8610b59747de028fda898a8aef0e103f156d0961"
|
||||
integrity sha512-V+evlYHZnQkaz8TRBuxTA92yZBPotr5H+WhQ7bD3hZUndx5tGOa1fuCgeSjxAzM1RiN5IzvadIXTVefuuwZCRg==
|
||||
|
||||
uglify-js@^3.6.0:
|
||||
version "3.6.0"
|
||||
|
|
|
|||
Loading…
Reference in a new issue