App Store Search (#5704)

Co-authored-by: Alex van Andel <me@alexvanandel.com>
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
Co-authored-by: Peer Richelsen <peer@cal.com>
This commit is contained in:
Leo Giovanetti
2022-11-30 20:51:44 +00:00
committed by GitHub
co-authored by Alex van Andel Peer Richelsen Peer Richelsen
parent ef3ad36c2c
commit f1b92c49fc
13 changed files with 312 additions and 58 deletions
+1 -1
View File
@@ -38,7 +38,7 @@
"@calcom/tsconfig": "*",
"@calcom/ui": "*",
"@daily-co/daily-js": "^0.26.0",
"@formkit/auto-animate": "^1.0.0-beta.1",
"@formkit/auto-animate": "^1.0.0-beta.5",
"@glidejs/glide": "^3.5.2",
"@heroicons/react": "^1.0.6",
"@hookform/error-message": "^2.0.0",
+39 -5
View File
@@ -1,21 +1,55 @@
import { useAutoAnimate } from "@formkit/auto-animate/react";
import { InferGetStaticPropsType, NextPageContext } from "next";
import { ChangeEventHandler, useState } from "react";
import { getAppRegistry, getAppRegistryWithCredentials } from "@calcom/app-store/_appRegistry";
import { classNames } from "@calcom/lib";
import { getSession } from "@calcom/lib/auth";
import { useLocale } from "@calcom/lib/hooks/useLocale";
import type { AppCategories } from "@calcom/prisma/client";
import { AllApps, AppsLayout, AppStoreCategories, TrendingAppsSlider } from "@calcom/ui";
import { AllApps, AppsLayout, AppStoreCategories, Icon, TextField, TrendingAppsSlider } from "@calcom/ui";
import { ssgInit } from "@server/lib/ssg";
function AppsSearch({
onChange,
className,
}: {
onChange: ChangeEventHandler<HTMLInputElement>;
className?: string;
}) {
return (
<TextField
className="!border-gray-100 bg-gray-100 !pl-0 focus:!ring-offset-0"
addOnLeading={<Icon.FiSearch className="h-4 w-4 text-gray-500" />}
addOnClassname="!border-gray-100"
containerClassName={classNames("focus:!ring-offset-0", className)}
type="search"
autoComplete="false"
onChange={onChange}
/>
);
}
export default function Apps({ appStore, categories }: InferGetStaticPropsType<typeof getServerSideProps>) {
const { t } = useLocale();
const [searchText, setSearchText] = useState<string | undefined>(undefined);
return (
<AppsLayout isPublic heading={t("app_store")} subtitle={t("app_store_description")}>
<AppStoreCategories categories={categories} />
<TrendingAppsSlider items={appStore} />
<AllApps apps={appStore} />
<AppsLayout
isPublic
heading={t("app_store")}
subtitle={t("app_store_description")}
actions={(className) => (
<AppsSearch className={className} onChange={(e) => setSearchText(e.target.value)} />
)}>
{!searchText && (
<>
<AppStoreCategories categories={categories} />
<TrendingAppsSlider items={appStore} />
</>
)}
<AllApps apps={appStore} searchText={searchText} />
</AppsLayout>
);
}
@@ -52,6 +52,7 @@
"still_waiting_for_approval": "An event is still waiting for approval",
"event_is_still_waiting": "Event request is still waiting: {{attendeeName}} - {{date}} - {{eventType}}",
"no_more_results": "No more results",
"no_results": "No results",
"load_more_results": "Load more results",
"integration_meeting_id": "{{integrationName}} meeting ID: {{meetingId}}",
"confirmed_event_type_subject": "Confirmed: {{eventType}} with {{name}} at {{date}}",
+4
View File
@@ -499,4 +499,8 @@ hr {
.h-screen {
height: -webkit-fill-available;
}
}
::-webkit-search-cancel-button {
-webkit-appearance: none;
}
@@ -63,7 +63,7 @@ export const CreateANewTeamForm = () => {
className="mt-2"
name="name"
label={t("team_name")}
value={value}
defaultValue={value}
onChange={(e) => {
newTeamFormMethods.setValue("name", e?.target.value);
if (newTeamFormMethods.formState.touchedFields["slug"] === undefined) {
@@ -91,7 +91,7 @@ export const CreateANewTeamForm = () => {
"http://",
""
)}/`}
value={value}
defaultValue={value}
onChange={(e) => {
newTeamFormMethods.setValue("slug", slugify(e?.target.value), {
shouldTouch: true,
+33 -12
View File
@@ -6,7 +6,7 @@ import classNames from "@calcom/lib/classNames";
import { getErrorFromUnknown } from "@calcom/lib/errors";
import { useLocale } from "@calcom/lib/hooks/useLocale";
import { Alert, showToast, Skeleton, Tooltip, UnstyledSelect } from "../../..";
import { Alert, showToast, Icon, Skeleton, Tooltip, UnstyledSelect } from "../../..";
import { HintsOrErrors } from "./HintOrErrors";
import { Label } from "./Label";
@@ -44,9 +44,8 @@ type InputFieldProps = {
addOnLeading?: ReactNode;
addOnSuffix?: ReactNode;
inputIsFullWidth?: boolean;
/**@Default paddingX 12px */
addOnPadding?: number;
addOnFilled?: boolean;
addOnClassname?: string;
error?: string;
labelSrOnly?: boolean;
containerClassName?: string;
@@ -61,13 +60,15 @@ type AddonProps = {
isFilled?: boolean;
className?: string;
error?: boolean;
paddingX?: number;
};
const Addon = ({ isFilled, children, className, error, paddingX = 12 }: AddonProps) => (
const Addon = ({ isFilled, children, className, error }: AddonProps) => (
<div
style={{ padding: `0 ${paddingX}px` }}
className={classNames("addon-wrapper h-9 border border-gray-300", isFilled && "bg-gray-100", className)}>
className={classNames(
"addon-wrapper h-9 border border-gray-300 px-3",
isFilled && "bg-gray-100",
className
)}>
<div className={classNames("flex h-full flex-col justify-center text-sm", error && "text-red-900")}>
<span className="whitespace-nowrap py-2.5">{children}</span>
</div>
@@ -88,9 +89,10 @@ export const InputField = forwardRef<HTMLInputElement, InputFieldProps>(function
addOnLeading,
addOnSuffix,
addOnFilled = true,
addOnPadding,
addOnClassname,
inputIsFullWidth,
hint,
type,
hintErrors,
labelSrOnly,
containerClassName,
@@ -99,6 +101,8 @@ export const InputField = forwardRef<HTMLInputElement, InputFieldProps>(function
...passThrough
} = props;
const [inputValue, setInputValue] = useState<string>("");
return (
<div className={classNames(containerClassName)}>
{!!name && (
@@ -114,28 +118,45 @@ export const InputField = forwardRef<HTMLInputElement, InputFieldProps>(function
{addOnLeading || addOnSuffix ? (
<div className="relative mb-1 flex items-center rounded-md focus-within:outline-none focus-within:ring-2 focus-within:ring-neutral-800 focus-within:ring-offset-1">
{addOnLeading && (
<Addon isFilled={addOnFilled} className="rounded-l-md border-r-0" paddingX={addOnPadding}>
<Addon isFilled={addOnFilled} className={classNames("rounded-l-md border-r-0", addOnClassname)}>
{addOnLeading}
</Addon>
)}
<Input
id={id}
placeholder={placeholder}
{...passThrough}
{...(type == "search" && {
onChange: (e) => {
setInputValue(e.target.value);
props.onChange && props.onChange(e);
},
value: inputValue,
})}
isFullWidth={inputIsFullWidth}
className={classNames(
className,
addOnLeading && "rounded-l-none",
addOnSuffix && "rounded-r-none",
type === "search" && "pr-8",
"!my-0 !ring-0"
)}
{...passThrough}
ref={ref}
/>
{addOnSuffix && (
<Addon isFilled={addOnFilled} className="rounded-r-md border-l-0" paddingX={addOnPadding}>
<Addon isFilled={addOnFilled} className={classNames("rounded-r-md border-l-0", addOnClassname)}>
{addOnSuffix}
</Addon>
)}
{type === "search" && inputValue?.toString().length > 0 && (
<Icon.FiX
className="absolute right-2 top-2.5 h-4 w-4 cursor-pointer text-gray-500"
onClick={(e) => {
setInputValue("");
props.onChange && props.onChange(e as unknown as React.ChangeEvent<HTMLInputElement>);
}}
/>
)}
</div>
) : (
<Input
@@ -344,7 +365,7 @@ export const InputFieldWithSelect = forwardRef<
ref={ref}
{...props}
inputIsFullWidth={false}
addOnPadding={0}
addOnClassname="!px-0"
addOnSuffix={<UnstyledSelect {...props.selectProps} />}
/>
);
+1 -1
View File
@@ -15,7 +15,7 @@
"dependencies": {
"@calcom/lib": "*",
"@calcom/trpc": "*",
"@formkit/auto-animate": "^1.0.0-beta.1",
"@formkit/auto-animate": "^1.0.0-beta.5",
"@radix-ui/react-dialog": "^1.0.0",
"@radix-ui/react-portal": "^1.0.0",
"@radix-ui/react-select": "^0.1.1",
+3
View File
@@ -183,6 +183,8 @@ type LayoutProps = {
withoutMain?: boolean;
// Gives you the option to skip HeadSEO and render your own.
withoutSeo?: boolean;
// Gives the ability to include actions to the right of the heading
actions?: JSX.Element;
};
const CustomBrandingContainer = () => {
@@ -840,6 +842,7 @@ export function ShellMain(props: LayoutProps) {
{props.CTA}
</div>
)}
{props.actions && props.actions}
</header>
)}
</div>
+34 -23
View File
@@ -36,14 +36,15 @@ export function useShouldShowArrows() {
return { ref, calculateScroll, leftVisible: showArrowScroll.left, rightVisible: showArrowScroll.right };
}
type AllAppsPropsType = { apps: (App & { credentials: Credential[] | undefined })[] };
type AllAppsPropsType = { apps: (App & { credentials: Credential[] | undefined })[]; searchText?: string };
interface CategoryTabProps {
selectedCategory: string | null;
categories: string[];
searchText?: string;
}
function CategoryTab({ selectedCategory, categories }: CategoryTabProps) {
function CategoryTab({ selectedCategory, categories, searchText }: CategoryTabProps) {
const { t } = useLocale();
const router = useRouter();
const { ref, calculateScroll, leftVisible, rightVisible } = useShouldShowArrows();
@@ -60,12 +61,14 @@ function CategoryTab({ selectedCategory, categories }: CategoryTabProps) {
};
return (
<div className="relative mb-4 flex flex-col justify-between lg:flex-row lg:items-center">
<h2 className="text-lg font-semibold text-gray-900 ">
{t("explore_apps", {
category:
(selectedCategory && selectedCategory[0].toUpperCase() + selectedCategory.slice(1)) ||
t("all_apps"),
})}
<h2 className="hidden text-lg font-semibold text-gray-900 sm:block">
{searchText
? t("search")
: t("explore_apps", {
category:
(selectedCategory && selectedCategory[0].toUpperCase() + selectedCategory.slice(1)) ||
t("all_apps"),
})}
</h2>
{leftVisible && (
<button onClick={handleLeft} className="absolute top-9 flex md:left-1/2 md:-top-1">
@@ -121,11 +124,11 @@ function CategoryTab({ selectedCategory, categories }: CategoryTabProps) {
);
}
export default function AllApps({ apps }: AllAppsPropsType) {
export default function AllApps({ apps, searchText }: AllAppsPropsType) {
const router = useRouter();
const { t } = useLocale();
const [selectedCategory, setSelectedCategory] = useState<string | null>(null);
const [appsContainerRef] = useAutoAnimate<HTMLDivElement>();
const [appsContainerRef, enableAnimation] = useAutoAnimate<HTMLDivElement>();
const categories = apps
.map((app) => app.category)
@@ -133,6 +136,10 @@ export default function AllApps({ apps }: AllAppsPropsType) {
return self.indexOf(cat) === pos;
});
if (searchText) {
enableAnimation(false);
}
useEffect(() => {
const queryCategory =
typeof router.query.category === "string" && categories.includes(router.query.category)
@@ -141,23 +148,27 @@ export default function AllApps({ apps }: AllAppsPropsType) {
setSelectedCategory(queryCategory);
}, [router.query.category]);
const filteredApps = apps
.filter((app) =>
selectedCategory !== null
? app.categories
? app.categories.includes(selectedCategory)
: app.category === selectedCategory
: true
)
.filter((app) => (searchText ? app.name.toLowerCase().includes(searchText.toLowerCase()) : true));
return (
<div className="mb-16">
<CategoryTab selectedCategory={selectedCategory} categories={categories} />
<CategoryTab selectedCategory={selectedCategory} searchText={searchText} categories={categories} />
<div
className="grid gap-3 lg:grid-cols-4 [@media(max-width:1270px)]:grid-cols-3 [@media(max-width:730px)]:grid-cols-2 [@media(max-width:500px)]:grid-cols-1"
ref={appsContainerRef}>
{apps
.filter((app) =>
selectedCategory !== null
? app.categories
? app.categories.includes(selectedCategory)
: app.category === selectedCategory
: true
)
.map((app) => (
<AppCard key={app.name} app={app} credentials={app.credentials} />
))}
{filteredApps.length
? filteredApps.map((app) => (
<AppCard key={app.name} app={app} searchText={searchText} credentials={app.credentials} />
))
: t("no_results")}
</div>
</div>
);
+21 -2
View File
@@ -1,5 +1,6 @@
import type { Credential } from "@prisma/client";
import { useRouter } from "next/router";
import { useEffect, useState } from "react";
import useAddAppMutation from "@calcom/app-store/_utils/useAddAppMutation";
import { InstallAppButton } from "@calcom/app-store/components";
@@ -12,9 +13,10 @@ import { showToast } from "../notifications";
interface AppCardProps {
app: App;
credentials?: Credential[];
searchText?: string;
}
export default function AppCard({ app, credentials }: AppCardProps) {
export default function AppCard({ app, credentials, searchText }: AppCardProps) {
const { t } = useLocale();
const router = useRouter();
const mutation = useAddAppMutation(null, {
@@ -31,6 +33,11 @@ export default function AppCard({ app, credentials }: AppCardProps) {
const allowedMultipleInstalls = app.categories && app.categories.indexOf("calendar") > -1;
const appAdded = (credentials && credentials.length) || 0;
const [searchTextIndex, setSearchTextIndex] = useState<number | undefined>(undefined);
useEffect(() => {
setSearchTextIndex(searchText ? app.name.toLowerCase().indexOf(searchText.toLowerCase()) : undefined);
}, [app.name, searchText]);
return (
<div className="relative flex h-64 flex-col rounded-md border border-gray-300 p-5">
@@ -38,7 +45,19 @@ export default function AppCard({ app, credentials }: AppCardProps) {
<img src={app.logo} alt={app.name + " Logo"} className="mb-4 h-12 w-12 rounded-sm" />
</div>
<div className="flex items-center">
<h3 className="font-medium">{app.name}</h3>
<h3 className="font-medium">
{searchTextIndex != undefined && searchText ? (
<>
{app.name.substring(0, searchTextIndex)}
<span className="bg-yellow-300">
{app.name.substring(searchTextIndex, searchTextIndex + searchText.length)}
</span>
{app.name.substring(searchTextIndex + searchText.length)}
</>
) : (
app.name
)}
</h3>
</div>
{/* TODO: add reviews <div className="flex text-sm text-gray-800">
<span>{props.rating} stars</span> <StarIcon className="ml-1 mt-0.5 h-4 w-4 text-yellow-600" />
+9 -7
View File
@@ -15,15 +15,17 @@ const tabs: HorizontalTabItemProps[] = [
},
];
export default function AppsLayout({
children,
...rest
}: { children: React.ReactNode } & ComponentProps<typeof Shell>) {
type AppsLayoutProps = {
children: React.ReactNode;
actions?: (className?: string) => JSX.Element;
} & Omit<ComponentProps<typeof Shell>, "actions">;
export default function AppsLayout({ children, actions, ...rest }: AppsLayoutProps) {
return (
<Shell {...rest}>
<div className="flex flex-col xl:flex-row ">
<Shell {...rest} actions={actions?.("hidden sm:block")}>
<div className="flex flex-col xl:flex-row">
<div className="block lg:hidden">
<HorizontalTabs tabs={tabs} />
<HorizontalTabs tabs={tabs} actions={actions?.("ml-6 mr-4 mt-3 block sm:hidden")} />
</div>
<main className="w-full">{children}</main>
</div>
@@ -5,9 +5,10 @@ export { HorizontalTabItem };
export interface NavTabProps {
tabs: HorizontalTabItemProps[];
linkProps?: HorizontalTabItemProps["linkProps"];
actions?: JSX.Element;
}
const HorizontalTabs = function ({ tabs, linkProps, ...props }: NavTabProps) {
const HorizontalTabs = function ({ tabs, linkProps, actions, ...props }: NavTabProps) {
return (
<div className="-mx-6 mb-2 w-[calc(100%+40px)]">
<nav
@@ -18,6 +19,7 @@ const HorizontalTabs = function ({ tabs, linkProps, ...props }: NavTabProps) {
<HorizontalTabItem {...tab} key={idx} {...linkProps} />
))}
</nav>
{actions && actions}
</div>
);
};
+161 -4
View File
@@ -3839,10 +3839,10 @@
intl-messageformat "9.13.0"
tslib "^2.1.0"
"@formkit/auto-animate@^1.0.0-beta.1":
version "1.0.0-beta.1"
resolved "https://registry.yarnpkg.com/@formkit/auto-animate/-/auto-animate-1.0.0-beta.1.tgz#aec5fd2ea5e499ceb7eb117c7fd1217a7f100748"
integrity sha512-I3OWOBaPZKSJL4bsooXI8kC3q7bcgibD2oML0P/Lir6MnbvUe/0/7EH8br024juvM/Ulm9C9xGx9CJUQYrOWSA==
"@formkit/auto-animate@^1.0.0-beta.5":
version "1.0.0-beta.5"
resolved "https://registry.yarnpkg.com/@formkit/auto-animate/-/auto-animate-1.0.0-beta.5.tgz#3fe4d520a82909cdcffa8854f26bc26ca4562045"
integrity sha512-WoSwyhAZPOe6RB/IgicOtCHtrWwEpfKIZ/H/nxpKfnZL9CB6hhhBGU5bCdMRw7YpAUF2CDlQa+WWh+gCqz5lDg==
"@gar/promisify@^1.0.1":
version "1.1.3"
@@ -4593,6 +4593,158 @@
resolved "https://registry.yarnpkg.com/@juggle/resize-observer/-/resize-observer-3.4.0.tgz#08d6c5e20cf7e4cc02fd181c4b0c225cd31dbb60"
integrity sha512-dfLbk+PwWvFzSxwk3n5ySL0hfBog779o8h68wK/7/APo/7cgyWp5jcXockbxdk5kFRkbeXWm4Fbi9FrdN381sA==
"@lexical/clipboard@0.5.0":
version "0.5.0"
resolved "https://registry.yarnpkg.com/@lexical/clipboard/-/clipboard-0.5.0.tgz#3d835289c0e1543a13a5fd032294aa2614e4373a"
integrity sha512-JFvdH4N/80GxC0jhaiO/fdUOeYcX8pMFrcrpBDeNIcBN/9eF8Rn/czvoPLLNB9Kcbz8d8XXqabKEGCz2hFL//w==
dependencies:
"@lexical/html" "0.5.0"
"@lexical/list" "0.5.0"
"@lexical/selection" "0.5.0"
"@lexical/utils" "0.5.0"
"@lexical/code@0.5.0":
version "0.5.0"
resolved "https://registry.yarnpkg.com/@lexical/code/-/code-0.5.0.tgz#05c92e3b077af3148a494b44f5663dea14f7631f"
integrity sha512-GmqRaQ8EBtlu13ObSZYiGDzIsrkwRyyqI2HRVBrPo2iszLBpby+7uIncAVQVkxt1JNYOKE2n4JfxK8TSYyMtYQ==
dependencies:
"@lexical/utils" "0.5.0"
prismjs "^1.27.0"
"@lexical/dragon@0.5.0":
version "0.5.0"
resolved "https://registry.yarnpkg.com/@lexical/dragon/-/dragon-0.5.0.tgz#54ec8812e3fb907af5913c5d0436b8d28fa4efe8"
integrity sha512-Gf0jN8hjlF8E71wAsvbRpR1u9oS6RUjUw3VWp/Qa+IrtjBFFVzdTUloUs3cjMX9E/MFRJgt3wPsaKx2IuLBWQw==
"@lexical/hashtag@0.5.0":
version "0.5.0"
resolved "https://registry.yarnpkg.com/@lexical/hashtag/-/hashtag-0.5.0.tgz#dfe39ea73d1c4658c724419ef1113e27fb75a7f3"
integrity sha512-3MT72y72BmK4q7Rtb9gP3n83UL4vWC078T9io4zyPxKEI1Mh3UAVuRwh6Ypn0FeH94XvmuZAGVdoOC/nTd1now==
dependencies:
"@lexical/utils" "0.5.0"
"@lexical/history@0.5.0":
version "0.5.0"
resolved "https://registry.yarnpkg.com/@lexical/history/-/history-0.5.0.tgz#5a13077e012f27f783beadca1c3fe545a2968f20"
integrity sha512-DCQgh1aQ1KS5JVYPU6GYr52BN0MQqmoXfFtf5uYCX9CbSAC0hDSK8ZPqwFW7jINqe6GwXxy7bo32j7E0A5023A==
dependencies:
"@lexical/utils" "0.5.0"
"@lexical/html@0.5.0":
version "0.5.0"
resolved "https://registry.yarnpkg.com/@lexical/html/-/html-0.5.0.tgz#5eb2ccb9ffb7c24fff097db369d81431d7a98833"
integrity sha512-uJAof6gXTLOH9JnmPJ+wxILFtu7I/eCebFyVMjV53sqaeLsQ3pDfBTUe4RO+NciC+XBQ1WVpZgCM8Yx5c5cMmQ==
dependencies:
"@lexical/selection" "0.5.0"
"@lexical/link@0.5.0":
version "0.5.0"
resolved "https://registry.yarnpkg.com/@lexical/link/-/link-0.5.0.tgz#fa5f3baa1122eb2a1be12ac7a30977eb4c557e1e"
integrity sha512-XB8e+UPI9jeqsi7+Wr0n9SToljiS+gZmJ5gXANtR6lSZPtpcSUPs1iJZU2A2dNKXdvsZwSPCFdPL6ogFaaRvvQ==
dependencies:
"@lexical/utils" "0.5.0"
"@lexical/list@0.5.0":
version "0.5.0"
resolved "https://registry.yarnpkg.com/@lexical/list/-/list-0.5.0.tgz#6ab4e1789d037af43f3d01012d2533c7c94daf15"
integrity sha512-TYXe4FtNL7Lk3XDEhPyUbT0Pb1TU58qZywGCdrtuRjPnF4oDvRXgg9EhYWfHzYwdsyhNgaHId+Fq41CjrwTMYg==
dependencies:
"@lexical/utils" "0.5.0"
"@lexical/mark@0.5.0":
version "0.5.0"
resolved "https://registry.yarnpkg.com/@lexical/mark/-/mark-0.5.0.tgz#59c2a2a9f0ecfa063d48ce6f4a50e6d8bc6fcae1"
integrity sha512-leeqegWD4hqUdfYNsxB5iwsWozX2oc6mnJzcJfR4UB3Ksr0zH2xHc/z3Zp+CTeGuK5Tzppq5yGS+4cQ5xNpVgQ==
dependencies:
"@lexical/utils" "0.5.0"
"@lexical/markdown@0.5.0":
version "0.5.0"
resolved "https://registry.yarnpkg.com/@lexical/markdown/-/markdown-0.5.0.tgz#3424a98e8600bc719f99bb4ab2484f0cf0e3c0f7"
integrity sha512-02RLx7PdVzvYxvx65FTbXkW6KcjQZ1waAaMDNKdtBV9r9Mv2Y2XunCUjErYHQ1JN9JkGGv0+JuliRT7qZTsF+Q==
dependencies:
"@lexical/code" "0.5.0"
"@lexical/link" "0.5.0"
"@lexical/list" "0.5.0"
"@lexical/rich-text" "0.5.0"
"@lexical/text" "0.5.0"
"@lexical/utils" "0.5.0"
"@lexical/offset@0.5.0":
version "0.5.0"
resolved "https://registry.yarnpkg.com/@lexical/offset/-/offset-0.5.0.tgz#445aae1c74198dd4ed7d59669735925621139e0a"
integrity sha512-ie4AFbvtt0CFBqaMcb0/gUuhoTt+YwbFXPFo1hW+oDVpmo3rJsEJKVsHhftBvHIP+/G5QlgPIhVmnlcSvEteTw==
"@lexical/overflow@0.5.0":
version "0.5.0"
resolved "https://registry.yarnpkg.com/@lexical/overflow/-/overflow-0.5.0.tgz#70daabdb96a3de9bf2f052ab2e38917aaf6e3b18"
integrity sha512-N+BQvgODU9lS7VK4FlxIRhGeASwsxfdkECtZ5iomHfqqNEI0WPLHbCTCkwS10rjfH1NrkXC314Y0SG2F7Ncv9Q==
"@lexical/plain-text@0.5.0":
version "0.5.0"
resolved "https://registry.yarnpkg.com/@lexical/plain-text/-/plain-text-0.5.0.tgz#385ac7c67b34116578e45fe34cca41e9f62cbcad"
integrity sha512-t1rnVnSXbPs9jLN/36/xZLNAlF9jwv8rSh6GHsjRIYiWX/MovNmgPmhNq/nkc+gRFZ2FKTFjdz3UeAUF4xQZMw==
"@lexical/react@^0.5.0":
version "0.5.0"
resolved "https://registry.yarnpkg.com/@lexical/react/-/react-0.5.0.tgz#f227dd71f95e49bf817d648b9ffd5a31850876bc"
integrity sha512-bba0KXslxjf6M8XXJhx1rsrq9UV/6eo73WCZel2K+tGz8NEn1HCRTebQoebmRikzEQatEa3SoB6R47drMlk7Yw==
dependencies:
"@lexical/clipboard" "0.5.0"
"@lexical/code" "0.5.0"
"@lexical/dragon" "0.5.0"
"@lexical/hashtag" "0.5.0"
"@lexical/history" "0.5.0"
"@lexical/link" "0.5.0"
"@lexical/list" "0.5.0"
"@lexical/mark" "0.5.0"
"@lexical/markdown" "0.5.0"
"@lexical/overflow" "0.5.0"
"@lexical/plain-text" "0.5.0"
"@lexical/rich-text" "0.5.0"
"@lexical/selection" "0.5.0"
"@lexical/table" "0.5.0"
"@lexical/text" "0.5.0"
"@lexical/utils" "0.5.0"
"@lexical/yjs" "0.5.0"
"@lexical/rich-text@0.5.0":
version "0.5.0"
resolved "https://registry.yarnpkg.com/@lexical/rich-text/-/rich-text-0.5.0.tgz#9b7ddacdd74a49761f15486ed2846c5117a55d14"
integrity sha512-JhgMn70K410j3T/2WefPpEswZ+hWF3aJMNu7zkrCf2wB+KdrrGYoeNSZUzg2r4e6BuJgS117KlD99+MDnokCuw==
"@lexical/selection@0.5.0":
version "0.5.0"
resolved "https://registry.yarnpkg.com/@lexical/selection/-/selection-0.5.0.tgz#fe94f06fb17d9f5848921a0bbce10774398d3486"
integrity sha512-6I5qlqkYDIbDZPGwSOuvpWQUrqMY6URaKwrWsijQZMnNNKscGpC7IKb7sSDKn6YkLm7tuqig3hf2p+6hshkyWg==
"@lexical/table@0.5.0":
version "0.5.0"
resolved "https://registry.yarnpkg.com/@lexical/table/-/table-0.5.0.tgz#cf33fac7c2e0b520ab4747f9322cce434d117cb6"
integrity sha512-VNHWSsTFDSHNzLdQOR9qgKx4tvTuiDz6w0GfwBnMP4Ro2iKKtNowmZO4wDEZtVlUHvLMuOGuYqipOtKEDKbD4w==
dependencies:
"@lexical/utils" "0.5.0"
"@lexical/text@0.5.0":
version "0.5.0"
resolved "https://registry.yarnpkg.com/@lexical/text/-/text-0.5.0.tgz#803e34d9b1e2430e8062d2db50c7452d4e03c86e"
integrity sha512-RqhOBU2Ecg0WVW8p1d3OB2a8sQyvh3suADdr7We50+Dn/k1M+jhKVWiQnf07ve4/yqYTj6/9/8AAg7kuNS2P/A==
"@lexical/utils@0.5.0":
version "0.5.0"
resolved "https://registry.yarnpkg.com/@lexical/utils/-/utils-0.5.0.tgz#4f03e8090e65cde5e81801ab08a2450e2e03733a"
integrity sha512-FhQ+thPFTOyBxyRGcd3yJuYh/rvD8ro43DaelWD1KpSlwQ/YuWpdxsSuMqJ32ERpl+bmPPFP2kjkBofxSw1Quw==
dependencies:
"@lexical/list" "0.5.0"
"@lexical/table" "0.5.0"
"@lexical/yjs@0.5.0":
version "0.5.0"
resolved "https://registry.yarnpkg.com/@lexical/yjs/-/yjs-0.5.0.tgz#a6a6e12f5eceaa5a37ae7999b97ba8ce217987b6"
integrity sha512-2io4GqnRoSh6Nu9bzsDOlwPFJYjXZ9SdgU4ZioH2VvyW4wVstd+ZF2QVcUJlhuwgQr6DzuvM/pqN914IufLzpw==
dependencies:
"@lexical/offset" "0.5.0"
"@lit-labs/react@^1.0.2":
version "1.0.7"
resolved "https://registry.yarnpkg.com/@lit-labs/react/-/react-1.0.7.tgz#fbf7c129af701d74484c5dbc6f6ea97990b85e54"
@@ -17945,6 +18097,11 @@ levn@~0.3.0:
prelude-ls "~1.1.2"
type-check "~0.3.2"
lexical@^0.5.0:
version "0.5.0"
resolved "https://registry.yarnpkg.com/lexical/-/lexical-0.5.0.tgz#03a8abc816f6d922384ecd01bd14ed36a1ea4d63"
integrity sha512-J0cFuNPQQY5P9W5XW2/xgqp5W0eEQ2rxShLf8eevLvxFWsPSY3zjg3RCzTHyheSiGBBjKDIaM4gxtO8eNeJr2A==
libphonenumber-js@^1.10.12:
version "1.10.12"
resolved "https://registry.yarnpkg.com/libphonenumber-js/-/libphonenumber-js-1.10.12.tgz#75ebe2f1887d12bbf45af5655fdb63f55f4ee05b"