diff --git a/common/user.ts b/common/user.ts index e3c9d181..0e333278 100644 --- a/common/user.ts +++ b/common/user.ts @@ -34,6 +34,7 @@ export type User = { followerCountCached: number followedCategories?: string[] + homeSections?: { visible: string[]; hidden: string[] } referredByUserId?: string referredByContractId?: string diff --git a/web/components/carousel.tsx b/web/components/carousel.tsx index 7ca19c66..9719ba06 100644 --- a/web/components/carousel.tsx +++ b/web/components/carousel.tsx @@ -3,9 +3,14 @@ import clsx from 'clsx' import { throttle } from 'lodash' import { ReactNode, useRef, useState, useEffect } from 'react' import { Row } from './layout/row' +import { VisibilityObserver } from 'web/components/visibility-observer' -export function Carousel(props: { children: ReactNode; className?: string }) { - const { children, className } = props +export function Carousel(props: { + children: ReactNode + loadMore?: () => void + className?: string +}) { + const { children, loadMore, className } = props const ref = useRef(null) @@ -38,6 +43,13 @@ export function Carousel(props: { children: ReactNode; className?: string }) { onScroll={onScroll} > {children} + + {loadMore && ( + visible && loadMore()} + /> + )} {!atFront && (
ReactNode + renderContracts?: ( + contracts: Contract[] | undefined, + loadMore: () => void + ) => ReactNode }) { const { user, @@ -100,7 +102,6 @@ export function ContractSearch(props: { persistPrefix, useQueryUrlParam, isWholePage, - maxItems, noControls, renderContracts, } = props @@ -184,8 +185,7 @@ export function ContractSearch(props: { const contracts = state.pages .flat() .filter((c) => !additionalFilter?.excludeContractIds?.includes(c.id)) - const renderedContracts = - state.pages.length === 0 ? undefined : contracts.slice(0, maxItems) + const renderedContracts = state.pages.length === 0 ? undefined : contracts if (IS_PRIVATE_MANIFOLD || process.env.NEXT_PUBLIC_FIREBASE_EMULATE) { return @@ -206,7 +206,7 @@ export function ContractSearch(props: { noControls={noControls} /> {renderContracts ? ( - renderContracts(renderedContracts) + renderContracts(renderedContracts, performQuery) ) : ( { - const creds = await authenticateOnServer(ctx) - const auth = creds ? await getUserAndPrivateUser(creds.user.uid) : null - return { props: { auth } } -} - -const Home = (props: { auth: { user: User } | null }) => { - const user = props.auth ? props.auth.user : null - - useTracking('view home') - - useSaveReferral() - - const memberGroups = (useMemberGroups(user?.id) ?? []).filter( - (group) => group.contractIds.length > 0 - ) - - return ( - - - - - - {memberGroups.map((group) => ( - - ))} - - - - ) -} - -function SearchSection(props: { - label: string - user: User | null - sort: Sort -}) { - const { label, user, sort } = props - const href = `/home?s=${sort}` - - return ( - - - {label} - - - contracts ? ( - - ) : ( - - ) - } - /> - - ) -} - -function GroupSection(props: { group: Group; user: User | null }) { - const { group, user } = props - - return ( - - - - contracts ? ( - - ) : ( - - ) - } - /> - - ) -} - -function DoubleCarousel(props: { - contracts: Contract[] - seeMoreUrl?: string - showTime?: ShowTime -}) { - const { contracts, seeMoreUrl, showTime } = props - return ( - -
- {contracts.length >= 6 - ? range(0, Math.floor(contracts.length / 2)).map((col) => { - const i = col * 2 - return ( - - - - - ) - }) - : contracts.map((c) => ( - - ))} - - - ) -} - -export default Home diff --git a/web/pages/experimental/home/_arrange-home.tsx b/web/pages/experimental/home/_arrange-home.tsx new file mode 100644 index 00000000..cfae0142 --- /dev/null +++ b/web/pages/experimental/home/_arrange-home.tsx @@ -0,0 +1,127 @@ +import clsx from 'clsx' +import { DragDropContext, Droppable, Draggable } from 'react-beautiful-dnd' +import { MenuIcon } from '@heroicons/react/solid' + +import { Col } from 'web/components/layout/col' +import { Row } from 'web/components/layout/row' +import { Subtitle } from 'web/components/subtitle' +import { useMemberGroups } from 'web/hooks/use-group' +import { filterDefined } from 'common/util/array' +import { keyBy } from 'lodash' +import { User } from 'common/user' + +export function ArrangeHome(props: { + user: User | null + homeSections: { visible: string[]; hidden: string[] } + setHomeSections: (homeSections: { + visible: string[] + hidden: string[] + }) => void +}) { + const { + user, + homeSections: { visible, hidden }, + setHomeSections, + } = props + + const memberGroups = useMemberGroups(user?.id) ?? [] + + const items = [ + { label: 'Trending', id: 'score' }, + { label: 'Newest', id: 'newest' }, + { label: 'Close date', id: 'close-date' }, + ...memberGroups.map((g) => ({ + label: g.name, + id: g.id, + })), + ] + const itemsById = keyBy(items, 'id') + + const [visibleItems, hiddenItems] = [ + filterDefined(visible.map((id) => itemsById[id])), + filterDefined(hidden.map((id) => itemsById[id])), + ] + + // Add unmentioned items to the visible list. + visibleItems.push( + ...items.filter( + (item) => !visibleItems.includes(item) && !hiddenItems.includes(item) + ) + ) + + return ( + { + console.log('drag end', e) + const { destination, source, draggableId } = e + if (!destination) return + + const item = itemsById[draggableId] + + const newHomeSections = { + visible: visibleItems.map((item) => item.id), + hidden: hiddenItems.map((item) => item.id), + } + + const sourceSection = source.droppableId as 'visible' | 'hidden' + newHomeSections[sourceSection].splice(source.index, 1) + + const destSection = destination.droppableId as 'visible' | 'hidden' + newHomeSections[destSection].splice(destination.index, 0, item.id) + + setHomeSections(newHomeSections) + }} + > + + + + + + ) +} + +function DraggableList(props: { + title: string + items: { id: string; label: string }[] +}) { + const { title, items } = props + return ( + + {(provided, snapshot) => ( + + + {items.map((item, index) => ( + + {(provided, snapshot) => ( +
+
+ )} +
+ ))} + {provided.placeholder} + + )} +
+ ) +} diff --git a/web/pages/experimental/home/_double-carousel.tsx b/web/pages/experimental/home/_double-carousel.tsx new file mode 100644 index 00000000..da01eb5a --- /dev/null +++ b/web/pages/experimental/home/_double-carousel.tsx @@ -0,0 +1,52 @@ +import { Contract } from 'common/contract' +import { range } from 'lodash' +import { Carousel } from 'web/components/carousel' +import { ContractCard } from 'web/components/contract/contract-card' +import { ShowTime } from 'web/components/contract/contract-details' +import { Col } from 'web/components/layout/col' + +export function DoubleCarousel(props: { + contracts: Contract[] + seeMoreUrl?: string + showTime?: ShowTime + loadMore?: () => void +}) { + const { contracts, showTime, loadMore } = props + return ( + +
+ {contracts.length >= 6 + ? range(0, Math.floor(contracts.length / 2)).map((col) => { + const i = col * 2 + return ( + + + + + ) + }) + : contracts.map((c) => ( + + ))} + + ) +} diff --git a/web/pages/experimental/home/index.tsx b/web/pages/experimental/home/index.tsx new file mode 100644 index 00000000..1683b8d8 --- /dev/null +++ b/web/pages/experimental/home/index.tsx @@ -0,0 +1,204 @@ +import React, { useState } from 'react' +import Router from 'next/router' +import { PencilIcon, PlusSmIcon } from '@heroicons/react/solid' + +import { Page } from 'web/components/page' +import { Col } from 'web/components/layout/col' +import { ContractSearch, SORTS } from 'web/components/contract-search' +import { User } from 'common/user' +import { getUserAndPrivateUser, updateUser } from 'web/lib/firebase/users' +import { useTracking } from 'web/hooks/use-tracking' +import { track } from 'web/lib/service/analytics' +import { authenticateOnServer } from 'web/lib/firebase/server-auth' +import { useSaveReferral } from 'web/hooks/use-save-referral' +import { GetServerSideProps } from 'next' +import { Sort } from 'web/components/contract-search' +import { Group } from 'common/group' +import { LoadingIndicator } from 'web/components/loading-indicator' +import { GroupLinkItem } from '../../groups' +import { SiteLink } from 'web/components/site-link' +import { useUser } from 'web/hooks/use-user' +import { useMemberGroups } from 'web/hooks/use-group' +import { DoubleCarousel } from './_double-carousel' +import clsx from 'clsx' +import { Button } from 'web/components/button' +import { ArrangeHome } from './_arrange-home' +import { Title } from 'web/components/title' +import { Row } from 'web/components/layout/row' + +export const getServerSideProps: GetServerSideProps = async (ctx) => { + const creds = await authenticateOnServer(ctx) + const auth = creds ? await getUserAndPrivateUser(creds.user.uid) : null + return { props: { auth } } +} + +const Home = (props: { auth: { user: User } | null }) => { + const user = useUser() ?? props.auth?.user ?? null + + useTracking('view home') + + useSaveReferral() + + const memberGroups = useMemberGroups(user?.id) ?? [] + + const [homeSections, setHomeSections] = useState( + user?.homeSections ?? { visible: [], hidden: [] } + ) + + const updateHomeSections = (newHomeSections: { + visible: string[] + hidden: string[] + }) => { + if (!user) return + updateUser(user.id, { homeSections: newHomeSections }) + setHomeSections(newHomeSections) + } + + const [isEditing, setIsEditing] = useState(false) + + return ( + + + + + + <EditDoneButton isEditing={isEditing} setIsEditing={setIsEditing} /> + </Row> + + {isEditing ? ( + <> + <ArrangeHome + user={user} + homeSections={homeSections} + setHomeSections={updateHomeSections} + /> + </> + ) : ( + homeSections.visible.map((id) => { + const sort = SORTS.find((sort) => sort.value === id) + if (sort) + return ( + <SearchSection + label={sort.label} + sort={sort.value} + user={user} + /> + ) + + const group = memberGroups.find((g) => g.id === id) + if (group) return <GroupSection group={group} user={user} /> + + return null + }) + )} + </Col> + <button + type="button" + className="fixed bottom-[70px] right-3 z-20 inline-flex items-center rounded-full border border-transparent bg-indigo-600 p-3 text-white shadow-sm hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 lg:hidden" + onClick={() => { + Router.push('/create') + track('mobile create button') + }} + > + <PlusSmIcon className="h-8 w-8" aria-hidden="true" /> + </button> + </Page> + ) +} + +function SearchSection(props: { + label: string + user: User | null + sort: Sort +}) { + const { label, user, sort } = props + const href = `/home?s=${sort}` + + return ( + <Col> + <SiteLink className="mb-2 text-xl" href={href}> + {label} + </SiteLink> + <ContractSearch + user={user} + defaultSort={sort} + noControls + // persistPrefix={`experimental-home-${sort}`} + renderContracts={(contracts, loadMore) => + contracts ? ( + <DoubleCarousel + contracts={contracts} + seeMoreUrl={href} + showTime={ + sort === 'close-date' || sort === 'resolve-date' + ? sort + : undefined + } + loadMore={loadMore} + /> + ) : ( + <LoadingIndicator /> + ) + } + /> + </Col> + ) +} + +function GroupSection(props: { group: Group; user: User | null }) { + const { group, user } = props + + return ( + <Col> + <GroupLinkItem className="mb-2 text-xl" group={group} /> + <ContractSearch + user={user} + defaultSort={'score'} + additionalFilter={{ groupSlug: group.slug }} + noControls + // persistPrefix={`experimental-home-${group.slug}`} + renderContracts={(contracts, loadMore) => + contracts ? ( + contracts.length == 0 ? ( + <div className="m-2 text-gray-500">No open markets</div> + ) : ( + <DoubleCarousel + contracts={contracts} + seeMoreUrl={`/group/${group.slug}`} + loadMore={loadMore} + /> + ) + ) : ( + <LoadingIndicator /> + ) + } + /> + </Col> + ) +} + +function EditDoneButton(props: { + isEditing: boolean + setIsEditing: (isEditing: boolean) => void + className?: string +}) { + const { isEditing, setIsEditing, className } = props + + return ( + <Button + size="lg" + color={isEditing ? 'blue' : 'gray-white'} + className={clsx(className, 'flex')} + onClick={() => { + setIsEditing(!isEditing) + }} + > + {!isEditing && ( + <PencilIcon className={clsx('mr-2 h-[24px] w-5')} aria-hidden="true" /> + )} + {isEditing ? 'Done' : 'Edit'} + </Button> + ) +} + +export default Home diff --git a/yarn.lock b/yarn.lock index 0381fd46..be83129b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1310,6 +1310,13 @@ dependencies: regenerator-runtime "^0.13.4" +"@babel/runtime@^7.15.4", "@babel/runtime@^7.9.2": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.18.9.tgz#b4fcfce55db3d2e5e080d2490f608a3b9f407f4a" + integrity sha512-lkqXDcvlFT5rvEjiu6+QYO+1GXrEHRo2LOtS7E4GtX5ESIZOgepqsZBVIj6Pv+a6zqsya9VCgiK1KAK4BvJDAw== + dependencies: + regenerator-runtime "^0.13.4" + "@babel/template@^7.12.7", "@babel/template@^7.16.7": version "7.16.7" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.16.7.tgz#8d126c8701fde4d66b264b3eba3d96f07666d155" @@ -3316,6 +3323,14 @@ resolved "https://registry.yarnpkg.com/@types/hogan.js/-/hogan.js-3.0.1.tgz#64c54407b30da359763e14877f5702b8ae85d61c" integrity sha512-D03i/2OY7kGyMq9wdQ7oD8roE49z/ZCZThe/nbahtvuqCNZY9T2MfedOWyeBdbEpY2W8Gnh/dyJLdFtUCOkYbg== +"@types/hoist-non-react-statics@^3.3.0": + version "3.3.1" + resolved "https://registry.yarnpkg.com/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz#1124aafe5118cb591977aeb1ceaaed1070eb039f" + integrity sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA== + dependencies: + "@types/react" "*" + hoist-non-react-statics "^3.3.0" + "@types/html-minifier-terser@^6.0.0": version "6.1.0" resolved "https://registry.yarnpkg.com/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz#4fc33a00c1d0c16987b1a20cf92d20614c55ac35" @@ -3428,6 +3443,13 @@ resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.4.tgz#cd667bcfdd025213aafb7ca5915a932590acdcdc" integrity sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw== +"@types/react-beautiful-dnd@13.1.2": + version "13.1.2" + resolved "https://registry.yarnpkg.com/@types/react-beautiful-dnd/-/react-beautiful-dnd-13.1.2.tgz#510405abb09f493afdfd898bf83995dc6385c130" + integrity sha512-+OvPkB8CdE/bGdXKyIhc/Lm2U7UAYCCJgsqmopFmh9gbAudmslkI8eOrPDjg4JhwSE6wytz4a3/wRjKtovHVJg== + dependencies: + "@types/react" "*" + "@types/react-dom@17.0.2": version "17.0.2" resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-17.0.2.tgz#35654cf6c49ae162d5bc90843d5437dc38008d43" @@ -3435,6 +3457,16 @@ dependencies: "@types/react" "*" +"@types/react-redux@^7.1.20": + version "7.1.24" + resolved "https://registry.yarnpkg.com/@types/react-redux/-/react-redux-7.1.24.tgz#6caaff1603aba17b27d20f8ad073e4c077e975c0" + integrity sha512-7FkurKcS1k0FHZEtdbbgN8Oc6b+stGSfZYjQGicofJ0j4U0qIn/jaSvnP2pLwZKiai3/17xqqxkkrxTgN8UNbQ== + dependencies: + "@types/hoist-non-react-statics" "^3.3.0" + "@types/react" "*" + hoist-non-react-statics "^3.3.0" + redux "^4.0.0" + "@types/react-router-config@*": version "5.0.6" resolved "https://registry.yarnpkg.com/@types/react-router-config/-/react-router-config-5.0.6.tgz#87c5c57e72d241db900d9734512c50ccec062451" @@ -4992,6 +5024,13 @@ crypto-random-string@^2.0.0: resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-2.0.0.tgz#ef2a7a966ec11083388369baa02ebead229b30d5" integrity sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA== +css-box-model@^1.2.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/css-box-model/-/css-box-model-1.2.1.tgz#59951d3b81fd6b2074a62d49444415b0d2b4d7c1" + integrity sha512-a7Vr4Q/kd/aw96bnJG332W9V9LkJO69JRcaCYDUqjp6/z0w6VcZjgAcTbgFxEPfBgdnAwlh3iwu+hLopa+flJw== + dependencies: + tiny-invariant "^1.0.6" + css-declaration-sorter@^6.2.2: version "6.2.2" resolved "https://registry.yarnpkg.com/css-declaration-sorter/-/css-declaration-sorter-6.2.2.tgz#bfd2f6f50002d6a3ae779a87d3a0c5d5b10e0f02" @@ -7071,7 +7110,7 @@ hogan.js@^3.0.2: mkdirp "0.3.0" nopt "1.0.10" -hoist-non-react-statics@^3.1.0: +hoist-non-react-statics@^3.1.0, hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.2: version "3.3.2" resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45" integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw== @@ -8377,6 +8416,11 @@ memfs@^3.1.2, memfs@^3.4.3: dependencies: fs-monkey "1.0.3" +memoize-one@^5.1.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-5.2.1.tgz#8337aa3c4335581839ec01c3d594090cebe8f00e" + integrity sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q== + merge-descriptors@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" @@ -9851,6 +9895,11 @@ quick-lru@^5.1.1: resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-5.1.1.tgz#366493e6b3e42a3a6885e2e99d18f80fb7a8c932" integrity sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA== +raf-schd@^4.0.2: + version "4.0.3" + resolved "https://registry.yarnpkg.com/raf-schd/-/raf-schd-4.0.3.tgz#5d6c34ef46f8b2a0e880a8fcdb743efc5bfdbc1a" + integrity sha512-tQkJl2GRWh83ui2DiPTJz9wEiMN20syf+5oKfB03yYP7ioZcJwsIK8FjrtLwH1m7C7e+Tt2yYBlrOpdT+dyeIQ== + raf@^3.1.0: version "3.4.1" resolved "https://registry.yarnpkg.com/raf/-/raf-3.4.1.tgz#0742e99a4a6552f445d73e3ee0328af0ff1ede39" @@ -9905,6 +9954,19 @@ react-base16-styling@^0.6.0: lodash.flow "^3.3.0" pure-color "^1.2.0" +react-beautiful-dnd@13.1.1: + version "13.1.1" + resolved "https://registry.yarnpkg.com/react-beautiful-dnd/-/react-beautiful-dnd-13.1.1.tgz#b0f3087a5840920abf8bb2325f1ffa46d8c4d0a2" + integrity sha512-0Lvs4tq2VcrEjEgDXHjT98r+63drkKEgqyxdA7qD3mvKwga6a5SscbdLPO2IExotU1jW8L0Ksdl0Cj2AF67nPQ== + dependencies: + "@babel/runtime" "^7.9.2" + css-box-model "^1.2.0" + memoize-one "^5.1.1" + raf-schd "^4.0.2" + react-redux "^7.2.0" + redux "^4.0.4" + use-memo-one "^1.1.1" + react-confetti@6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/react-confetti/-/react-confetti-6.0.1.tgz#d4f57b5a021dd908a6243b8f63b6009b00818d10" @@ -10012,6 +10074,11 @@ react-is@^16.13.1, react-is@^16.6.0, react-is@^16.7.0: resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== +react-is@^17.0.2: + version "17.0.2" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0" + integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w== + react-json-view@^1.21.3: version "1.21.3" resolved "https://registry.yarnpkg.com/react-json-view/-/react-json-view-1.21.3.tgz#f184209ee8f1bf374fb0c41b0813cff54549c475" @@ -10057,6 +10124,18 @@ react-query@3.39.0: broadcast-channel "^3.4.1" match-sorter "^6.0.2" +react-redux@^7.2.0: + version "7.2.8" + resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-7.2.8.tgz#a894068315e65de5b1b68899f9c6ee0923dd28de" + integrity sha512-6+uDjhs3PSIclqoCk0kd6iX74gzrGc3W5zcAjbrFgEdIjRSQObdIwfx80unTkVUYvbQ95Y8Av3OvFHq1w5EOUw== + dependencies: + "@babel/runtime" "^7.15.4" + "@types/react-redux" "^7.1.20" + hoist-non-react-statics "^3.3.2" + loose-envify "^1.4.0" + prop-types "^15.7.2" + react-is "^17.0.2" + react-router-config@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/react-router-config/-/react-router-config-5.1.1.tgz#0f4263d1a80c6b2dc7b9c1902c9526478194a988" @@ -10208,6 +10287,13 @@ recursive-readdir@^2.2.2: dependencies: minimatch "3.0.4" +redux@^4.0.0, redux@^4.0.4: + version "4.2.0" + resolved "https://registry.yarnpkg.com/redux/-/redux-4.2.0.tgz#46f10d6e29b6666df758780437651eeb2b969f13" + integrity sha512-oSBmcKKIuIR4ME29/AeNUnl5L+hvBq7OaJWzaptTQJAntaPvxIJqfnjbaEiCzzaIz+XmVILfqAM3Ob0aXLPfjA== + dependencies: + "@babel/runtime" "^7.9.2" + regenerate-unicode-properties@^10.0.1: version "10.0.1" resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-10.0.1.tgz#7f442732aa7934a3740c779bb9b3340dccc1fb56" @@ -11306,7 +11392,7 @@ thunky@^1.0.2: resolved "https://registry.yarnpkg.com/thunky/-/thunky-1.1.0.tgz#5abaf714a9405db0504732bbccd2cedd9ef9537d" integrity sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA== -tiny-invariant@^1.0.2: +tiny-invariant@^1.0.2, tiny-invariant@^1.0.6: version "1.2.0" resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.2.0.tgz#a1141f86b672a9148c72e978a19a73b9b94a15a9" integrity sha512-1Uhn/aqw5C6RI4KejVeTg6mIS7IqxnLJ8Mv2tV5rTc0qWobay7pDUz6Wi392Cnc8ak1H0F2cjoRzb2/AW4+Fvg== @@ -11740,6 +11826,11 @@ use-latest@^1.2.1: dependencies: use-isomorphic-layout-effect "^1.1.1" +use-memo-one@^1.1.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/use-memo-one/-/use-memo-one-1.1.2.tgz#0c8203a329f76e040047a35a1197defe342fab20" + integrity sha512-u2qFKtxLsia/r8qG0ZKkbytbztzRb317XCkT7yP8wxL0tZ/CzK2G+WWie5vWvpyeP7+YoPIwbJoIHJ4Ba4k0oQ== + use-sync-external-store@1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz#7dbefd6ef3fe4e767a0cf5d7287aacfb5846928a"