Start adding allotment cleaning up navigation
This commit is contained in:
@ -64,7 +64,7 @@ export function LibraryGridCard(props: LinkedItemCardProps): JSX.Element {
|
||||
css={{
|
||||
pl: '0px',
|
||||
padding: '0px',
|
||||
width: '293px',
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
minHeight: '270px',
|
||||
background: 'white',
|
||||
|
||||
@ -68,19 +68,19 @@ export function LibraryListCard(props: LinkedItemCardProps): JSX.Element {
|
||||
borderStyle: 'none',
|
||||
borderBottom: 'none',
|
||||
borderRadius: '6px',
|
||||
width: '100vw',
|
||||
'@media (min-width: 768px)': {
|
||||
width: `calc(100vw - ${LIBRARY_LEFT_MENU_WIDTH})`,
|
||||
},
|
||||
'@media (min-width: 930px)': {
|
||||
width: '580px',
|
||||
},
|
||||
'@media (min-width: 1280px)': {
|
||||
width: '890px',
|
||||
},
|
||||
'@media (min-width: 1600px)': {
|
||||
width: '1200px',
|
||||
},
|
||||
width: '100%',
|
||||
// '@media (min-width: 768px)': {
|
||||
// width: `calc(100vw - ${LIBRARY_LEFT_MENU_WIDTH})`,
|
||||
// },
|
||||
// '@media (min-width: 930px)': {
|
||||
// width: '580px',
|
||||
// },
|
||||
// '@media (min-width: 1280px)': {
|
||||
// width: '890px',
|
||||
// },
|
||||
// '@media (min-width: 1600px)': {
|
||||
// width: '1200px',
|
||||
// },
|
||||
'@media (max-width: 930px)': {
|
||||
borderRadius: '0px',
|
||||
},
|
||||
|
||||
@ -1,17 +1,17 @@
|
||||
import { useCallback, useRef, useState } from 'react'
|
||||
import * as Progress from '@radix-ui/react-progress'
|
||||
import { File, Info } from 'phosphor-react'
|
||||
import { locale, timeZone } from '../../../lib/dateFormatting'
|
||||
import { showErrorToast, showSuccessToast } from '../../../lib/toastHelpers'
|
||||
import { Button } from '../../elements/Button'
|
||||
import { FormInput } from '../../elements/FormElements'
|
||||
import { Box, HStack, SpanBox, VStack } from '../../elements/LayoutPrimitives'
|
||||
import { locale, timeZone } from '../../lib/dateFormatting'
|
||||
import { showErrorToast, showSuccessToast } from '../../lib/toastHelpers'
|
||||
import { Button } from '../elements/Button'
|
||||
import { FormInput } from '../elements/FormElements'
|
||||
import { Box, HStack, SpanBox, VStack } from '../elements/LayoutPrimitives'
|
||||
import {
|
||||
ModalContent,
|
||||
ModalOverlay,
|
||||
ModalRoot,
|
||||
} from '../../elements/ModalPrimitives'
|
||||
import { CloseButton } from '../../elements/CloseButton'
|
||||
} from '../elements/ModalPrimitives'
|
||||
import { CloseButton } from '../elements/CloseButton'
|
||||
import { styled } from '@stitches/react'
|
||||
import Dropzone, {
|
||||
Accept,
|
||||
@ -20,17 +20,17 @@ import Dropzone, {
|
||||
FileRejection,
|
||||
} from 'react-dropzone'
|
||||
import { v4 as uuidv4 } from 'uuid'
|
||||
import { validateCsvFile } from '../../../utils/csvValidator'
|
||||
import { validateCsvFile } from '../../utils/csvValidator'
|
||||
import {
|
||||
uploadImportFileRequestMutation,
|
||||
UploadImportFileType,
|
||||
} from '../../../lib/networking/mutations/uploadImportFileMutation'
|
||||
import { uploadFileRequestMutation } from '../../../lib/networking/mutations/uploadFileMutation'
|
||||
} from '../../lib/networking/mutations/uploadImportFileMutation'
|
||||
import { uploadFileRequestMutation } from '../../lib/networking/mutations/uploadFileMutation'
|
||||
import axios from 'axios'
|
||||
import { theme } from '../../tokens/stitches.config'
|
||||
import { formatMessage } from '../../../locales/en/messages'
|
||||
import { subscribeMutation } from '../../../lib/networking/mutations/subscribeMutation'
|
||||
import { SubscriptionType } from '../../../lib/networking/queries/useGetSubscriptionsQuery'
|
||||
import { theme } from '../tokens/stitches.config'
|
||||
import { formatMessage } from '../../locales/en/messages'
|
||||
import { subscribeMutation } from '../../lib/networking/mutations/subscribeMutation'
|
||||
import { SubscriptionType } from '../../lib/networking/queries/useGetSubscriptionsQuery'
|
||||
|
||||
type TabName = 'link' | 'feed' | 'opml' | 'pdf' | 'import'
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { PageMetaData, PageMetaDataProps } from '../patterns/PageMetaData'
|
||||
import { Box, VStack } from '../elements/LayoutPrimitives'
|
||||
import { Box, HStack, VStack } from '../elements/LayoutPrimitives'
|
||||
import { ReactNode, useEffect, useState, useCallback } from 'react'
|
||||
import { useGetViewerQuery } from '../../lib/networking/queries/useGetViewerQuery'
|
||||
import { navigationCommands } from '../../lib/keyboardShortcuts/navigationShortcuts'
|
||||
@ -19,6 +19,10 @@ import { DEFAULT_HEADER_HEIGHT } from './homeFeed/HeaderSpacer'
|
||||
import { Button } from '../elements/Button'
|
||||
import { List } from 'phosphor-react'
|
||||
import { usePersistedState } from '../../lib/hooks/usePersistedState'
|
||||
import { Allotment } from 'allotment'
|
||||
import 'allotment/dist/style.css'
|
||||
import { LibrarySideBar } from './library/LibrarySideBar'
|
||||
import NoSsr from './NoSsr'
|
||||
|
||||
export type NavigationSection =
|
||||
| 'justread'
|
||||
@ -29,6 +33,7 @@ export type NavigationSection =
|
||||
|
||||
type NavigationLayoutProps = {
|
||||
children: ReactNode
|
||||
rightPane?: ReactNode
|
||||
section: NavigationSection
|
||||
pageMetaDataProps?: PageMetaDataProps
|
||||
}
|
||||
@ -41,7 +46,8 @@ export function NavigationLayout(props: NavigationLayoutProps): JSX.Element {
|
||||
const [showLogoutConfirmation, setShowLogoutConfirmation] = useState(false)
|
||||
const [showKeyboardCommandsModal, setShowKeyboardCommandsModal] =
|
||||
useState(false)
|
||||
const [showLeftMenu, setShowLeftMenu] = usePersistedState<boolean>({
|
||||
|
||||
const [showNavMenu, setShowNavMenu] = usePersistedState<boolean>({
|
||||
key: 'nav-show-menu',
|
||||
isSessionStorage: false,
|
||||
initialValue: true,
|
||||
@ -109,51 +115,37 @@ export function NavigationLayout(props: NavigationLayoutProps): JSX.Element {
|
||||
}, [showLogout])
|
||||
|
||||
return (
|
||||
<>
|
||||
<HStack css={{ width: '100vw', height: '100vh' }}>
|
||||
{props.pageMetaDataProps ? (
|
||||
<PageMetaData {...props.pageMetaDataProps} />
|
||||
) : null}
|
||||
<Box
|
||||
css={{
|
||||
height: '100%',
|
||||
width: '100vw',
|
||||
bg: '$thBackground2',
|
||||
<Header
|
||||
toggleMenu={() => {
|
||||
setShowNavMenu(!showNavMenu)
|
||||
}}
|
||||
>
|
||||
<Header
|
||||
toggleMenu={() => {
|
||||
setShowLeftMenu(!showLeftMenu)
|
||||
}}
|
||||
/>
|
||||
<NavigationMenu
|
||||
section={props.section}
|
||||
setShowAddLinkModal={() => {}}
|
||||
searchTerm=""
|
||||
applySearchQuery={() => {}}
|
||||
showFilterMenu={showNavMenu}
|
||||
setShowFilterMenu={setShowNavMenu}
|
||||
/>
|
||||
{props.children}
|
||||
{showLogoutConfirmation ? (
|
||||
<ConfirmationModal
|
||||
message={'Are you sure you want to log out?'}
|
||||
onAccept={logout}
|
||||
onOpenChange={() => setShowLogoutConfirmation(false)}
|
||||
/>
|
||||
{showLeftMenu && (
|
||||
<NavigationMenu
|
||||
section={props.section}
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||
setShowAddLinkModal={() => {}}
|
||||
searchTerm={''}
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||
applySearchQuery={(searchQuery: string) => {}}
|
||||
showFilterMenu={showLeftMenu}
|
||||
setShowFilterMenu={(show) => {
|
||||
setShowLeftMenu(show)
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
{props.children}
|
||||
{showLogoutConfirmation ? (
|
||||
<ConfirmationModal
|
||||
message={'Are you sure you want to log out?'}
|
||||
onAccept={logout}
|
||||
onOpenChange={() => setShowLogoutConfirmation(false)}
|
||||
/>
|
||||
) : null}
|
||||
{showKeyboardCommandsModal ? (
|
||||
<KeyboardShortcutListModal
|
||||
onOpenChange={() => setShowKeyboardCommandsModal(false)}
|
||||
/>
|
||||
) : null}
|
||||
</Box>
|
||||
</>
|
||||
) : null}
|
||||
{showKeyboardCommandsModal ? (
|
||||
<KeyboardShortcutListModal
|
||||
onOpenChange={() => setShowKeyboardCommandsModal(false)}
|
||||
/>
|
||||
) : null}
|
||||
</HStack>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@ -2,7 +2,7 @@ import { Box, HStack, VStack } from '../../elements/LayoutPrimitives'
|
||||
import { LibraryFilterMenu } from '../navMenu/LibraryMenu'
|
||||
import { DiscoverHeader } from './DiscoverHeader/DiscoverHeader'
|
||||
import { useRouter } from 'next/router'
|
||||
import React, { useCallback, useEffect, useState } from "react"
|
||||
import React, { useCallback, useEffect, useState } from 'react'
|
||||
import { DiscoverItemFeed } from './DiscoverFeed/DiscoverFeed'
|
||||
import { useGetViewerQuery } from '../../../lib/networking/queries/useGetViewerQuery'
|
||||
import toast from 'react-hot-toast'
|
||||
@ -10,13 +10,13 @@ import { Button } from '../../elements/Button'
|
||||
import { showErrorToast } from '../../../lib/toastHelpers'
|
||||
import {
|
||||
saveDiscoverArticleMutation,
|
||||
SaveDiscoverArticleOutput
|
||||
} from "../../../lib/networking/mutations/saveDiscoverArticle"
|
||||
import { saveUrlMutation } from "../../../lib/networking/mutations/saveUrlMutation"
|
||||
import { useFetchMore } from "../../../lib/hooks/useFetchMoreScroll"
|
||||
import { AddLinkModal } from "../homeFeed/AddLinkModal"
|
||||
import { useGetDiscoverFeedItems } from "../../../lib/networking/queries/useGetDiscoverFeedItems"
|
||||
import { useGetDiscoverFeeds } from "../../../lib/networking/queries/useGetDiscoverFeeds"
|
||||
SaveDiscoverArticleOutput,
|
||||
} from '../../../lib/networking/mutations/saveDiscoverArticle'
|
||||
import { saveUrlMutation } from '../../../lib/networking/mutations/saveUrlMutation'
|
||||
import { useFetchMore } from '../../../lib/hooks/useFetchMoreScroll'
|
||||
import { AddLinkModal } from '../AddLinkModal'
|
||||
import { useGetDiscoverFeedItems } from '../../../lib/networking/queries/useGetDiscoverFeedItems'
|
||||
import { useGetDiscoverFeeds } from '../../../lib/networking/queries/useGetDiscoverFeeds'
|
||||
|
||||
export type LayoutType = 'LIST_LAYOUT' | 'GRID_LAYOUT'
|
||||
|
||||
@ -27,8 +27,8 @@ export function DiscoverContainer(): JSX.Element {
|
||||
const viewer = useGetViewerQuery()
|
||||
const [showFilterMenu, setShowFilterMenu] = useState(false)
|
||||
const [layoutType, setLayoutType] = useState<LayoutType>('GRID_LAYOUT')
|
||||
const [showAddLinkModal, setShowAddLinkModal] = useState(false);
|
||||
const {feeds, revalidate, isValidating} = useGetDiscoverFeeds()
|
||||
const [showAddLinkModal, setShowAddLinkModal] = useState(false)
|
||||
const { feeds, revalidate, isValidating } = useGetDiscoverFeeds()
|
||||
const topics = [
|
||||
{
|
||||
title: 'Popular',
|
||||
@ -73,8 +73,16 @@ export function DiscoverContainer(): JSX.Element {
|
||||
},
|
||||
]
|
||||
|
||||
const [selectedFeed, setSelectedFeed] = useState("All Feeds");
|
||||
const { discoverItems, setTopic, activeTopic, isLoading, hasMore, setPage, page } = useGetDiscoverFeedItems(topics[1], selectedFeed)
|
||||
const [selectedFeed, setSelectedFeed] = useState('All Feeds')
|
||||
const {
|
||||
discoverItems,
|
||||
setTopic,
|
||||
activeTopic,
|
||||
isLoading,
|
||||
hasMore,
|
||||
setPage,
|
||||
page,
|
||||
} = useGetDiscoverFeedItems(topics[1], selectedFeed)
|
||||
const handleFetchMore = useCallback(() => {
|
||||
if (isLoading || !hasMore) {
|
||||
return
|
||||
@ -88,7 +96,11 @@ export function DiscoverContainer(): JSX.Element {
|
||||
timezone: string,
|
||||
locale: string
|
||||
): Promise<SaveDiscoverArticleOutput | undefined> => {
|
||||
const result = await saveDiscoverArticleMutation({discoverArticleId, timezone, locale})
|
||||
const result = await saveDiscoverArticleMutation({
|
||||
discoverArticleId,
|
||||
timezone,
|
||||
locale,
|
||||
})
|
||||
if (result?.saveDiscoverArticle) {
|
||||
toast(
|
||||
() => (
|
||||
@ -160,8 +172,8 @@ export function DiscoverContainer(): JSX.Element {
|
||||
}, [])
|
||||
|
||||
const setTopicAndReturnToTop = (topic: TopicTabData) => {
|
||||
window.scroll(0,0);
|
||||
setTopic(topic);
|
||||
window.scroll(0, 0)
|
||||
setTopic(topic)
|
||||
}
|
||||
|
||||
return (
|
||||
@ -204,12 +216,12 @@ export function DiscoverContainer(): JSX.Element {
|
||||
items={discoverItems ?? []}
|
||||
viewer={viewer.viewerData?.me}
|
||||
/>
|
||||
{ showAddLinkModal &&
|
||||
{showAddLinkModal && (
|
||||
<AddLinkModal
|
||||
handleLinkSubmission={handleLinkSave}
|
||||
onOpenChange={() => setShowAddLinkModal(false)}
|
||||
/>
|
||||
}
|
||||
)}
|
||||
</HStack>
|
||||
</VStack>
|
||||
)
|
||||
|
||||
@ -32,13 +32,13 @@ import { ConfirmationModal } from '../../patterns/ConfirmationModal'
|
||||
import { LinkedItemCardAction } from '../../patterns/LibraryCards/CardTypes'
|
||||
import { LinkedItemCard } from '../../patterns/LibraryCards/LinkedItemCard'
|
||||
import { Box, HStack, SpanBox, VStack } from './../../elements/LayoutPrimitives'
|
||||
import { AddLinkModal } from './AddLinkModal'
|
||||
import { AddLinkModal } from '../AddLinkModal'
|
||||
import { EditLibraryItemModal } from './EditItemModals'
|
||||
import { EmptyLibrary } from './EmptyLibrary'
|
||||
import { HighlightItemsLayout } from './HighlightsLayout'
|
||||
import { LibraryFilterMenu } from '../navMenu/LibraryMenu'
|
||||
import { LibraryLegacyMenu } from '../navMenu/LibraryLegacyMenu'
|
||||
import { LibraryHeader, MultiSelectMode } from './LibraryHeader'
|
||||
import { LegacyLibraryHeader, MultiSelectMode } from './LibraryHeader'
|
||||
import { UploadModal } from '../UploadModal'
|
||||
import { BulkAction } from '../../../lib/networking/mutations/bulkActionMutation'
|
||||
import { bulkActionMutation } from '../../../lib/networking/mutations/bulkActionMutation'
|
||||
@ -975,7 +975,7 @@ function HomeFeedGrid(props: HomeFeedContentProps): JSX.Element {
|
||||
}}
|
||||
>
|
||||
{props.mode != 'highlights' && (
|
||||
<LibraryHeader
|
||||
<LegacyLibraryHeader
|
||||
layout={layout}
|
||||
viewer={viewerData?.me}
|
||||
updateLayout={updateLayout}
|
||||
|
||||
@ -63,7 +63,7 @@ export const headerControlWidths = (
|
||||
}
|
||||
}
|
||||
|
||||
export function LibraryHeader(props: LibraryHeaderProps): JSX.Element {
|
||||
export function LegacyLibraryHeader(props: LibraryHeaderProps): JSX.Element {
|
||||
const [small, setSmall] = useState(false)
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
@ -9,12 +9,29 @@ import { TrashIcon } from '../../elements/icons/TrashIcon'
|
||||
import { ConfirmationModal } from '../../patterns/ConfirmationModal'
|
||||
import { AddBulkLabelsModal } from '../article/AddBulkLabelsModal'
|
||||
import { X } from 'phosphor-react'
|
||||
import { LibraryHeaderProps } from './LibraryHeader'
|
||||
import { MultiSelectMode } from './LibraryHeader'
|
||||
import { HeaderCheckboxIcon } from '../../elements/icons/HeaderCheckboxIcon'
|
||||
import { Label } from '../../../lib/networking/fragments/labelFragment'
|
||||
import { MarkAsReadIcon } from '../../elements/icons/MarkAsReadIcon'
|
||||
import { UserBasicData } from '../../../lib/networking/queries/useGetViewerQuery'
|
||||
|
||||
export const MultiSelectControls = (props: LibraryHeaderProps): JSX.Element => {
|
||||
export type MultiSelectProps = {
|
||||
viewer: UserBasicData | undefined
|
||||
|
||||
searchTerm: string | undefined
|
||||
applySearchQuery: (searchQuery: string) => void
|
||||
|
||||
showFilterMenu: boolean
|
||||
setShowFilterMenu: (show: boolean) => void
|
||||
|
||||
numItemsSelected: number
|
||||
multiSelectMode: MultiSelectMode
|
||||
setMultiSelectMode: (mode: MultiSelectMode) => void
|
||||
|
||||
performMultiSelectAction: (action: BulkAction, labelIds?: string[]) => void
|
||||
}
|
||||
|
||||
export const MultiSelectControls = (props: MultiSelectProps): JSX.Element => {
|
||||
const [showConfirmDelete, setShowConfirmDelete] = useState(false)
|
||||
const [showLabelsModal, setShowLabelsModal] = useState(false)
|
||||
// Don't change on immediate hover, the button has to be blurred at least once
|
||||
@ -146,7 +163,7 @@ export const MultiSelectControls = (props: LibraryHeaderProps): JSX.Element => {
|
||||
)
|
||||
}
|
||||
|
||||
export const CheckBoxButton = (props: LibraryHeaderProps): JSX.Element => {
|
||||
export const CheckBoxButton = (props: MultiSelectProps): JSX.Element => {
|
||||
return (
|
||||
<Button
|
||||
title="Select multiple"
|
||||
@ -171,7 +188,7 @@ export const CheckBoxButton = (props: LibraryHeaderProps): JSX.Element => {
|
||||
)
|
||||
}
|
||||
|
||||
export const ArchiveButton = (props: LibraryHeaderProps): JSX.Element => {
|
||||
export const ArchiveButton = (props: MultiSelectProps): JSX.Element => {
|
||||
const [color, setColor] = useState<string>(
|
||||
theme.colors.thTextContrast2.toString()
|
||||
)
|
||||
@ -206,7 +223,7 @@ export const ArchiveButton = (props: LibraryHeaderProps): JSX.Element => {
|
||||
)
|
||||
}
|
||||
|
||||
export const MarkAsReadButton = (props: LibraryHeaderProps): JSX.Element => {
|
||||
export const MarkAsReadButton = (props: MultiSelectProps): JSX.Element => {
|
||||
const [color, setColor] = useState<string>(
|
||||
theme.colors.thTextContrast2.toString()
|
||||
)
|
||||
@ -321,7 +338,7 @@ export const RemoveItemsButton = (
|
||||
)
|
||||
}
|
||||
|
||||
export const CancelButton = (props: LibraryHeaderProps): JSX.Element => {
|
||||
export const CancelButton = (props: MultiSelectProps): JSX.Element => {
|
||||
const [color, setColor] = useState<string>(
|
||||
theme.colors.thTextContrast2.toString()
|
||||
)
|
||||
|
||||
1275
packages/web/components/templates/library/LibraryContainer.tsx
Normal file
1275
packages/web/components/templates/library/LibraryContainer.tsx
Normal file
File diff suppressed because it is too large
Load Diff
418
packages/web/components/templates/library/LibraryHeader.tsx
Normal file
418
packages/web/components/templates/library/LibraryHeader.tsx
Normal file
@ -0,0 +1,418 @@
|
||||
import { useEffect, useRef, useState } from 'react'
|
||||
import { Box, HStack, SpanBox, VStack } from '../../elements/LayoutPrimitives'
|
||||
import { theme } from '../../tokens/stitches.config'
|
||||
import { FormInput } from '../../elements/FormElements'
|
||||
import { searchBarCommands } from '../../../lib/keyboardShortcuts/navigationShortcuts'
|
||||
import { useKeyboardShortcuts } from '../../../lib/keyboardShortcuts/useKeyboardShortcuts'
|
||||
import { Button, IconButton } from '../../elements/Button'
|
||||
import { FunnelSimple, X } from 'phosphor-react'
|
||||
import { LayoutType, LibraryMode } from '../homeFeed/HomeFeedContainer'
|
||||
import { OmnivoreSmallLogo } from '../../elements/images/OmnivoreNameLogo'
|
||||
import { DEFAULT_HEADER_HEIGHT, HeaderSpacer } from '../homeFeed/HeaderSpacer'
|
||||
import { LIBRARY_LEFT_MENU_WIDTH } from '../navMenu/LibraryMenu'
|
||||
import { BulkAction } from '../../../lib/networking/mutations/bulkActionMutation'
|
||||
import { HeaderToggleGridIcon } from '../../elements/icons/HeaderToggleGridIcon'
|
||||
import { HeaderToggleListIcon } from '../../elements/icons/HeaderToggleListIcon'
|
||||
import { HeaderToggleTLDRIcon } from '../../elements/icons/HeaderToggleTLDRIcon'
|
||||
import { UserBasicData } from '../../../lib/networking/queries/useGetViewerQuery'
|
||||
import { userHasFeature } from '../../../lib/featureFlag'
|
||||
import {
|
||||
MultiSelectControls,
|
||||
CheckBoxButton,
|
||||
} from '../homeFeed/MultiSelectControls'
|
||||
|
||||
export type MultiSelectMode = 'off' | 'none' | 'some' | 'visible' | 'search'
|
||||
|
||||
export type LibraryHeaderProps = {
|
||||
viewer: UserBasicData | undefined
|
||||
|
||||
layout: LayoutType
|
||||
updateLayout: (layout: LayoutType) => void
|
||||
|
||||
searchTerm: string | undefined
|
||||
applySearchQuery: (searchQuery: string) => void
|
||||
|
||||
showFilterMenu: boolean
|
||||
setShowFilterMenu: (show: boolean) => void
|
||||
|
||||
numItemsSelected: number
|
||||
multiSelectMode: MultiSelectMode
|
||||
setMultiSelectMode: (mode: MultiSelectMode) => void
|
||||
|
||||
performMultiSelectAction: (action: BulkAction, labelIds?: string[]) => void
|
||||
}
|
||||
|
||||
export const headerControlWidths = (
|
||||
layout: LayoutType,
|
||||
multiSelectMode: MultiSelectMode
|
||||
) => {
|
||||
return {
|
||||
width: '95%',
|
||||
'@mdDown': {
|
||||
width: '100%',
|
||||
},
|
||||
'@media (min-width: 930px)': {
|
||||
width: '620px',
|
||||
},
|
||||
'@media (min-width: 1280px)': {
|
||||
width: '940px',
|
||||
},
|
||||
'@media (min-width: 1600px)': {
|
||||
width: '1232px',
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
export function LibraryHeader(props: LibraryHeaderProps): JSX.Element {
|
||||
const [small, setSmall] = useState(false)
|
||||
|
||||
useEffect(() => {
|
||||
const handleScroll = () => {
|
||||
setSmall(window.scrollY > 40)
|
||||
}
|
||||
if (typeof window !== 'undefined') {
|
||||
window.addEventListener('scroll', handleScroll)
|
||||
}
|
||||
return () => {
|
||||
window.removeEventListener('scroll', handleScroll)
|
||||
}
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<>
|
||||
<VStack
|
||||
alignment="start"
|
||||
distribution="start"
|
||||
css={{
|
||||
width: '100%',
|
||||
px: '70px',
|
||||
bg: '$thLibraryBackground',
|
||||
// position: 'sticky',
|
||||
left: LIBRARY_LEFT_MENU_WIDTH,
|
||||
height: small ? '60px' : DEFAULT_HEADER_HEIGHT,
|
||||
transition: 'height 0.5s',
|
||||
'@lgDown': { px: '20px' },
|
||||
'@mdDown': {
|
||||
px: '10px',
|
||||
left: '0px',
|
||||
right: '0',
|
||||
},
|
||||
}}
|
||||
>
|
||||
<LargeHeaderLayout {...props} />
|
||||
</VStack>
|
||||
|
||||
{/* This spacer is put in to push library content down
|
||||
below the fixed header height. */}
|
||||
<HeaderSpacer />
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
function LargeHeaderLayout(props: LibraryHeaderProps): JSX.Element {
|
||||
return (
|
||||
<HStack
|
||||
alignment="center"
|
||||
distribution="start"
|
||||
css={{
|
||||
gap: '10px',
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
}}
|
||||
>
|
||||
{props.multiSelectMode !== 'off' ? (
|
||||
<>
|
||||
<MultiSelectControls {...props} />
|
||||
</>
|
||||
) : (
|
||||
<HeaderControls {...props} />
|
||||
)}
|
||||
</HStack>
|
||||
)
|
||||
}
|
||||
|
||||
const HeaderControls = (props: LibraryHeaderProps): JSX.Element => {
|
||||
const [searchBoxFocused, setSearchBoxFocused] = useState(false)
|
||||
|
||||
return (
|
||||
<>
|
||||
{!searchBoxFocused && (
|
||||
<SpanBox
|
||||
css={{
|
||||
display: 'none',
|
||||
'@mdDown': { display: 'flex' },
|
||||
}}
|
||||
>
|
||||
<MenuHeaderButton {...props} />
|
||||
</SpanBox>
|
||||
)}
|
||||
|
||||
<SearchBox
|
||||
{...props}
|
||||
searchBoxFocused={searchBoxFocused}
|
||||
setSearchBoxFocused={setSearchBoxFocused}
|
||||
/>
|
||||
|
||||
<SpanBox css={{ display: 'flex', ml: 'auto', gap: '10px' }}>
|
||||
{/* {userHasFeature(props.viewer, 'ai-summaries') && (
|
||||
<Button
|
||||
title="TLDR Summaries"
|
||||
style="plainIcon"
|
||||
css={{
|
||||
display: 'flex',
|
||||
marginLeft: 'auto',
|
||||
'&:hover': { opacity: '1.0' },
|
||||
}}
|
||||
onClick={(e) => {
|
||||
if (props.mode == 'reads') {
|
||||
props.setMode('tldr')
|
||||
} else {
|
||||
props.setMode('reads')
|
||||
}
|
||||
e.preventDefault()
|
||||
}}
|
||||
>
|
||||
<HeaderToggleTLDRIcon />
|
||||
</Button>
|
||||
)} */}
|
||||
|
||||
<Button
|
||||
title={
|
||||
props.layout == 'GRID_LAYOUT'
|
||||
? 'Switch to list layout'
|
||||
: 'Switch to grid layout'
|
||||
}
|
||||
style="plainIcon"
|
||||
css={{
|
||||
display: 'flex',
|
||||
marginLeft: 'auto',
|
||||
'&:hover': { opacity: '1.0' },
|
||||
}}
|
||||
onClick={(e) => {
|
||||
props.updateLayout(
|
||||
props.layout == 'GRID_LAYOUT' ? 'LIST_LAYOUT' : 'GRID_LAYOUT'
|
||||
)
|
||||
e.preventDefault()
|
||||
}}
|
||||
>
|
||||
{props.layout == 'LIST_LAYOUT' ? (
|
||||
<HeaderToggleGridIcon />
|
||||
) : (
|
||||
<HeaderToggleListIcon />
|
||||
)}
|
||||
</Button>
|
||||
</SpanBox>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
type MenuHeaderButtonProps = {
|
||||
showFilterMenu: boolean
|
||||
setShowFilterMenu: (show: boolean) => void
|
||||
}
|
||||
|
||||
export function MenuHeaderButton(props: MenuHeaderButtonProps): JSX.Element {
|
||||
return (
|
||||
<HStack
|
||||
css={{
|
||||
width: '67px',
|
||||
height: '40px',
|
||||
bg: props.showFilterMenu ? '$thTextContrast2' : '$thBackground2',
|
||||
borderRadius: '5px',
|
||||
px: '5px',
|
||||
cursor: 'pointer',
|
||||
}}
|
||||
alignment="center"
|
||||
distribution="around"
|
||||
onClick={() => {
|
||||
props.setShowFilterMenu(!props.showFilterMenu)
|
||||
}}
|
||||
>
|
||||
<OmnivoreSmallLogo
|
||||
size={20}
|
||||
strokeColor={
|
||||
props.showFilterMenu
|
||||
? theme.colors.thBackground.toString()
|
||||
: theme.colors.thTextContrast2.toString()
|
||||
}
|
||||
/>
|
||||
<FunnelSimple
|
||||
size={20}
|
||||
color={
|
||||
props.showFilterMenu
|
||||
? theme.colors.thBackground.toString()
|
||||
: theme.colors.thTextContrast2.toString()
|
||||
}
|
||||
/>
|
||||
</HStack>
|
||||
)
|
||||
}
|
||||
|
||||
type SearchBoxProps = LibraryHeaderProps & {
|
||||
searchBoxFocused: boolean
|
||||
setSearchBoxFocused: (show: boolean) => void
|
||||
}
|
||||
|
||||
export function SearchBox(props: SearchBoxProps): JSX.Element {
|
||||
const inputRef = useRef<HTMLInputElement | null>(null)
|
||||
const [searchTerm, setSearchTerm] = useState(props.searchTerm ?? '')
|
||||
|
||||
useEffect(() => {
|
||||
setSearchTerm(props.searchTerm ?? '')
|
||||
}, [props.searchTerm])
|
||||
|
||||
useKeyboardShortcuts(
|
||||
searchBarCommands((action) => {
|
||||
if (action === 'focusSearchBar' && inputRef.current) {
|
||||
inputRef.current.select()
|
||||
}
|
||||
if (action == 'clearSearch' && inputRef.current) {
|
||||
setSearchTerm('')
|
||||
props.applySearchQuery('')
|
||||
}
|
||||
})
|
||||
)
|
||||
|
||||
return (
|
||||
<Box
|
||||
css={{
|
||||
height: '38px',
|
||||
width: '100%',
|
||||
maxWidth: '521px',
|
||||
bg: '$thLibrarySearchbox',
|
||||
borderRadius: '6px',
|
||||
boxShadow: props.searchBoxFocused
|
||||
? 'none'
|
||||
: '0 1px 3px 0 rgba(0, 0, 0, 0.1),0 1px 2px 0 rgba(0, 0, 0, 0.06);',
|
||||
}}
|
||||
>
|
||||
<HStack
|
||||
alignment="center"
|
||||
distribution="start"
|
||||
css={{ width: '100%', height: '100%' }}
|
||||
>
|
||||
<HStack
|
||||
alignment="center"
|
||||
distribution="center"
|
||||
css={{
|
||||
width: '53px',
|
||||
height: '100%',
|
||||
display: 'flex',
|
||||
bg: props.multiSelectMode !== 'off' ? '$ctaBlue' : 'transparent',
|
||||
borderTopLeftRadius: '6px',
|
||||
borderBottomLeftRadius: '6px',
|
||||
'--checkbox-color': 'var(--colors-thLibraryMultiselectCheckbox)',
|
||||
'&:hover': {
|
||||
bg: '$thLibraryMultiselectHover',
|
||||
'--checkbox-color':
|
||||
'var(--colors-thLibraryMultiselectCheckboxHover)',
|
||||
},
|
||||
}}
|
||||
>
|
||||
<CheckBoxButton {...props} />
|
||||
</HStack>
|
||||
<HStack
|
||||
alignment="center"
|
||||
distribution="start"
|
||||
css={{
|
||||
border: props.searchBoxFocused
|
||||
? '2px solid $searchActiveOutline'
|
||||
: '2px solid transparent',
|
||||
borderTopRightRadius: '6px',
|
||||
borderBottomRightRadius: '6px',
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
}}
|
||||
>
|
||||
<form
|
||||
onSubmit={async (event) => {
|
||||
event.preventDefault()
|
||||
props.applySearchQuery(searchTerm || '')
|
||||
inputRef.current?.blur()
|
||||
}}
|
||||
style={{ width: '100%' }}
|
||||
>
|
||||
<FormInput
|
||||
ref={inputRef}
|
||||
type="text"
|
||||
value={searchTerm}
|
||||
autoFocus={false}
|
||||
placeholder="Search keywords or labels"
|
||||
onFocus={(event) => {
|
||||
event.target.select()
|
||||
props.setSearchBoxFocused(true)
|
||||
}}
|
||||
onBlur={() => {
|
||||
props.setSearchBoxFocused(false)
|
||||
}}
|
||||
onChange={(event) => {
|
||||
setSearchTerm(event.target.value)
|
||||
}}
|
||||
onKeyDown={(event) => {
|
||||
const key = event.key.toLowerCase()
|
||||
if (key == 'escape') {
|
||||
event.currentTarget.blur()
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</form>
|
||||
<HStack
|
||||
alignment="center"
|
||||
css={{
|
||||
py: '15px',
|
||||
mr: '10px',
|
||||
marginLeft: 'auto',
|
||||
}}
|
||||
>
|
||||
<CancelSearchButton
|
||||
onClick={() => {
|
||||
setSearchTerm('in:inbox')
|
||||
props.applySearchQuery('')
|
||||
inputRef.current?.blur()
|
||||
}}
|
||||
/>
|
||||
</HStack>
|
||||
</HStack>
|
||||
</HStack>
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
|
||||
type CancelSearchButtonProps = {
|
||||
onClick: () => void
|
||||
}
|
||||
|
||||
const CancelSearchButton = (props: CancelSearchButtonProps): JSX.Element => {
|
||||
const [color, setColor] = useState<string>(
|
||||
theme.colors.thTextContrast2.toString()
|
||||
)
|
||||
return (
|
||||
<Button
|
||||
title="Cancel"
|
||||
style="plainIcon"
|
||||
css={{
|
||||
p: '5px',
|
||||
display: 'flex',
|
||||
'&:hover': {
|
||||
bg: '$ctaBlue',
|
||||
borderRadius: '100px',
|
||||
opacity: 1.0,
|
||||
},
|
||||
}}
|
||||
onMouseEnter={(event) => {
|
||||
setColor('white')
|
||||
event.preventDefault()
|
||||
}}
|
||||
onMouseLeave={(event) => {
|
||||
setColor(theme.colors.thTextContrast2.toString())
|
||||
event.preventDefault()
|
||||
}}
|
||||
onClick={(event) => {
|
||||
event.preventDefault()
|
||||
props.onClick()
|
||||
}}
|
||||
>
|
||||
<X width={19} height={19} color={color} />
|
||||
</Button>
|
||||
)
|
||||
}
|
||||
@ -0,0 +1,23 @@
|
||||
import { Allotment } from 'allotment'
|
||||
import 'allotment/dist/style.css'
|
||||
import { useGetViewerQuery } from '../../../lib/networking/queries/useGetViewerQuery'
|
||||
import { useRouter } from 'next/router'
|
||||
import { useKBar } from 'kbar'
|
||||
import { useState } from 'react'
|
||||
import { LibraryContainer } from './LibraryContainer'
|
||||
import { LibrarySideBar } from './LibrarySideBar'
|
||||
|
||||
export function LibraryItemsContainer(): JSX.Element {
|
||||
const router = useRouter()
|
||||
|
||||
return (
|
||||
<Allotment>
|
||||
<Allotment.Pane minSize={200}>
|
||||
<LibraryContainer />
|
||||
</Allotment.Pane>
|
||||
<Allotment.Pane snap maxSize={230}>
|
||||
<LibrarySideBar />
|
||||
</Allotment.Pane>
|
||||
</Allotment>
|
||||
)
|
||||
}
|
||||
62
packages/web/components/templates/library/LibrarySideBar.tsx
Normal file
62
packages/web/components/templates/library/LibrarySideBar.tsx
Normal file
@ -0,0 +1,62 @@
|
||||
import { Action, createAction, useKBar, useRegisterActions } from 'kbar'
|
||||
import debounce from 'lodash/debounce'
|
||||
import { useRouter } from 'next/router'
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
|
||||
import { Toaster } from 'react-hot-toast'
|
||||
import TopBarProgress from 'react-topbar-progress-indicator'
|
||||
import { useFetchMore } from '../../../lib/hooks/useFetchMoreScroll'
|
||||
import { usePersistedState } from '../../../lib/hooks/usePersistedState'
|
||||
import { libraryListCommands } from '../../../lib/keyboardShortcuts/navigationShortcuts'
|
||||
import { useKeyboardShortcuts } from '../../../lib/keyboardShortcuts/useKeyboardShortcuts'
|
||||
import {
|
||||
PageType,
|
||||
State,
|
||||
} from '../../../lib/networking/fragments/articleFragment'
|
||||
import {
|
||||
SearchItem,
|
||||
TypeaheadSearchItemsData,
|
||||
typeaheadSearchQuery,
|
||||
} from '../../../lib/networking/queries/typeaheadSearch'
|
||||
import type {
|
||||
LibraryItem,
|
||||
LibraryItemsQueryInput,
|
||||
} from '../../../lib/networking/queries/useGetLibraryItemsQuery'
|
||||
import { useGetLibraryItemsQuery } from '../../../lib/networking/queries/useGetLibraryItemsQuery'
|
||||
import {
|
||||
useGetViewerQuery,
|
||||
UserBasicData,
|
||||
} from '../../../lib/networking/queries/useGetViewerQuery'
|
||||
import { Button } from '../../elements/Button'
|
||||
import { StyledText } from '../../elements/StyledText'
|
||||
import { ConfirmationModal } from '../../patterns/ConfirmationModal'
|
||||
import { LinkedItemCardAction } from '../../patterns/LibraryCards/CardTypes'
|
||||
import { LinkedItemCard } from '../../patterns/LibraryCards/LinkedItemCard'
|
||||
import { Box, HStack, SpanBox, VStack } from '../../elements/LayoutPrimitives'
|
||||
import { AddLinkModal } from '../AddLinkModal'
|
||||
import { EditLibraryItemModal } from '../homeFeed/EditItemModals'
|
||||
import { EmptyLibrary } from '../homeFeed/EmptyLibrary'
|
||||
import { LegacyLibraryHeader, MultiSelectMode } from '../homeFeed/LibraryHeader'
|
||||
import { UploadModal } from '../UploadModal'
|
||||
import { BulkAction } from '../../../lib/networking/mutations/bulkActionMutation'
|
||||
import { bulkActionMutation } from '../../../lib/networking/mutations/bulkActionMutation'
|
||||
import {
|
||||
showErrorToast,
|
||||
showSuccessToast,
|
||||
showSuccessToastWithAction,
|
||||
} from '../../../lib/toastHelpers'
|
||||
import { SetPageLabelsModalPresenter } from '../article/SetLabelsModalPresenter'
|
||||
import { NotebookPresenter } from '../article/NotebookPresenter'
|
||||
import { saveUrlMutation } from '../../../lib/networking/mutations/saveUrlMutation'
|
||||
import { articleQuery } from '../../../lib/networking/queries/useGetArticleQuery'
|
||||
import { PinnedButtons } from '../homeFeed/PinnedButtons'
|
||||
import { PinnedSearch } from '../../../pages/settings/pinned-searches'
|
||||
import { FetchItemsError } from '../homeFeed/FetchItemsError'
|
||||
import { LibraryHeader } from './LibraryHeader'
|
||||
|
||||
type LibrarySideBarProps = {
|
||||
text: string
|
||||
}
|
||||
|
||||
export function LibrarySideBar(props: LibrarySideBarProps): JSX.Element {
|
||||
return <VStack css={{ width: '100%', height: '100%' }}>{props.text}</VStack>
|
||||
}
|
||||
@ -105,9 +105,9 @@ export function NavigationMenu(props: LibraryFilterMenuProps): JSX.Element {
|
||||
left: '0px',
|
||||
top: '0px',
|
||||
position: 'fixed',
|
||||
bg: '$thLeftMenuBackground',
|
||||
height: '100%',
|
||||
width: LIBRARY_LEFT_MENU_WIDTH,
|
||||
bg: '$thLeftMenuBackground',
|
||||
overflowY: 'auto',
|
||||
overflowX: 'hidden',
|
||||
'&::-webkit-scrollbar': {
|
||||
@ -200,7 +200,7 @@ const LibraryNav = (props: LibraryFilterMenuProps): JSX.Element => {
|
||||
gap: '5px',
|
||||
width: '100%',
|
||||
borderBottom: '1px solid $thBorderColor',
|
||||
px: '15px',
|
||||
px: '0px',
|
||||
pb: '25px',
|
||||
}}
|
||||
alignment="start"
|
||||
@ -213,13 +213,6 @@ const LibraryNav = (props: LibraryFilterMenuProps): JSX.Element => {
|
||||
isSelected={props.section == 'home'}
|
||||
icon={<HomeIcon color={theme.colors.thHomeIcon.toString()} />}
|
||||
/>
|
||||
<NavButton
|
||||
{...props}
|
||||
text="Subscriptions"
|
||||
section="subscriptions"
|
||||
isSelected={props.section == 'subscriptions'}
|
||||
icon={<FollowingIcon color="#F59932" />}
|
||||
/>
|
||||
<NavButton
|
||||
{...props}
|
||||
text="Library"
|
||||
@ -227,6 +220,13 @@ const LibraryNav = (props: LibraryFilterMenuProps): JSX.Element => {
|
||||
isSelected={props.section == 'library'}
|
||||
icon={<LibraryIcon color={theme.colors.ctaBlue.toString()} />}
|
||||
/>
|
||||
<NavButton
|
||||
{...props}
|
||||
text="Subscriptions"
|
||||
section="subscriptions"
|
||||
isSelected={props.section == 'subscriptions'}
|
||||
icon={<FollowingIcon color="#F59932" />}
|
||||
/>
|
||||
<NavButton
|
||||
{...props}
|
||||
text="Highlights"
|
||||
@ -303,7 +303,7 @@ const Shortcuts = (props: LibraryFilterMenuProps): JSX.Element => {
|
||||
m: '0px',
|
||||
gap: '8px',
|
||||
width: '100%',
|
||||
px: '15px',
|
||||
px: '0px',
|
||||
pb: '25px',
|
||||
}}
|
||||
alignment="start"
|
||||
@ -815,6 +815,7 @@ function NavButton(props: NavButtonProps): JSX.Element {
|
||||
width: '100%',
|
||||
maxWidth: '100%',
|
||||
height: '34px',
|
||||
px: '15px',
|
||||
|
||||
backgroundColor: props.isSelected
|
||||
? '$thLibrarySelectionColor'
|
||||
|
||||
@ -31,6 +31,7 @@
|
||||
"@radix-ui/react-switch": "^1.0.1",
|
||||
"@sentry/nextjs": "^7.42.0",
|
||||
"@stitches/react": "^1.2.5",
|
||||
"allotment": "^1.20.2",
|
||||
"antd": "4.24.3",
|
||||
"axios": "^1.2.0",
|
||||
"cookie": "^0.5.0",
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import * as HoverCard from '@radix-ui/react-hover-card'
|
||||
import { styled } from '@stitches/react'
|
||||
import { useRouter } from 'next/router'
|
||||
import { useCallback, useMemo, useState } from 'react'
|
||||
import { useMemo, useState } from 'react'
|
||||
import { Button } from '../../components/elements/Button'
|
||||
import { AddToLibraryActionIcon } from '../../components/elements/icons/home/AddToLibraryActionIcon'
|
||||
import { ArchiveActionIcon } from '../../components/elements/icons/home/ArchiveActionIcon'
|
||||
|
||||
@ -1,13 +1,14 @@
|
||||
import { NavigationLayout } from '../../components/templates/NavigationLayout'
|
||||
import { PrimaryLayout } from '../../components/templates/PrimaryLayout'
|
||||
import { HomeFeedContainer } from '../../components/templates/homeFeed/HomeFeedContainer'
|
||||
import { VStack } from '../../components/elements/LayoutPrimitives'
|
||||
import { Box, VStack } from '../../components/elements/LayoutPrimitives'
|
||||
import { LibraryContainer } from '../../components/templates/library/LibraryContainer'
|
||||
import { LibraryItemsContainer } from '../../components/templates/library/LibraryItemsContainer'
|
||||
import { LibrarySideBar } from '../../components/templates/library/LibrarySideBar'
|
||||
import { Allotment, LayoutPriority } from 'allotment'
|
||||
import 'allotment/dist/style.css'
|
||||
|
||||
export default function Home(): JSX.Element {
|
||||
return <LoadedContent />
|
||||
}
|
||||
|
||||
function LoadedContent(): JSX.Element {
|
||||
export default function Library(): JSX.Element {
|
||||
return (
|
||||
<NavigationLayout
|
||||
section="library"
|
||||
@ -16,18 +17,16 @@ function LoadedContent(): JSX.Element {
|
||||
path: '/library',
|
||||
}}
|
||||
>
|
||||
<VStack
|
||||
alignment="start"
|
||||
distribution="center"
|
||||
css={{
|
||||
px: '70px',
|
||||
backgroundColor: '$thLibraryBackground',
|
||||
'@lgDown': { px: '20px' },
|
||||
'@mdDown': { px: '10px' },
|
||||
}}
|
||||
>
|
||||
<HomeFeedContainer />
|
||||
</VStack>
|
||||
{/* <Allotment>
|
||||
<Allotment.Pane priority={LayoutPriority.High}> */}
|
||||
<Box css={{ width: '100%', height: '100%', overflowY: 'auto' }}>
|
||||
<LibraryContainer />
|
||||
</Box>
|
||||
{/* </Allotment.Pane>
|
||||
<Allotment.Pane maxSize={480}>
|
||||
<LibrarySideBar text="SIDEBAR" />
|
||||
</Allotment.Pane>
|
||||
</Allotment> */}
|
||||
</NavigationLayout>
|
||||
)
|
||||
}
|
||||
|
||||
46
yarn.lock
46
yarn.lock
@ -3793,6 +3793,11 @@
|
||||
dependencies:
|
||||
lodash "^4.17.21"
|
||||
|
||||
"@juggle/resize-observer@^3.3.1":
|
||||
version "3.4.0"
|
||||
resolved "https://registry.yarnpkg.com/@juggle/resize-observer/-/resize-observer-3.4.0.tgz#08d6c5e20cf7e4cc02fd181c4b0c225cd31dbb60"
|
||||
integrity sha512-dfLbk+PwWvFzSxwk3n5ySL0hfBog779o8h68wK/7/APo/7cgyWp5jcXockbxdk5kFRkbeXWm4Fbi9FrdN381sA==
|
||||
|
||||
"@langchain/anthropic@^0.1.16":
|
||||
version "0.1.16"
|
||||
resolved "https://registry.yarnpkg.com/@langchain/anthropic/-/anthropic-0.1.16.tgz#c2a9d3dd4e02df7118dd97cf2503c9bd1a4de5ad"
|
||||
@ -9649,6 +9654,18 @@ ajv@^8.11.0:
|
||||
require-from-string "^2.0.2"
|
||||
uri-js "^4.2.2"
|
||||
|
||||
allotment@^1.20.2:
|
||||
version "1.20.2"
|
||||
resolved "https://registry.yarnpkg.com/allotment/-/allotment-1.20.2.tgz#5ea3a630b3265479debb69156658244711f83843"
|
||||
integrity sha512-TaCuHfYNcsJS9EPk04M7TlG5Rl3vbAdHeAyrTE9D5vbpzV+wxnRoUrulDbfnzaQcPIZKpHJNixDOoZNuzliKEA==
|
||||
dependencies:
|
||||
classnames "^2.3.0"
|
||||
eventemitter3 "^5.0.0"
|
||||
lodash.clamp "^4.0.0"
|
||||
lodash.debounce "^4.0.0"
|
||||
lodash.isequal "^4.5.0"
|
||||
use-resize-observer "^9.0.0"
|
||||
|
||||
ansi-align@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/ansi-align/-/ansi-align-3.0.0.tgz#b536b371cf687caaef236c18d3e21fe3797467cb"
|
||||
@ -12147,6 +12164,11 @@ classnames@^2.2.6:
|
||||
resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.3.1.tgz#dfcfa3891e306ec1dad105d0e88f4417b8535e8e"
|
||||
integrity sha512-OlQdbZ7gLfGarSqxesMesDa5uz7KFbID8Kpq/SxIoNGDqY8lSYs0D+hhtBXhcdB3rcbXArFr7vlHheLk1voeNA==
|
||||
|
||||
classnames@^2.3.0:
|
||||
version "2.5.1"
|
||||
resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.5.1.tgz#ba774c614be0f016da105c858e7159eae8e7687b"
|
||||
integrity sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==
|
||||
|
||||
cld@^2.9.1:
|
||||
version "2.9.1"
|
||||
resolved "https://registry.yarnpkg.com/cld/-/cld-2.9.1.tgz#0c6685672d9f4612dfeb75eabfdd17bf282a87a6"
|
||||
@ -15330,6 +15352,11 @@ eventemitter3@^4.0.0, eventemitter3@^4.0.4:
|
||||
resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f"
|
||||
integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==
|
||||
|
||||
eventemitter3@^5.0.0:
|
||||
version "5.0.1"
|
||||
resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-5.0.1.tgz#53f5ffd0a492ac800721bb42c66b841de96423c4"
|
||||
integrity sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==
|
||||
|
||||
eventid@^2.0.0:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/eventid/-/eventid-2.0.1.tgz#574e860149457a79a2efe788c459f0c3062d02ec"
|
||||
@ -21076,12 +21103,17 @@ lodash.capitalize@^4.2.1:
|
||||
resolved "https://registry.yarnpkg.com/lodash.capitalize/-/lodash.capitalize-4.2.1.tgz#f826c9b4e2a8511d84e3aca29db05e1a4f3b72a9"
|
||||
integrity sha512-kZzYOKspf8XVX5AvmQF94gQW0lejFVgb80G85bU4ZWzoJ6C03PQg3coYAUpSTpQWelrZELd3XWgHzw4Ck5kaIw==
|
||||
|
||||
lodash.clamp@^4.0.0:
|
||||
version "4.0.3"
|
||||
resolved "https://registry.yarnpkg.com/lodash.clamp/-/lodash.clamp-4.0.3.tgz#5c24bedeeeef0753560dc2b4cb4671f90a6ddfaa"
|
||||
integrity sha512-HvzRFWjtcguTW7yd8NJBshuNaCa8aqNFtnswdT7f/cMd/1YKy5Zzoq4W/Oxvnx9l7aeY258uSdDfM793+eLsVg==
|
||||
|
||||
lodash.clonedeep@^4.5.0:
|
||||
version "4.5.0"
|
||||
resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef"
|
||||
integrity sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=
|
||||
|
||||
lodash.debounce@^4.0.8:
|
||||
lodash.debounce@^4.0.0, lodash.debounce@^4.0.8:
|
||||
version "4.0.8"
|
||||
resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af"
|
||||
integrity sha1-gteb/zCmfEAF/9XiUVMArZyk168=
|
||||
@ -21126,6 +21158,11 @@ lodash.isboolean@^3.0.3:
|
||||
resolved "https://registry.yarnpkg.com/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz#6c2e171db2a257cd96802fd43b01b20d5f5870f6"
|
||||
integrity sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY=
|
||||
|
||||
lodash.isequal@^4.5.0:
|
||||
version "4.5.0"
|
||||
resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0"
|
||||
integrity sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==
|
||||
|
||||
lodash.isfunction@^3.0.9:
|
||||
version "3.0.9"
|
||||
resolved "https://registry.yarnpkg.com/lodash.isfunction/-/lodash.isfunction-3.0.9.tgz#06de25df4db327ac931981d1bdb067e5af68d051"
|
||||
@ -31088,6 +31125,13 @@ use-latest@^1.0.0:
|
||||
dependencies:
|
||||
use-isomorphic-layout-effect "^1.0.0"
|
||||
|
||||
use-resize-observer@^9.0.0:
|
||||
version "9.1.0"
|
||||
resolved "https://registry.yarnpkg.com/use-resize-observer/-/use-resize-observer-9.1.0.tgz#14735235cf3268569c1ea468f8a90c5789fc5c6c"
|
||||
integrity sha512-R25VqO9Wb3asSD4eqtcxk8sJalvIOYBqS8MNZlpDSQ4l4xMQxC/J7Id9HoTqPq8FwULIn0PVW+OAqF2dyYbjow==
|
||||
dependencies:
|
||||
"@juggle/resize-observer" "^3.3.1"
|
||||
|
||||
use-sidecar@^1.1.2:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/use-sidecar/-/use-sidecar-1.1.2.tgz#2f43126ba2d7d7e117aa5855e5d8f0276dfe73c2"
|
||||
|
||||
Reference in New Issue
Block a user