Added search support for kbar in this PR.

This commit is contained in:
gitstart-omnivore 2022-06-24 15:30:48 +00:00 committed by Jackson Harper
parent 3baa845853
commit 552d76a929
12 changed files with 565 additions and 154 deletions

View file

@ -0,0 +1,85 @@
import { KBarResults, useMatches } from 'kbar'
import { theme } from '../tokens/stitches.config'
import { Box, SpanBox } from './LayoutPrimitives'
export const searchStyle = {
padding: '14px 16px',
fontSize: '16px',
width: '100%',
outline: 'none',
border: 'none',
boxSizing: 'border-box' as React.CSSProperties['boxSizing'],
backgroundColor: theme.colors.grayBase.toString(),
color: theme.colors.grayTextContrast.toString(),
}
export const animatorStyle = {
maxWidth: '600px',
width: '100%',
backgroundColor: theme.colors.grayBase.toString(),
color: theme.colors.grayTextContrast.toString(),
borderRadius: '8px',
overflow: 'hidden',
boxShadow: '0px 6px 20px rgba(0, 0, 0, 0.2)',
}
const groupNameStyle = {
padding: '8px 16px',
fontSize: '10px',
textTransform: 'uppercase' as const,
opacity: 0.5,
}
export const KBarResultsComponents = () => {
const { results } = useMatches()
return (
<KBarResults
items={results}
onRender={({ item, active }) => {
return typeof item === 'string' ? (
<Box style={groupNameStyle}>{item.toLocaleUpperCase()}</Box>
) : (
<Box
style={{
background: active
? theme.colors.grayBgActive.toString()
: theme.colors.grayBase.toString(),
color: theme.colors.grayTextContrast.toString(),
padding: '0.8rem 1.5rem',
alignItems: 'center',
justifyContent: 'space-between',
cursor: 'pointer',
height: '100',
borderLeft: `2px solid ${
active
? theme.colors.grayTextContrast.toString()
: 'transparent'
}`,
display: 'flex',
gap: '0',
fontSize: 16,
}}
>
<Box>{item.name}</Box>
<Box style={{ display: 'flex', gap: '4px' }}>
{item.shortcut?.map((st, idx) => (
<SpanBox
key={idx}
style={{
padding: '4px 6px',
background: 'rgba(0, 0, 0, 0.1)',
borderRadius: '4px',
fontSize: '14px',
}}
>
{st}
</SpanBox>
))}
</Box>
</Box>
)
}}
/>
)
}

View file

@ -10,6 +10,7 @@ import { useKeyboardShortcuts } from '../../lib/keyboardShortcuts/useKeyboardSho
import { primaryCommands } from '../../lib/keyboardShortcuts/navigationShortcuts'
import { UserBasicData } from '../../lib/networking/queries/useGetViewerQuery'
import { setupAnalytics } from '../../lib/analytics'
import { useRegisterActions } from 'kbar'
type HeaderProps = {
user?: UserBasicData
@ -30,12 +31,12 @@ export function PrimaryHeader(props: HeaderProps): JSX.Element {
useKeyboardShortcuts(
primaryCommands((action) => {
switch (action) {
case 'themeDarker':
darkenTheme()
break
case 'themeLighter':
lightenTheme()
break
// case 'themeDarker':
// darkenTheme()
// break
// case 'themeLighter':
// lightenTheme()
// break
case 'toggleShortcutHelpModalDisplay':
props.setShowKeyboardCommandsModal(true)
break
@ -43,7 +44,6 @@ export function PrimaryHeader(props: HeaderProps): JSX.Element {
})
)
/*
useRegisterActions([
{
id: 'lightTheme',
@ -62,7 +62,6 @@ export function PrimaryHeader(props: HeaderProps): JSX.Element {
perform: () => darkenTheme(),
},
])
*/
const initAnalytics = useCallback(() => {
setupAnalytics(props.user)

View file

@ -176,7 +176,6 @@ export function ArticleActionsMenu(props: ArticleActionsMenuProps): JSX.Element
)}
{/* <MenuSeparator layout={props.layout} />
<Button style='articleActionIcon'>
<DotsThree size={24} color={theme.colors.readerFont.toString()} />
</Button> */}

View file

@ -1,6 +1,7 @@
import { Box, HStack, VStack } from './../../elements/LayoutPrimitives'
import type {
LibraryItem,
LibraryItemsData,
LibraryItemsQueryInput,
} from '../../../lib/networking/queries/useGetLibraryItemsQuery'
import { useGetLibraryItemsQuery } from '../../../lib/networking/queries/useGetLibraryItemsQuery'
@ -41,8 +42,11 @@ import {
State,
PageType,
} from '../../../lib/networking/fragments/articleFragment'
import { useRegisterActions, createAction, useKBar } from 'kbar'
import { EditTitleModal } from './EditTitleModal'
import { useGetUserPreferences } from '../../../lib/networking/queries/useGetUserPreferences'
import { searchQuery } from '../../../lib/networking/queries/search'
import debounce from 'lodash/debounce'
export type LayoutType = 'LIST_LAYOUT' | 'GRID_LAYOUT'
@ -60,11 +64,24 @@ const SAVED_SEARCHES: Record<string, string> = {
Newsletters: `in:inbox label:Newsletter`,
}
const fetchSearchResults = async (query: string, cb: any) => {
if (!query.startsWith('#')) return
const res = await searchQuery({ limit: 10, searchQuery: query.substring(1)})
cb(res);
};
const debouncedFetchSearchResults = debounce((query, cb) => {
fetchSearchResults(query, cb);
}, 300);
export function HomeFeedContainer(): JSX.Element {
useGetUserPreferences()
const { viewerData } = useGetViewerQuery()
const router = useRouter()
const { queryValue } = useKBar((state) => ({queryValue: state.searchQuery}));
const [searchResults, setSearchResults] = useState<LibraryItem[]>([]);
const defaultQuery = {
limit: 10,
sortDescending: true,
@ -102,6 +119,16 @@ export function HomeFeedContainer(): JSX.Element {
const { itemsPages, size, setSize, isValidating, performActionOnItem } =
useGetLibraryItemsQuery(queryInputs)
useEffect(() => {
if (queryValue.startsWith('#')) {
debouncedFetchSearchResults(queryValue, (data: LibraryItemsData) => {
setSearchResults(data?.search.edges || [])
})
}
else setSearchResults([])
}, [queryValue])
useEffect(() => {
if (!router.isReady) return
const q = router.query['q']
@ -421,6 +448,72 @@ export function HomeFeedContainer(): JSX.Element {
})
)
const ARCHIVE_ACTION = !activeItem?.node.isArchived ?
createAction({
section: 'Library',
name: 'Archive selected item',
shortcut: ['e'],
perform: () => handleCardAction('archive', activeItem),
}) :
createAction({
section: 'Library',
name: 'UnArchive selected item',
shortcut: ['e'],
perform: () => handleCardAction('unarchive', activeItem),
})
const ACTIVE_ACTIONS = [
ARCHIVE_ACTION,
createAction({
section: 'Library',
name: 'Remove item',
shortcut: ['r'],
perform: () => handleCardAction('delete', activeItem),
}),
createAction({
section: 'Library',
name: 'Edit item labels',
shortcut: ['l'],
perform: () => handleCardAction('set-labels', activeItem),
}),
createAction({
section: 'Library',
name: 'Mark item as read',
shortcut: ['Shift', 'i'],
perform: () => handleCardAction('mark-read', activeItem),
}),
createAction({
section: 'Library',
name: 'Mark item as unread',
shortcut: ['Shift', 'u'],
perform: () => handleCardAction('mark-unread', activeItem),
}),
]
const UNACTIVE_ACTIONS = [
createAction({
section: 'Library',
name: 'Sort item in ascending order',
shortcut: ['s', 'o'],
perform: () => setQueryInputs({ ...queryInputs, sortDescending: false }),
}),
createAction({
section: 'Library',
name: 'Sort item in descending order',
shortcut: ['s', 'n'],
perform: () => setQueryInputs({ ...queryInputs, sortDescending: true }),
}),
]
useRegisterActions(searchResults.map(link => ({
id: link.node.id,
section: 'Search Results',
name: link.node.title,
keywords: '#' + link.node.title,
perform: () => handleCardAction('showDetail', link),
})), [searchResults])
useRegisterActions(activeCardId ? [...ACTIVE_ACTIONS, ...UNACTIVE_ACTIONS] : UNACTIVE_ACTIONS, [activeCardId, activeItem]);
useFetchMore(handleFetchMore)
return (

View file

@ -1,3 +1,4 @@
import { useRegisterActions } from "kbar"
import { useCallback, useState } from "react"
import { userPersonalizationMutation } from "../networking/mutations/userPersonalizationMutation"
import { useGetUserPreferences, UserPreferences } from "../networking/queries/useGetUserPreferences"
@ -36,12 +37,12 @@ export const useReaderSettings = (): ReaderSettings => {
const [showSetLabelsModal, setShowSetLabelsModal] = useState(false)
const [showEditDisplaySettingsModal, setShowEditDisplaySettingsModal] = useState(false)
const actionHandler = useCallback(async(action: string, arg?: unknown) => {
const updateFontSize = async(newFontSize: number) => {
setFontSize(newFontSize)
await userPersonalizationMutation({ fontSize: newFontSize })
}
const updateFontSize = async (newFontSize: number) => {
setFontSize(newFontSize)
await userPersonalizationMutation({ fontSize: newFontSize })
}
const actionHandler = useCallback(async(action: string, arg?: unknown) => {
switch (action) {
case 'incrementFontSize':
await updateFontSize(Math.min(fontSize + 2, 28))
@ -91,6 +92,45 @@ export const useReaderSettings = (): ReaderSettings => {
}
}, [fontSize, setFontSize, lineHeight, fontFamily,
setLineHeight, marginWidth, setMarginWidth, setFontFamily])
useRegisterActions([
{
id: 'increaseFont',
section: 'Article',
name: 'Increase font size',
shortcut: ['+'],
perform: () => actionHandler('incrementFontSize'),
},
{
id: 'decreaseFont',
section: 'Article',
name: 'Decrease font size',
shortcut: ['-'],
perform: () => actionHandler('decrementFontSize'),
},
{
id: 'increaseMargin',
section: 'Article',
name: 'Increase margin width',
shortcut: [']'],
perform: () => actionHandler('incrementMarginWidth'),
},
{
id: 'decreaseMargin',
section: 'Article',
name: 'Decrease margin width',
shortcut: ['['],
perform: () => actionHandler('decrementMarginWidth'),
},
{
id: 'edit_a',
section: 'Article',
name: 'Edit labels',
shortcut: ['l'],
perform: () => setShowSetLabelsModal(true),
},
], [fontSize, marginWidth, setFontSize, setMarginWidth])
return {
preferencesData,

View file

@ -123,36 +123,36 @@ export function libraryListCommands(
shortcutKeyDescription: 'k or left arrow',
callback: () => actionHandler('moveFocusToPreviousListItem'),
},
{
shortcutKeys: ['e'],
actionDescription: 'Archive item',
shortcutKeyDescription: 'e',
callback: () => actionHandler('archiveItem'),
},
{
shortcutKeys: ['r'],
actionDescription: 'Remove item',
shortcutKeyDescription: 'r',
callback: () => actionHandler('removeItem'),
},
{
shortcutKeys: ['l'],
actionDescription: 'Edit item labels',
shortcutKeyDescription: 'l',
callback: () => actionHandler('showEditLabelsModal'),
},
{
shortcutKeys: ['shift', 'i'],
actionDescription: 'Mark item as read',
shortcutKeyDescription: 'shift + i',
callback: () => actionHandler('markItemAsRead'),
},
{
shortcutKeys: ['shift', 'u'],
actionDescription: 'Mark item as unread',
shortcutKeyDescription: 'shift + u',
callback: () => actionHandler('markItemAsUnread'),
},
// {
// shortcutKeys: ['e'],
// actionDescription: 'Archive item',
// shortcutKeyDescription: 'e',
// callback: () => actionHandler('archiveItem'),
// },
// {
// shortcutKeys: ['r'],
// actionDescription: 'Remove item',
// shortcutKeyDescription: 'r',
// callback: () => actionHandler('removeItem'),
// },
// {
// shortcutKeys: ['l'],
// actionDescription: 'Edit item labels',
// shortcutKeyDescription: 'l',
// callback: () => actionHandler('showEditLabelsModal'),
// },
// {
// shortcutKeys: ['shift', 'i'],
// actionDescription: 'Mark item as read',
// shortcutKeyDescription: 'shift + i',
// callback: () => actionHandler('markItemAsRead'),
// },
// {
// shortcutKeys: ['shift', 'u'],
// actionDescription: 'Mark item as unread',
// shortcutKeyDescription: 'shift + u',
// callback: () => actionHandler('markItemAsUnread'),
// },
// Commented out until we re-enable highlight sharing
// {
// shortcutKeys: ['shift', 's'],
@ -160,18 +160,18 @@ export function libraryListCommands(
// shortcutKeyDescription: 'shift + s',
// callback: () => actionHandler('shareItem'),
// },
{
shortcutKeys: ['s', 'o'],
actionDescription: 'Sort item in ascending order',
shortcutKeyDescription: 's then o',
callback: () => actionHandler('sortAscending'),
},
{
shortcutKeys: ['s', 'n'],
actionDescription: 'Sort item in descending order',
shortcutKeyDescription: 's then n',
callback: () => actionHandler('sortDescending'),
},
// {
// shortcutKeys: ['s', 'o'],
// actionDescription: 'Sort item in ascending order',
// shortcutKeyDescription: 's then o',
// callback: () => actionHandler('sortAscending'),
// },
// {
// shortcutKeys: ['s', 'n'],
// actionDescription: 'Sort item in descending order',
// shortcutKeyDescription: 's then n',
// callback: () => actionHandler('sortDescending'),
// },
{
shortcutKeys: ['arrowdown'],
actionDescription: 'Move cursor to the next row',
@ -231,53 +231,53 @@ export function articleKeyboardCommands(
actionHandler: (action: ArticleKeyboardAction) => void
): KeyboardCommand[] {
return [
{
shortcutKeys: ['o'],
actionDescription: 'Open original article page',
shortcutKeyDescription: 'o',
callback: () => actionHandler('openOriginalArticle'),
},
{
shortcutKeys: ['u'],
actionDescription: 'Back to library',
shortcutKeyDescription: 'u',
callback: () => router?.push('/home'),
},
{
shortcutKeys: ['+'],
actionDescription: 'Increase font size',
shortcutKeyDescription: '+',
callback: () => actionHandler('incrementFontSize'),
},
{
shortcutKeys: ['-'],
actionDescription: 'Decrease font size',
shortcutKeyDescription: '-',
callback: () => actionHandler('decrementFontSize'),
},
{
shortcutKeys: [']'],
actionDescription: 'Increase margin width',
shortcutKeyDescription: ']',
callback: () => actionHandler('incrementMarginWidth'),
},
{
shortcutKeys: ['['],
actionDescription: 'Decrease margin width',
shortcutKeyDescription: '[',
callback: () => actionHandler('decrementMarginWidth'),
},
// {
// shortcutKeys: ['o'],
// actionDescription: 'Open original article page',
// shortcutKeyDescription: 'o',
// callback: () => actionHandler('openOriginalArticle'),
// },
// {
// shortcutKeys: ['u'],
// actionDescription: 'Back to library',
// shortcutKeyDescription: 'u',
// callback: () => router?.push('/home'),
// },
// {
// shortcutKeys: ['+'],
// actionDescription: 'Increase font size',
// shortcutKeyDescription: '+',
// callback: () => actionHandler('incrementFontSize'),
// },
// {
// shortcutKeys: ['-'],
// actionDescription: 'Decrease font size',
// shortcutKeyDescription: '-',
// callback: () => actionHandler('decrementFontSize'),
// },
// {
// shortcutKeys: [']'],
// actionDescription: 'Increase margin width',
// shortcutKeyDescription: ']',
// callback: () => actionHandler('incrementMarginWidth'),
// },
// {
// shortcutKeys: ['['],
// actionDescription: 'Decrease margin width',
// shortcutKeyDescription: '[',
// callback: () => actionHandler('decrementMarginWidth'),
// },
{
shortcutKeys: ['d'],
actionDescription: 'Edit Display Settings',
shortcutKeyDescription: 'd',
callback: () => actionHandler('editDisplaySettings'),
},
{
shortcutKeys: ['l'],
actionDescription: 'Edit labels',
shortcutKeyDescription: 'l',
callback: () => actionHandler('setLabels'),
},
// {
// shortcutKeys: ['l'],
// actionDescription: 'Edit labels',
// shortcutKeyDescription: 'l',
// callback: () => actionHandler('setLabels'),
// },
]
}

View file

@ -10,6 +10,8 @@ const disabledTargets = ['INPUT', 'TEXTAREA']
]
*/
const KBAR_KEYS = ['control', 'meta', 'v', 'i', 's', 'n', '[', ']']
type KeyPressed = {
[name: string]: boolean
}
@ -52,7 +54,8 @@ export const useKeyboardShortcuts = (commands: KeyboardCommand[]): void => {
})
})
})
KBAR_KEYS.map((key) => currentKeys[key.toLowerCase()] = false)
return currentKeys
}, [commands])

View file

@ -0,0 +1,80 @@
import { gql } from 'graphql-request'
import { gqlFetcher } from '../networkHelpers'
import { LibraryItemsData } from './useGetLibraryItemsQuery'
export type LibraryItemsQueryInput = {
limit?: number
searchQuery?: string
}
export async function searchQuery({
limit = 10,
searchQuery,
}: LibraryItemsQueryInput): Promise<LibraryItemsData | undefined> {
const query = gql`
query Search($after: String, $first: Int, $query: String) {
search(first: $first, after: $after, query: $query) {
... on SearchSuccess {
edges {
cursor
node {
id
title
slug
url
pageType
contentReader
createdAt
isArchived
readingProgressPercent
readingProgressAnchorIndex
author
image
description
publishedAt
ownedByViewer
originalArticleUrl
uploadFileId
labels {
id
name
color
}
pageId
shortId
quote
annotation
state
siteName
subscription
readAt
}
}
pageInfo {
hasNextPage
hasPreviousPage
startCursor
endCursor
totalCount
}
}
... on SearchError {
errorCodes
}
}
}
`
const variables = {
first: limit,
query: searchQuery,
}
try {
const data = (await gqlFetcher(query, {...variables}))
return data as LibraryItemsData || undefined;
} catch (error) {
console.log('search error', error)
return undefined
}
}

View file

@ -32,6 +32,7 @@
"cookie": "^0.5.0",
"diff-match-patch": "^1.0.5",
"graphql-request": "^3.6.1",
"kbar": "^0.1.0-beta.35",
"nanoid": "^3.1.29",
"next": "^12.1.0",
"phosphor-react": "^1.4.0",

View file

@ -29,6 +29,7 @@ import { SetLabelsModal } from '../../../components/templates/article/SetLabelsM
import { DisplaySettingsModal } from '../../../components/templates/article/DisplaySettingsModal'
import { useReaderSettings } from '../../../lib/hooks/useReaderSettings'
import { SkeletonArticleContainer } from '../../../components/templates/article/SkeletonArticleContainer'
import { useRegisterActions } from 'kbar'
const PdfArticleContainerNoSSR = dynamic<PdfArticleContainerProps>(
@ -137,6 +138,23 @@ export default function Home(): JSX.Element {
})
}
}, [article, viewerData])
useRegisterActions([
{
id: 'open',
section: 'Article',
name: 'Open original article page',
shortcut: ['o'],
perform: () => actionHandler('openOriginalArticle')
},
{
id: 'back',
section: 'Article',
name: 'Back to library',
shortcut: ['u'],
perform: () => router.push(`/home`),
},
], [article])
if (articleFetchError && articleFetchError.indexOf('NOT_FOUND') > -1) {
router.push('/404')
@ -190,55 +208,55 @@ export default function Home(): JSX.Element {
/>
) : null}
</VStack>
{article && viewerData?.me && article.contentReader == 'PDF' ? (
<PdfArticleContainerNoSSR
article={article}
showHighlightsModal={showHighlightsModal}
setShowHighlightsModal={setShowHighlightsModal}
viewerUsername={viewerData.me?.profile?.username}
/>
) : (
<VStack
alignment="center"
distribution="center"
ref={scrollRef}
className="disable-webkit-callout"
css={{
'@smDown': {
background: theme.colors.grayBg.toString(),
}
}}
>
{article && viewerData?.me ? (
<ArticleContainer
article={article}
isAppleAppEmbed={false}
highlightBarDisabled={false}
highlightsBaseURL={`${webBaseURL}/${viewerData.me?.profile?.username}/${slug}/highlights`}
fontSize={readerSettings.fontSize}
margin={readerSettings.marginWidth}
lineHeight={readerSettings.lineHeight}
fontFamily={readerSettings.fontFamily}
labels={labels}
showHighlightsModal={showHighlightsModal}
setShowHighlightsModal={setShowHighlightsModal}
articleMutations={{
createHighlightMutation,
deleteHighlightMutation,
mergeHighlightMutation,
updateHighlightMutation,
articleReadingProgressMutation,
}}
/>
) : (
<SkeletonArticleContainer
margin={readerSettings.marginWidth}
lineHeight={readerSettings.lineHeight}
fontSize={readerSettings.fontSize}
/>
)}
</VStack>
{article && viewerData?.me && article.contentReader == 'PDF' ? (
<PdfArticleContainerNoSSR
article={article}
showHighlightsModal={showHighlightsModal}
setShowHighlightsModal={setShowHighlightsModal}
viewerUsername={viewerData.me?.profile?.username}
/>
) : (
<VStack
alignment="center"
distribution="center"
ref={scrollRef}
className="disable-webkit-callout"
css={{
'@smDown': {
background: theme.colors.grayBg.toString(),
}
}}
>
{article && viewerData?.me ? (
<ArticleContainer
article={article}
isAppleAppEmbed={false}
highlightBarDisabled={false}
highlightsBaseURL={`${webBaseURL}/${viewerData.me?.profile?.username}/${slug}/highlights`}
fontSize={readerSettings.fontSize}
margin={readerSettings.marginWidth}
lineHeight={readerSettings.lineHeight}
fontFamily={readerSettings.fontFamily}
labels={labels}
showHighlightsModal={showHighlightsModal}
setShowHighlightsModal={setShowHighlightsModal}
articleMutations={{
createHighlightMutation,
deleteHighlightMutation,
mergeHighlightMutation,
updateHighlightMutation,
articleReadingProgressMutation,
}}
/>
) : (
<SkeletonArticleContainer
margin={readerSettings.marginWidth}
lineHeight={readerSettings.lineHeight}
fontSize={readerSettings.fontSize}
/>
)}
</VStack>
)}
{article && readerSettings.showSetLabelsModal && (
<SetLabelsModal

View file

@ -2,12 +2,20 @@ import '../styles/globals.css'
import '../styles/articleInnerStyling.css'
import type { AppProps } from 'next/app'
import { IdProvider } from '@radix-ui/react-id'
import { useRouter } from 'next/router'
import { NextRouter, useRouter } from 'next/router'
import { useEffect, useState } from 'react'
import { Analytics, AnalyticsBrowser } from '@segment/analytics-next'
import { segmentApiKey } from '../lib/appConfig'
import { TooltipProvider } from '../components/elements/Tooltip'
import TopBarProgress from 'react-topbar-progress-indicator'
import {
KBarProvider,
KBarPortal,
KBarPositioner,
KBarAnimator,
KBarSearch,
} from 'kbar'
import { animatorStyle, KBarResultsComponents, searchStyle } from '../components/elements/KBar'
TopBarProgress.config({
barColors: {
@ -16,7 +24,22 @@ TopBarProgress.config({
},
shadowBlur: 0,
barThickness: 2,
});
})
const generateActions = (router: NextRouter) => {
const defaultActions = [
{
id: 'home',
section: 'Navigation',
name: 'Go to Home (Library) ',
shortcut: ['g', 'h'],
keywords: 'go home',
perform: () => router?.push('/home'),
},
]
return defaultActions
}
function OmnivoreApp({ Component, pageProps }: AppProps): JSX.Element {
const router = useRouter()
@ -51,11 +74,21 @@ function OmnivoreApp({ Component, pageProps }: AppProps): JSX.Element {
}, [router.events, analytics])
return (
<IdProvider>
<TooltipProvider delayDuration={200}>
<Component {...pageProps} />
</TooltipProvider>
</IdProvider>
<KBarProvider actions={generateActions(router)}>
<KBarPortal>
<KBarPositioner>
<KBarAnimator style={animatorStyle}>
<KBarSearch style={searchStyle} />
<KBarResultsComponents />
</KBarAnimator>
</KBarPositioner>
</KBarPortal>
<IdProvider>
<TooltipProvider delayDuration={200}>
<Component {...pageProps} />
</TooltipProvider>
</IdProvider>
</KBarProvider>
)
}

View file

@ -5020,6 +5020,28 @@
dependencies:
"@babel/runtime" "^7.13.10"
"@reach/observe-rect@^1.1.0":
version "1.2.0"
resolved "https://registry.yarnpkg.com/@reach/observe-rect/-/observe-rect-1.2.0.tgz#d7a6013b8aafcc64c778a0ccb83355a11204d3b2"
integrity sha512-Ba7HmkFgfQxZqqaeIWWkNK0rEhpxVQHIoVyW1YDSkGsGIXzcaW4deC8B0pZrNSSyLTdIk7y+5olKt5+g0GmFIQ==
"@reach/portal@^0.16.0":
version "0.16.2"
resolved "https://registry.yarnpkg.com/@reach/portal/-/portal-0.16.2.tgz#ca83696215ee03acc2bb25a5ae5d8793eaaf2f64"
integrity sha512-9ur/yxNkuVYTIjAcfi46LdKUvH0uYZPfEp4usWcpt6PIp+WDF57F/5deMe/uGi/B/nfDweQu8VVwuMVrCb97JQ==
dependencies:
"@reach/utils" "0.16.0"
tiny-warning "^1.0.3"
tslib "^2.3.0"
"@reach/utils@0.16.0":
version "0.16.0"
resolved "https://registry.yarnpkg.com/@reach/utils/-/utils-0.16.0.tgz#5b0777cf16a7cab1ddd4728d5d02762df0ba84ce"
integrity sha512-PCggBet3qaQmwFNcmQ/GqHSefadAFyNCUekq9RrWoaU9hh/S4iaFgf2MBMdM47eQj5i/Bk0Mm07cP/XPFlkN+Q==
dependencies:
tiny-warning "^1.0.3"
tslib "^2.3.0"
"@rushstack/eslint-patch@^1.0.8":
version "1.1.0"
resolved "https://registry.yarnpkg.com/@rushstack/eslint-patch/-/eslint-patch-1.1.0.tgz#7f698254aadf921e48dda8c0a6b304026b8a9323"
@ -10942,6 +10964,11 @@ comma-separated-tokens@^1.0.0:
resolved "https://registry.yarnpkg.com/comma-separated-tokens/-/comma-separated-tokens-1.0.8.tgz#632b80b6117867a158f1080ad498b2fbe7e3f5ea"
integrity sha512-GHuDRO12Sypu2cV70d1dkA2EUmXHgntrzbpvOB+Qy+49ypNfGgFQIC2fhhXbnyrJRynDCAARsT7Ou0M6hirpfw==
command-score@^0.1.2:
version "0.1.2"
resolved "https://registry.yarnpkg.com/command-score/-/command-score-0.1.2.tgz#b986ad7e8c0beba17552a56636c44ae38363d381"
integrity sha512-VtDvQpIJBvBatnONUsPzXYFVKQQAhuf3XTNOAsdBxCNO/QCtUUd8LSgjn0GVarBkCad6aJCZfXgrjYbl/KRr7w==
commander@^2.19.0, commander@^2.20.0, commander@^2.20.3:
version "2.20.3"
resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
@ -13357,6 +13384,11 @@ fast-diff@^1.1.2:
resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.2.0.tgz#73ee11982d86caaf7959828d519cfe927fac5f03"
integrity sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==
fast-equals@^2.0.3:
version "2.0.4"
resolved "https://registry.yarnpkg.com/fast-equals/-/fast-equals-2.0.4.tgz#3add9410585e2d7364c2deeb6a707beadb24b927"
integrity sha512-caj/ZmjHljPrZtbzJ3kfH5ia/k4mTJe/qSiXAGzxZWRZgsgDV0cvNaQULqUX8t0/JVlzzEdYOwCN5DmzTxoD4w==
fast-glob@^2.2.6:
version "2.2.7"
resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-2.2.7.tgz#6953857c3afa475fff92ee6015d52da70a4cd39d"
@ -17111,6 +17143,17 @@ jws@^4.0.0:
jwa "^2.0.0"
safe-buffer "^5.0.1"
kbar@^0.1.0-beta.35:
version "0.1.0-beta.35"
resolved "https://registry.yarnpkg.com/kbar/-/kbar-0.1.0-beta.35.tgz#48f6f021fa65793cdf9f5e8876db666f160eee47"
integrity sha512-lXA/AFfmeTBIC0+6wsqHPpU1ULI4MMgzX9cRKkpHh9BVij5t1EAJOFTLzQQBr/4jVzSYNwRogRHHU4oQAlAduQ==
dependencies:
"@reach/portal" "^0.16.0"
command-score "^0.1.2"
fast-equals "^2.0.3"
react-virtual "^2.8.2"
tiny-invariant "^1.2.0"
keyv@^3.0.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/keyv/-/keyv-3.1.0.tgz#ecc228486f69991e49e9476485a5be1e8fc5c4d9"
@ -21240,6 +21283,13 @@ react-twitter-widgets@^1.10.0:
dependencies:
loadjs "^4.2.0"
react-virtual@^2.8.2:
version "2.10.4"
resolved "https://registry.yarnpkg.com/react-virtual/-/react-virtual-2.10.4.tgz#08712f0acd79d7d6f7c4726f05651a13b24d8704"
integrity sha512-Ir6+oPQZTVHfa6+JL9M7cvMILstFZH/H3jqeYeKI4MSUX+rIruVwFC6nGVXw9wqAw8L0Kg2KvfXxI85OvYQdpQ==
dependencies:
"@reach/observe-rect" "^1.1.0"
react@^17.0.2:
version "17.0.2"
resolved "https://registry.yarnpkg.com/react/-/react-17.0.2.tgz#d0b5cc516d29eb3eee383f75b62864cfb6800037"
@ -23527,6 +23577,16 @@ tiny-hashes@^1.0.1:
resolved "https://registry.yarnpkg.com/tiny-hashes/-/tiny-hashes-1.0.1.tgz#ddbe9060312ddb4efe0a174bb3a27e1331c425a1"
integrity sha512-knIN5zj4fl7kW4EBU5sLP20DWUvi/rVouvJezV0UAym2DkQaqm365Nyc8F3QEiOvunNDMxR8UhcXd1d5g+Wg1g==
tiny-invariant@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.2.0.tgz#a1141f86b672a9148c72e978a19a73b9b94a15a9"
integrity sha512-1Uhn/aqw5C6RI4KejVeTg6mIS7IqxnLJ8Mv2tV5rTc0qWobay7pDUz6Wi392Cnc8ak1H0F2cjoRzb2/AW4+Fvg==
tiny-warning@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754"
integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==
title-case@^2.1.0:
version "2.1.1"
resolved "https://registry.yarnpkg.com/title-case/-/title-case-2.1.1.tgz#3e127216da58d2bc5becf137ab91dae3a7cd8faa"