mirror of
https://github.com/nextui-org/nextui.git
synced 2025-12-08 19:26:11 +00:00
feat(docs): new snapshot, release blog in progress
This commit is contained in:
parent
aedda9d0de
commit
1976c62105
128
apps/docs/app/blog/[slug]/page.tsx
Normal file
128
apps/docs/app/blog/[slug]/page.tsx
Normal file
@ -0,0 +1,128 @@
|
||||
import type {Metadata} from "next";
|
||||
|
||||
import {notFound} from "next/navigation";
|
||||
import {allBlogPosts} from "contentlayer/generated";
|
||||
import {Link, User} from "@nextui-org/react";
|
||||
import {format, parseISO} from "date-fns";
|
||||
import NextLink from "next/link";
|
||||
import {Balancer} from "react-wrap-balancer";
|
||||
|
||||
import {MDXContent} from "@/components/mdx-content";
|
||||
import {siteConfig} from "@/config/site";
|
||||
import {Route} from "@/libs/docs/page";
|
||||
import {ChevronRightLinearIcon} from "@/components/icons";
|
||||
import {__PROD__} from "@/utils";
|
||||
|
||||
interface BlogPostProps {
|
||||
params: {
|
||||
slug: string;
|
||||
};
|
||||
}
|
||||
|
||||
async function getBlogPostFromParams({params}: BlogPostProps) {
|
||||
const slug = params.slug || "";
|
||||
const post = allBlogPosts.find((post) => post.slugAsParams === slug);
|
||||
|
||||
if (!post) {
|
||||
null;
|
||||
}
|
||||
|
||||
const currentRoute: Route = {
|
||||
key: post?._id,
|
||||
title: post?.title,
|
||||
path: `/${post?._raw?.sourceFilePath}`,
|
||||
};
|
||||
|
||||
return {post, currentRoute};
|
||||
}
|
||||
|
||||
export async function generateMetadata({params}: BlogPostProps): Promise<Metadata> {
|
||||
const {post} = await getBlogPostFromParams({params});
|
||||
|
||||
if (!post) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return {
|
||||
title: post.title,
|
||||
description: post.description,
|
||||
openGraph: {
|
||||
title: post.title,
|
||||
description: post.description,
|
||||
type: "article",
|
||||
url: post.url,
|
||||
images: [
|
||||
{
|
||||
url: post.imageAsParams || siteConfig.ogImage,
|
||||
width: 1200,
|
||||
height: 630,
|
||||
alt: post.title || siteConfig.name,
|
||||
},
|
||||
],
|
||||
},
|
||||
twitter: {
|
||||
card: "summary_large_image",
|
||||
title: post.title,
|
||||
description: post.description,
|
||||
images: [siteConfig.ogImage],
|
||||
creator: siteConfig.creator,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export async function generateStaticParams(): Promise<BlogPostProps["params"][]> {
|
||||
return allBlogPosts.map((doc) => ({
|
||||
slug: doc.slugAsParams,
|
||||
}));
|
||||
}
|
||||
|
||||
export default async function DocPage({params}: BlogPostProps) {
|
||||
const {post} = await getBlogPostFromParams({params});
|
||||
|
||||
if (!post || __PROD__) {
|
||||
notFound();
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="w-full mt-12 flex flex-col justify-start items-center prose prose-neutral">
|
||||
<div className="w-full max-w-4xl">
|
||||
<Link
|
||||
isBlock
|
||||
as={NextLink}
|
||||
className="mb-8 -ml-3 text-default-500 hover:text-default-900"
|
||||
color="foreground"
|
||||
href="/blog"
|
||||
size="sm"
|
||||
>
|
||||
<ChevronRightLinearIcon className="rotate-180 inline-block mr-1" size={15} />
|
||||
Back to blog
|
||||
</Link>
|
||||
<time className="block text-small mb-2 text-default-500" dateTime={post.date}>
|
||||
{format(parseISO(post.date), "LLLL d, yyyy")}
|
||||
</time>
|
||||
<div className="mb-3 flex w-full flex-col items-start">
|
||||
<User
|
||||
isExternal
|
||||
as={Link}
|
||||
avatarProps={{
|
||||
className: "w-9 h-9 text-large",
|
||||
src: post.author?.avatar,
|
||||
}}
|
||||
className="hover:opacity-100"
|
||||
classNames={{
|
||||
base: "-ml-2 px-2 py-1.5 hover:bg-default-100 dark:hover:bg-default-50 cursor-pointer transition-colors",
|
||||
name: "text-foreground",
|
||||
}}
|
||||
description={post.author?.username}
|
||||
href={post.author?.link}
|
||||
name={post.author?.name}
|
||||
/>
|
||||
</div>
|
||||
<h1 className="mb-2 font-bold text-4xl">
|
||||
<Balancer>{post.title}</Balancer>
|
||||
</h1>
|
||||
<MDXContent code={post.body.code} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
27
apps/docs/app/blog/layout.tsx
Normal file
27
apps/docs/app/blog/layout.tsx
Normal file
@ -0,0 +1,27 @@
|
||||
import {Image} from "@nextui-org/react";
|
||||
|
||||
interface DocsLayoutProps {
|
||||
children: React.ReactNode;
|
||||
}
|
||||
|
||||
export default function DocsLayout({children}: DocsLayoutProps) {
|
||||
return (
|
||||
<>
|
||||
<main className="relative container mx-auto max-w-7xl z-10 px-6 min-h-[calc(100vh_-_64px_-_108px)] mb-12 flex-grow">
|
||||
{children}
|
||||
</main>
|
||||
<div
|
||||
aria-hidden="true"
|
||||
className="fixed hidden dark:md:block dark:opacity-70 -bottom-[40%] -left-[20%] z-0"
|
||||
>
|
||||
<Image removeWrapper alt="docs left background" src="/gradients/docs-left.png" />
|
||||
</div>
|
||||
<div
|
||||
aria-hidden="true"
|
||||
className="fixed hidden dark:md:block dark:opacity-70 -top-[80%] -right-[60%] 2xl:-top-[60%] 2xl:-right-[45%] z-0 rotate-12"
|
||||
>
|
||||
<Image removeWrapper alt="docs right background" src="/gradients/docs-right.png" />
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
23
apps/docs/app/blog/page.tsx
Normal file
23
apps/docs/app/blog/page.tsx
Normal file
@ -0,0 +1,23 @@
|
||||
import {allBlogPosts} from "contentlayer/generated";
|
||||
import {compareDesc} from "date-fns";
|
||||
|
||||
import {BlogPostList} from "@/components/blog-post";
|
||||
import {__PROD__} from "@/utils";
|
||||
|
||||
export default function Blog() {
|
||||
const posts = allBlogPosts.sort((a, b) => compareDesc(new Date(a.date), new Date(b.date)));
|
||||
|
||||
if (__PROD__) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="w-full lg:px-16 mt-12">
|
||||
<div className="text-center">
|
||||
<h1 className="mb-2 font-bold text-4xl">NextUI Latest Updates</h1>
|
||||
<h5 className="text-default-500 text-lg">All the latest news about NextUI.</h5>
|
||||
</div>
|
||||
<BlogPostList posts={posts} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@ -78,8 +78,6 @@ export async function generateStaticParams(): Promise<DocPageProps["params"][]>
|
||||
}
|
||||
|
||||
export default async function DocPage({params}: DocPageProps) {
|
||||
// const {doc, source, tag, slug, currentRoute, headings} = await getDocData({params});
|
||||
|
||||
const {doc, headings, currentRoute} = await getDocFromParams({params});
|
||||
|
||||
if (!doc) {
|
||||
|
||||
27
apps/docs/app/examples/demo/page.tsx
Normal file
27
apps/docs/app/examples/demo/page.tsx
Normal file
@ -0,0 +1,27 @@
|
||||
"use client";
|
||||
|
||||
import {Card, CardBody, CircularProgress} from "@nextui-org/react";
|
||||
|
||||
export default function ButtonDemo() {
|
||||
return (
|
||||
<main className="dark bg-background text-foreground">
|
||||
<div className="flex w-screen h-screen items-center justify-center">
|
||||
<Card className="w-[240px] h-[240px] bg-default-200 dark:bg-default-50">
|
||||
<CardBody className="justify-center items-center py-0">
|
||||
<CircularProgress
|
||||
classNames={{
|
||||
svg: "w-36 h-36 drop-shadow-md",
|
||||
indicator: "stroke-foreground",
|
||||
track: "stroke-foreground/10",
|
||||
value: "text-3xl font-semibold text-foreground",
|
||||
}}
|
||||
showValueLabel={true}
|
||||
strokeWidth={4}
|
||||
value={70}
|
||||
/>
|
||||
</CardBody>
|
||||
</Card>
|
||||
</div>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
68
apps/docs/components/blog-post.tsx
Normal file
68
apps/docs/components/blog-post.tsx
Normal file
@ -0,0 +1,68 @@
|
||||
"use client";
|
||||
|
||||
import {BlogPost} from "contentlayer/generated";
|
||||
import {Card, CardFooter, CardBody, CardHeader, Link, Avatar} from "@nextui-org/react";
|
||||
import Balancer from "react-wrap-balancer";
|
||||
import {format, parseISO} from "date-fns";
|
||||
import NextLink from "next/link";
|
||||
import {AnimatePresence, motion} from "framer-motion";
|
||||
|
||||
import {useIsMounted} from "@/hooks/use-is-mounted";
|
||||
|
||||
const BlogPostCard = (post: BlogPost) => {
|
||||
const isMounted = useIsMounted();
|
||||
|
||||
return (
|
||||
<AnimatePresence>
|
||||
{isMounted && (
|
||||
<motion.div
|
||||
animate={{opacity: 1, y: 0}}
|
||||
exit={{opacity: 0, y: 5}}
|
||||
initial={{opacity: 0, y: 5}}
|
||||
transition={{duration: 0.3}}
|
||||
>
|
||||
<Card
|
||||
isBlurred
|
||||
as={NextLink}
|
||||
className="p-2 border-transparent text-start bg-white/5 dark:bg-default-400/10 backdrop-blur-lg backdrop-saturate-[1.8]"
|
||||
href={post.url}
|
||||
isPressable={!!post.url}
|
||||
>
|
||||
<CardHeader>
|
||||
<Link
|
||||
as={NextLink}
|
||||
className="font-semibold "
|
||||
href={post.url}
|
||||
size="lg"
|
||||
underline="hover"
|
||||
>
|
||||
<Balancer>{post.title}</Balancer>
|
||||
</Link>
|
||||
</CardHeader>
|
||||
<CardBody className="px-3 pt-0 pb-1">
|
||||
<p className="font-normal text-default-600">
|
||||
<Balancer>{post.description}</Balancer>
|
||||
</p>
|
||||
</CardBody>
|
||||
<CardFooter className="flex justify-between items-center">
|
||||
<time className="block text-small text-default-500" dateTime={post.date}>
|
||||
{format(parseISO(post.date), "LLLL d, yyyy")}
|
||||
</time>
|
||||
<Avatar size="sm" src={post.author?.avatar} />
|
||||
</CardFooter>
|
||||
</Card>
|
||||
</motion.div>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
);
|
||||
};
|
||||
|
||||
export const BlogPostList = ({posts}: {posts: BlogPost[]}) => {
|
||||
return (
|
||||
<div className="mt-10 grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
||||
{posts.map((post, idx) => (
|
||||
<BlogPostCard key={idx} {...post} />
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
2
apps/docs/components/blog/components.ts
Normal file
2
apps/docs/components/blog/components.ts
Normal file
@ -0,0 +1,2 @@
|
||||
export * from "./nextjs-templates";
|
||||
export * from "./video-in-view";
|
||||
34
apps/docs/components/blog/nextjs-templates.tsx
Normal file
34
apps/docs/components/blog/nextjs-templates.tsx
Normal file
@ -0,0 +1,34 @@
|
||||
import {NewNextJSIcon} from "@/components/icons";
|
||||
import {FeaturesGrid} from "@/components/marketing/features-grid";
|
||||
|
||||
const frameworks = [
|
||||
{
|
||||
title: "Next.js 13 (App) Template",
|
||||
isExternal: true,
|
||||
description:
|
||||
"A Next.js 13 with app directory template pre-configured with NextUI (v2) and Tailwind CSS.",
|
||||
icon: <NewNextJSIcon height={40} width={40} />,
|
||||
href: "https://github.com/nextui-org/next-app-template",
|
||||
},
|
||||
{
|
||||
title: "Next.js 13 (Pages) Template",
|
||||
isExternal: true,
|
||||
description:
|
||||
"A Next.js 13 with pages directory template pre-configured with NextUI (v2) and Tailwind CSS.",
|
||||
icon: <NewNextJSIcon height={40} width={40} />,
|
||||
href: "https://github.com/nextui-org/next-pages-template",
|
||||
},
|
||||
];
|
||||
|
||||
export const NextJsTemplates = () => {
|
||||
return (
|
||||
<FeaturesGrid
|
||||
classNames={{
|
||||
base: "mt-8 grid grid-cols-1 md:grid-cols-2 lg:grid-cols-2 gap-4",
|
||||
iconWrapper: "bg-default-300/20",
|
||||
body: "py-0",
|
||||
}}
|
||||
features={frameworks}
|
||||
/>
|
||||
);
|
||||
};
|
||||
91
apps/docs/components/blog/video-in-view.tsx
Normal file
91
apps/docs/components/blog/video-in-view.tsx
Normal file
@ -0,0 +1,91 @@
|
||||
/* eslint-disable jsx-a11y/media-has-caption */
|
||||
"use client";
|
||||
|
||||
import {useInView} from "framer-motion";
|
||||
import {useRef, FC, useEffect, useState, useCallback} from "react";
|
||||
import {Button, cn, Spinner, Tooltip} from "@nextui-org/react";
|
||||
|
||||
import {RotateLeftLinearIcon} from "@/components/icons";
|
||||
|
||||
interface VideoInViewProps {
|
||||
src: string;
|
||||
autoPlay?: boolean;
|
||||
width?: number;
|
||||
height?: number;
|
||||
controls?: boolean;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
export const VideoInView: FC<VideoInViewProps> = ({
|
||||
src,
|
||||
width,
|
||||
height,
|
||||
autoPlay = true,
|
||||
controls = false,
|
||||
className,
|
||||
}) => {
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
|
||||
const videoRef = useRef<HTMLVideoElement>(null);
|
||||
|
||||
const isVisible = useInView(videoRef);
|
||||
|
||||
// play video when it is visible
|
||||
useEffect(() => {
|
||||
if (isVisible) {
|
||||
videoRef.current?.play();
|
||||
} else {
|
||||
videoRef.current?.pause();
|
||||
}
|
||||
}, [isVisible]);
|
||||
|
||||
const handleCanPlayThrough = useCallback(() => {
|
||||
setIsLoading(false);
|
||||
}, []);
|
||||
|
||||
const onRestart = useCallback(() => {
|
||||
if (videoRef.current) {
|
||||
videoRef.current.currentTime = 0;
|
||||
videoRef.current.play();
|
||||
}
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className="relative">
|
||||
{isLoading && (
|
||||
<Spinner
|
||||
className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2"
|
||||
color="secondary"
|
||||
size="lg"
|
||||
/>
|
||||
)}
|
||||
<Tooltip content="Restart" delay={1000}>
|
||||
<Button
|
||||
isIconOnly
|
||||
className="absolute z-50 right-3 top-3 border-1 border-transparent bg-transparent before:bg-white/10 before:content-[''] before:block before:z-[-1] before:absolute before:inset-0 before:backdrop-blur-md before:backdrop-saturate-100 before:rounded-lg"
|
||||
size="sm"
|
||||
variant="bordered"
|
||||
onPress={onRestart}
|
||||
>
|
||||
<RotateLeftLinearIcon size={16} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<video
|
||||
ref={videoRef}
|
||||
loop
|
||||
muted
|
||||
autoPlay={autoPlay}
|
||||
className={cn(
|
||||
"w-full border border-transparent dark:border-default-200/50 object-fit rounded-xl shadow-lg",
|
||||
className,
|
||||
)}
|
||||
controls={controls}
|
||||
height={height}
|
||||
src={src}
|
||||
width={width}
|
||||
onCanPlayThrough={handleCanPlayThrough}
|
||||
onPlaying={() => setIsLoading(false)}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@ -206,6 +206,10 @@ export const CommonColors = () => {
|
||||
title: "Cyan",
|
||||
items: getCommonItems([...Object.values(commonColors.cyan)]),
|
||||
},
|
||||
{
|
||||
title: "Zinc",
|
||||
items: getCommonItems([...Object.values(commonColors.zinc)]),
|
||||
},
|
||||
]}
|
||||
/>
|
||||
);
|
||||
|
||||
@ -19,3 +19,4 @@ export * from "./hash";
|
||||
export * from "./chevron-right";
|
||||
export * from "./search";
|
||||
export * from "./simple-grid";
|
||||
export * from "./rotate-left";
|
||||
|
||||
36
apps/docs/components/icons/linear/rotate-left.tsx
Normal file
36
apps/docs/components/icons/linear/rotate-left.tsx
Normal file
@ -0,0 +1,36 @@
|
||||
import {IconSvgProps} from "@/types";
|
||||
|
||||
export const RotateLeftLinearIcon = ({size = 24, width, height, ...props}: IconSvgProps) => (
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
fill="none"
|
||||
focusable="false"
|
||||
height={size || height}
|
||||
role="presentation"
|
||||
viewBox="0 0 24 24"
|
||||
width={size || width}
|
||||
{...props}
|
||||
>
|
||||
<path
|
||||
d="M9.11008 5.0799C9.98008 4.8199 10.9401 4.6499 12.0001 4.6499C16.7901 4.6499 20.6701 8.5299 20.6701 13.3199C20.6701 18.1099 16.7901 21.9899 12.0001 21.9899C7.21008 21.9899 3.33008 18.1099 3.33008 13.3199C3.33008 11.5399 3.87008 9.8799 4.79008 8.4999"
|
||||
stroke="currentColor"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth="1.5"
|
||||
/>
|
||||
<path
|
||||
d="M7.87012 5.32L10.7601 2"
|
||||
stroke="currentColor"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth="1.5"
|
||||
/>
|
||||
<path
|
||||
d="M7.87012 5.32007L11.2401 7.78007"
|
||||
stroke="currentColor"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth="1.5"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
@ -65,13 +65,13 @@ export const FeaturesGrid: React.FC<FeaturesGridProps> = ({features, classNames,
|
||||
<p className={slots.title({class: classNames?.title})}>{feat.title}</p>
|
||||
{feat.isExternal && <LinkIcon className="text-white" height={18} width={18} />}
|
||||
</CardHeader>
|
||||
{feat.description && (
|
||||
{feat.description ? (
|
||||
<CardBody className={slots.body({class: classNames?.body})}>
|
||||
<p className={slots.description({class: classNames?.description})}>
|
||||
{feat.description}
|
||||
</p>
|
||||
</CardBody>
|
||||
)}
|
||||
) : null}
|
||||
</Card>
|
||||
))}
|
||||
</div>
|
||||
|
||||
@ -8,6 +8,7 @@ import {ThemeSwitch} from "./theme-switch";
|
||||
|
||||
import {Sandpack} from "@/components/sandpack";
|
||||
import * as DocsComponents from "@/components/docs/components";
|
||||
import * as BlogComponents from "@/components/blog/components";
|
||||
import {Codeblock} from "@/components/docs/components";
|
||||
import {VirtualAnchor, virtualAnchorEncode} from "@/components";
|
||||
|
||||
@ -173,6 +174,10 @@ export const MDXComponents = {
|
||||
...DocsComponents,
|
||||
Sandpack,
|
||||
ThemeSwitch,
|
||||
/**
|
||||
* Blog components
|
||||
*/
|
||||
...BlogComponents,
|
||||
/**
|
||||
* Markdown components
|
||||
*/
|
||||
|
||||
@ -42,6 +42,7 @@ import {
|
||||
import {useIsMounted} from "@/hooks/use-is-mounted";
|
||||
import {DocsSidebar} from "@/components/docs/sidebar";
|
||||
import {useCmdkStore} from "@/components/cmdk";
|
||||
import {__PROD__} from "@/utils";
|
||||
|
||||
export interface NavbarProps {
|
||||
routes: Route[];
|
||||
@ -108,6 +109,11 @@ export const Navbar: FC<NavbarProps> = ({children, routes, slug, tag}) => {
|
||||
return null;
|
||||
}
|
||||
|
||||
const navLinkClasses = clsx(
|
||||
link({color: "foreground"}),
|
||||
"data-[active=true]:text-primary data-[active=true]:font-medium",
|
||||
);
|
||||
|
||||
return (
|
||||
<NextUINavbar
|
||||
ref={ref}
|
||||
@ -166,10 +172,7 @@ export const Navbar: FC<NavbarProps> = ({children, routes, slug, tag}) => {
|
||||
<ul className="hidden lg:flex gap-4 justify-start">
|
||||
<NavbarItem>
|
||||
<NextLink
|
||||
className={clsx(
|
||||
link({color: "foreground"}),
|
||||
"data-[active=true]:text-primary data-[active=true]:font-medium",
|
||||
)}
|
||||
className={navLinkClasses}
|
||||
color="foreground"
|
||||
data-active={includes(docsPaths, pathname)}
|
||||
href="/docs/guide/introduction"
|
||||
@ -179,10 +182,7 @@ export const Navbar: FC<NavbarProps> = ({children, routes, slug, tag}) => {
|
||||
</NavbarItem>
|
||||
<NavbarItem>
|
||||
<NextLink
|
||||
className={clsx(
|
||||
link({color: "foreground"}),
|
||||
"data-[active=true]:text-primary data-[active=true]:font-medium",
|
||||
)}
|
||||
className={navLinkClasses}
|
||||
color="foreground"
|
||||
data-active={includes(pathname, "components")}
|
||||
href="/docs/components/avatar"
|
||||
@ -190,14 +190,23 @@ export const Navbar: FC<NavbarProps> = ({children, routes, slug, tag}) => {
|
||||
Components
|
||||
</NextLink>
|
||||
</NavbarItem>
|
||||
{!__PROD__ && (
|
||||
<NavbarItem>
|
||||
<NextLink
|
||||
className={navLinkClasses}
|
||||
color="foreground"
|
||||
data-active={includes(pathname, "blog")}
|
||||
href="/blog"
|
||||
>
|
||||
Blog
|
||||
</NextLink>
|
||||
</NavbarItem>
|
||||
)}
|
||||
<NavbarItem>
|
||||
<NextLink
|
||||
className={clsx(
|
||||
link({color: "foreground"}),
|
||||
"data-[active=true]:text-primary data-[active=true]:font-medium",
|
||||
)}
|
||||
className={navLinkClasses}
|
||||
color="foreground"
|
||||
data-active={pathname === "/figma"}
|
||||
data-active={includes(pathname, "figma")}
|
||||
href="/figma"
|
||||
>
|
||||
Figma
|
||||
|
||||
301
apps/docs/content/blog/nextui-v2.mdx
Normal file
301
apps/docs/content/blog/nextui-v2.mdx
Normal file
@ -0,0 +1,301 @@
|
||||
---
|
||||
title: "Introducing NextUI Version 2"
|
||||
description: "Discover NextUI v2. TailwindCSS integration, enhanced theming, improved animations, and more."
|
||||
date: "2023-07-29"
|
||||
image: "/blog/nextuiv2.jpg"
|
||||
author:
|
||||
name: "Junior Garcia"
|
||||
username: "@jrgarciadev"
|
||||
link: "https://twitter.com/jrgarciadev"
|
||||
avatar: "/avatars/junior-garcia.jpeg"
|
||||
---
|
||||
|
||||
<img
|
||||
src="/blog/nextuiv2.jpg"
|
||||
width={700}
|
||||
height={350}
|
||||
alt="NextUI v2"
|
||||
className="w-full border border-transparent dark:border-default-200/50 object-fit rounded-xl shadow-lg"
|
||||
/>
|
||||
|
||||
We're thrilled to announce the release of **NextUI v2.0**. Our mission has always been to create a more
|
||||
efficient, flexible, **beautiful** and customizable UI library for you. And, this update is a huge leap
|
||||
towards achieving that.
|
||||
|
||||
## Table of Contents
|
||||
|
||||
- [Transition to TailwindCSS](#transition-to-tailwindcss) - Our shift to TailwindCSS.
|
||||
- [TailwindCSS Plugin](#tailwindcss-plugin) - Introducing theme customization plugin.
|
||||
- [React Server Components](#react-server-components) - Enhanced performance with React Server Components.
|
||||
- [Custom Themes, Layouts, Colors](#custom-themes-layouts-colors) - New customizability options.
|
||||
- [Enhanced Documentation](#enhanced-documentation) - A better navigation experience.
|
||||
- [New Templates & Guides](#new-templates-guides) - Easier app creation process.
|
||||
- [Custom Variants](#custom-variants) - Customization of components' variants.
|
||||
- [Enhanced Styling Model](#enhanced-styling-model) - Effortless component styling.
|
||||
- [Tailwind Variants](#tailwind-variants) - Our new library for better TailwindCSS handling.
|
||||
- [Revamped Components](#revamped-components) - Rewritten components with react-aria hooks.
|
||||
- [Optimized Animations](#optimized-animations) - Smoother app animations.
|
||||
- [Individual Packages](#individual-packages) - Install only what you need.
|
||||
- [Dark Mode Support](#dark-mode-support) - Easier implementation of dark mode.
|
||||
- [New Components](#new-components) - Six new components added.
|
||||
- [Figma Community File](#figma-community-file) - Streamlining design-to-development process.
|
||||
- [Get Started](#get-started) - Get on board with NextUI v2.0.
|
||||
|
||||
<Spacer y={4} />
|
||||
|
||||
## What's New in Version 2?
|
||||
|
||||
<Spacer y={4} />
|
||||
|
||||
### Transition from Stitches to TailwindCSS
|
||||
|
||||
We've transitioned from [Stitches](https://stitches.dev/) to [TailwindCSS](https://tailwindcss.com/),
|
||||
eliminating runtime styles and bringing you a more flexible and customizable UI library. This change allows
|
||||
you to use NextUI v2 with the latest versions of [React](https://reactjs.org/) and [Next.js](https://nextjs.org/) without running
|
||||
into React Server Components issues.
|
||||
|
||||
### TailwindCSS Plugin
|
||||
|
||||
NextUI v2.0 comes with a TailwindCSS plugin that enables the customization and addition of default themes.
|
||||
This plugin allows you to customize colors and layouts tokens that are used by NextUI components.
|
||||
|
||||
```js {8,13-14}
|
||||
// tailwind.config.js
|
||||
const {nextui} = require("@nextui-org/react");
|
||||
|
||||
/** @type {import('tailwindcss').Config} */
|
||||
module.exports = {
|
||||
content: [
|
||||
// ...
|
||||
"./node_modules/@nextui-org/theme/dist/**/*.{js,ts,jsx,tsx}",
|
||||
],
|
||||
theme: {
|
||||
extend: {},
|
||||
},
|
||||
darkMode: "class",
|
||||
plugins: [nextui()],
|
||||
};
|
||||
```
|
||||
|
||||
> Go to [Themes](/docs/customization/theme) documentation to learn more about the plugin and how to use it.
|
||||
|
||||
### React Server Components Support
|
||||
|
||||
Thanks to the switch to TailwindCSS, **NextUI v2.0** now supports React Server Components by default. This
|
||||
improves performance and allows you to use it with the latest versions of [React](https://reactjs.org/) and
|
||||
[Next.js](https://nextjs.org/).
|
||||
|
||||
NextUI components already inclue the `use client;` directive so you can import them
|
||||
server components.
|
||||
|
||||
```jsx
|
||||
// app/page.tsx
|
||||
import {Button} from "@nextui-org/button";
|
||||
|
||||
export default function Page() {
|
||||
return (
|
||||
<div>
|
||||
<Button>Click me</Button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
### Custom Themes, Layouts and Colors
|
||||
|
||||
The `nextui` TailwindCSS plugin allows you to customize the default themes, layouts and colors tokens. It
|
||||
also allows you to add new themes and customize them.
|
||||
|
||||
```js
|
||||
module.exports = {
|
||||
plugins: [
|
||||
nextui({
|
||||
themes: {
|
||||
light: {
|
||||
layout: {}, // light theme layout tokens
|
||||
colors: {}, // light theme colors
|
||||
},
|
||||
dark: {
|
||||
layout: {}, // dark theme layout tokens
|
||||
colors: {}, // dark theme colors
|
||||
},
|
||||
custom: {
|
||||
layout: {
|
||||
// custom theme layout tokens
|
||||
extend: "light" / "dark", // extend from light or dark theme
|
||||
},
|
||||
colors: {}, // custom theme colors
|
||||
},
|
||||
// ... custom themes
|
||||
},
|
||||
}),
|
||||
],
|
||||
};
|
||||
```
|
||||
|
||||
> Check out the [Layout](/docs/customization/layout) and [Colors](/docs/customization/colors) documentation
|
||||
> for better understanding of the layout and colors tokens.
|
||||
|
||||
### Enhanced Documentation
|
||||
|
||||
We've built our new documentation on top of Next.js 13 using the App directory, making it simpler, more
|
||||
robust, and more helpful than ever before. Additionally, we've improved the structure by placing useful
|
||||
links at the top of each component documentation, such as the component storybook, npm, react-aria hooks, and links to
|
||||
the source code and styles source code.
|
||||
|
||||
<VideoInView
|
||||
src="https://nextui-public-resources.s3.amazonaws.com/new-docs.mp4"
|
||||
width={700}
|
||||
height={350}
|
||||
/>
|
||||
|
||||
### New Templates and Guides
|
||||
|
||||
Two Next.js templates for App and Pages directories, alongside Vite, Remix, and Astro
|
||||
installation guides, are introduced to aid your app creation process.
|
||||
|
||||
#### Next.js Templates
|
||||
|
||||
<NextJsTemplates />
|
||||
|
||||
#### Frameworks
|
||||
|
||||
<Frameworks />
|
||||
|
||||
### Custom Variants
|
||||
|
||||
We've added a new function, `extendVariants`, that allows you to customize any NextUI components's variants.
|
||||
|
||||
<VideoInView
|
||||
src="https://nextui-public-resources.s3.amazonaws.com/custom-variants.mp4"
|
||||
width={700}
|
||||
height={350}
|
||||
/>
|
||||
|
||||
You can create or override the component `variants`, `defaultVariants` and `componentVariants`.
|
||||
|
||||
> Check out the [Custom Variants](/docs/customization/variants) documentation for more information.
|
||||
|
||||
### Enhanced Styling Model
|
||||
|
||||
With the new slots model, you can style every part of your components effortlessly.
|
||||
|
||||
<VideoInView
|
||||
src="https://nextui-public-resources.s3.amazonaws.com/override-styles.mp4"
|
||||
width={700}
|
||||
height={350}
|
||||
/>
|
||||
|
||||
> Check out the [Override Styles](/docs/customization/override-styles) documentation for more information.
|
||||
|
||||
### Tailwind Variants
|
||||
|
||||
Our new library, [Tailwind Variants](https://tailwind-variants.org), allows you to write TailwindCSS for large components in a reusable
|
||||
and clear way. It automatically handles TailwindCSS class conflicts and all NextUI components are built on top of it.
|
||||
|
||||
> Check out the [Tailwind Variants](https://tailwind-variants.org) documentation for more information.
|
||||
|
||||
### Revamped Components
|
||||
|
||||
All components are written from scratch and integrated with [react-aria](https://react-spectrum.adobe.com/react-aria/index.html) hooks, ensuring enhanced performance
|
||||
and better accessibility.
|
||||
|
||||
### Optimized Animations
|
||||
|
||||
Thanks to [framer-motion](https://www.framer.com/motion/), we've significantly improved and optimized animations to make your
|
||||
app feel more fluid and smooth.
|
||||
|
||||
<VideoInView
|
||||
src="https://nextui-public-resources.s3.amazonaws.com/dropdown-animation.mp4"
|
||||
width={700}
|
||||
height={350}
|
||||
/>
|
||||
|
||||
### Individual Packages Support
|
||||
|
||||
Install only what you need, reducing CSS bundle as it will only include styles for the components
|
||||
you're actually using.
|
||||
|
||||
<PackageManagers
|
||||
commands={{
|
||||
npm: "npm i @nextui-org/button",
|
||||
yarn: "yarn add @nextui-org/button",
|
||||
pnpm: "pnpm add @nextui-org/button",
|
||||
}}
|
||||
/>
|
||||
|
||||
> Check out the [Individual Packages](/docs/guide/installation#individual-installation) documentation for more information.
|
||||
|
||||
### Dark Mode Support
|
||||
|
||||
Implementing dark mode has never been easier. Thanks to the `nextui` TailwindCSS plugin, you can now use the `dark` theme
|
||||
by just adding the `dark` class to the `body` / `html` or `main` tag.
|
||||
|
||||
```jsx {11}
|
||||
// main.tsx or main.jsx
|
||||
import React from "react";
|
||||
import ReactDOM from "react-dom/client";
|
||||
import {NextUIProvider} from "@nextui-org/react";
|
||||
import App from "./App";
|
||||
import "./index.css";
|
||||
|
||||
ReactDOM.createRoot(document.getElementById("root")).render(
|
||||
<React.StrictMode>
|
||||
<NextUIProvider>
|
||||
<main className="dark text-foreground bg-background">
|
||||
<App />
|
||||
</main>
|
||||
</NextUIProvider>
|
||||
</React.StrictMode>,
|
||||
);
|
||||
```
|
||||
|
||||
<VideoInView
|
||||
src="https://nextui-public-resources.s3.amazonaws.com/dark-mode.mp4"
|
||||
width={700}
|
||||
height={350}
|
||||
/>
|
||||
|
||||
> **Note**: **text-foreground** and **bg-background** changes the text and background colors to the current theme.
|
||||
|
||||
### New Components
|
||||
|
||||
We've added 6 new components, expanding the possibilities of what you can create.
|
||||
|
||||
- [Chip](/docs/components/chip): Small block of essential information that represent an input, attribute, or action.
|
||||
- [Divider](/docs/components/divider): A line that separates content in a page.
|
||||
- [Kbd](/docs/components/kbd): Displays which `key` or combination of keys performs a given action.
|
||||
- [Skeleton](/docs/components/skeleton): Placeholder for loading content.
|
||||
- [Snippet](/docs/components/snippet): Displays a code snippet.
|
||||
- [Tabs](/docs/components/tabs): Organize content into separate views where only one view is visible at a time.
|
||||
|
||||
## Figma Community File
|
||||
|
||||
We're excited to also announce our **Figma Community File**. This file will enable you to easily translate
|
||||
your designs into NextUI components. Whether you're a solo developer or working with a design team, our Figma
|
||||
file helps streamline the process of transforming design ideas into functioning UI components.
|
||||
|
||||
<Blockquote color="warning">
|
||||
This file is still in development and will be continuously updated.
|
||||
</Blockquote>
|
||||
|
||||
<iframe
|
||||
height="450"
|
||||
width="800"
|
||||
src="https://embed.figma.com/file/1267584376234254760/hf_embed?community_viewer=true&embed_host=nextui"
|
||||
className="aspect-video w-full border border-transparent dark:border-default-200/50 object-fit rounded-xl shadow-lg"
|
||||
/>
|
||||
|
||||
<Spacer y={10} />
|
||||
|
||||
<Button color="default" variant="bordered">
|
||||
<Link isExternal className="text-current" href="https://www.figma.com/community/file/1267584376234254760">
|
||||
Open in Figma
|
||||
</Link>
|
||||
</Button>
|
||||
|
||||
## Get Started
|
||||
|
||||
To start using **NextUI v2.0**, head over to our [installation guide](/docs/guide/installation).
|
||||
|
||||
We can't wait to see the amazing things you'll build with **NextUI v2.0**!
|
||||
@ -7,7 +7,7 @@ import {chipContent} from "@/content/components/chip";
|
||||
|
||||
# Chip
|
||||
|
||||
A Chip is a small block of essential information that represent an input, attribute, or action
|
||||
A Chip is a small block of essential information that represent an input, attribute, or action.
|
||||
|
||||
<ComponentLinks component="chip" />
|
||||
|
||||
|
||||
@ -14,7 +14,7 @@ You can create or override the component `variants`, `defaultVariants` and `comp
|
||||
|
||||
## Creating new variants for non-slots components
|
||||
|
||||
The [Button](/docs/components/button) component is a non-slots component, meaning that it does not
|
||||
The [Button](/docs/components/button) component is a non-slots component, meaning that it does not
|
||||
have any slots that can be customized.
|
||||
|
||||
For this example, we will be using the `Button` component's styles source code as a
|
||||
@ -34,8 +34,9 @@ allows you to create a new component based on the original component, and custom
|
||||
import {extendVariants, Button} from "@nextui-org/react";
|
||||
|
||||
export const MyButton = extendVariants(Button, {
|
||||
variants: {// <- modify/add variants
|
||||
color: {
|
||||
variants: {
|
||||
// <- modify/add variants
|
||||
color: {
|
||||
olive: "text-[#000] bg-[#84cc16]",
|
||||
orange: "bg-[#ff8c00] text-[#fff]",
|
||||
violet: "bg-[#8b5cf6] text-[#fff]",
|
||||
@ -43,29 +44,31 @@ export const MyButton = extendVariants(Button, {
|
||||
isDisabled: {
|
||||
true: "bg-[#eaeaea] text-[#000] opacity-50 cursor-not-allowed",
|
||||
},
|
||||
size: {
|
||||
size: {
|
||||
xs: "px-unit-2 min-w-unit-12 h-unit-6 text-tiny gap-unit-1 rounded-small",
|
||||
md: "px-unit-4 min-w-unit-20 h-unit-10 text-small gap-unit-2 rounded-small",
|
||||
xl: "px-unit-8 min-w-unit-28 h-unit-14 text-large gap-unit-4 rounded-medium",
|
||||
},
|
||||
},
|
||||
defaultVariants: { // <- modify/add the default variants
|
||||
defaultVariants: {
|
||||
// <- modify/add the default variants
|
||||
color: "olive",
|
||||
size: "xl",
|
||||
},
|
||||
componentVariants: [ // <- modify/add the component variants
|
||||
componentVariants: [
|
||||
// <- modify/add the component variants
|
||||
{
|
||||
isDisabled: true,
|
||||
color: "olive",
|
||||
class: "bg-[#84cc16]/80 opacity-100"
|
||||
}
|
||||
class: "bg-[#84cc16]/80 opacity-100",
|
||||
},
|
||||
],
|
||||
});
|
||||
```
|
||||
|
||||
### Use your custom component in your application
|
||||
|
||||
Then, you can now use your custom component in your application. Here, `MyButton` is
|
||||
Then, you can now use your custom component in your application. Here, `MyButton` is
|
||||
used with the color set to `olive` and the size set to `xl`.
|
||||
|
||||
```tsx
|
||||
@ -76,10 +79,10 @@ const MyApp = () => {
|
||||
return (
|
||||
<MyButton color="olive" size="md">
|
||||
Press Me
|
||||
</MyButton>
|
||||
</MyButton>
|
||||
);
|
||||
}
|
||||
```
|
||||
};
|
||||
```
|
||||
|
||||
The new component will include the original props of the `Button` component, plus the new
|
||||
variants that you have created.
|
||||
@ -94,15 +97,13 @@ import customVariantsNoSlots from "@/content/customization/custom-variants/no-sl
|
||||
|
||||
</Steps>
|
||||
|
||||
|
||||
## Creating new variants for slots components
|
||||
|
||||
It is also possible to use the `extendVariants` function to add or override variants for
|
||||
components that have slots.
|
||||
|
||||
The [Input](/docs/components/input) component is a slots component, meaning that it has slots that can be
|
||||
customized.
|
||||
|
||||
customized.
|
||||
|
||||
For this example, we will be using the `Input` component's styles source code as a
|
||||
reference. Go [here](https://github.com/nextui-org/nextui/blob/feat/v2/packages/core/theme/src/components/input.ts) to view the styles source code.
|
||||
@ -121,10 +122,13 @@ allows you to create a new component based on the original component, and custom
|
||||
import {extendVariants, Input} from "@nextui-org/react";
|
||||
|
||||
const MyInput = extendVariants(Input, {
|
||||
variants: { // <- modify/add variants
|
||||
color: {
|
||||
stone: { // <- add a new color variant
|
||||
inputWrapper: [ // <- Input wrapper slot
|
||||
variants: {
|
||||
// <- modify/add variants
|
||||
color: {
|
||||
stone: {
|
||||
// <- add a new color variant
|
||||
inputWrapper: [
|
||||
// <- Input wrapper slot
|
||||
"bg-zinc-100",
|
||||
"border",
|
||||
"shadow",
|
||||
@ -139,7 +143,8 @@ const MyInput = extendVariants(Input, {
|
||||
"dark:data-[hover=true]:bg-zinc-900",
|
||||
"dark:focus-within:bg-zinc-900",
|
||||
],
|
||||
input: [ // Input element slot
|
||||
input: [
|
||||
// Input element slot
|
||||
"text-zinc-800",
|
||||
"placeholder:text-zinc-600",
|
||||
// dark theme
|
||||
@ -194,7 +199,7 @@ const MyInput = extendVariants(Input, {
|
||||
|
||||
Then, you can now use your custom component in your application. Here, `MyInput` is
|
||||
used with the color set to `slate` and the size set to `xl`.
|
||||
|
||||
|
||||
```tsx
|
||||
// App.tsx
|
||||
import {MyInput} from "./MyInput";
|
||||
@ -210,7 +215,7 @@ const MyApp = () => {
|
||||
startContent={<SearchIcon className="text-zinc-500" size={16} />}
|
||||
/>
|
||||
);
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
The new component will include the original props of the [Input](/docs/components/input) component, plus the new
|
||||
@ -224,7 +229,6 @@ import customVariantsSlots from "@/content/customization/custom-variants/slots-c
|
||||
files={customVariantsSlots}
|
||||
/>
|
||||
|
||||
|
||||
</Steps>
|
||||
|
||||
<Blockquote>
|
||||
@ -233,31 +237,28 @@ import customVariantsSlots from "@/content/customization/custom-variants/slots-c
|
||||
custom component.
|
||||
</Blockquote>
|
||||
|
||||
|
||||
### Types
|
||||
|
||||
### Main Function
|
||||
|
||||
```jsx
|
||||
const Component = extendVariants(BaseComponent, options, config)
|
||||
const Component = extendVariants(BaseComponent, options, config);
|
||||
|
||||
/**
|
||||
* BaseComponent -> NextUI component to extend
|
||||
* options -> the variants to add/modify
|
||||
* config -> config to extend the component
|
||||
*/
|
||||
|
||||
```
|
||||
|
||||
### Options
|
||||
|
||||
```ts
|
||||
type ExtendVariantsOptions = {
|
||||
variants?: Record<string, Record<string, ClassValue>>,
|
||||
defaultVariants?: Record<string, ClassValue>,
|
||||
compoundVariants?: Array<Record<string, string> & ClassProp>
|
||||
}
|
||||
|
||||
variants?: Record<string, Record<string, ClassValue>>;
|
||||
defaultVariants?: Record<string, ClassValue>;
|
||||
compoundVariants?: Array<Record<string, string> & ClassProp>;
|
||||
};
|
||||
```
|
||||
|
||||
### Config
|
||||
@ -275,7 +276,6 @@ type ExtendVariantsOptions = {
|
||||
* @see https://github.com/dcastil/tailwind-merge/blob/v1.8.1/docs/configuration.md
|
||||
*/
|
||||
twMergeConfig?: TWMergeConfig;
|
||||
```
|
||||
```
|
||||
|
||||
> **Note**: See the [Tailwind Merge Config](https://github.com/dcastil/tailwind-merge/blob/v1.8.1/docs/configuration.md) to learn more about it.
|
||||
|
||||
|
||||
@ -5,27 +5,25 @@ description: Learn how to customize your application's appearance using NextUI's
|
||||
|
||||
# Theme
|
||||
|
||||
Theming is a key element in designing user interfaces (UIs). It enables the application of a
|
||||
consistent aesthetic across your application, enhancing the user experience and maintaining
|
||||
Theming is a key element in designing user interfaces (UIs). It enables the application of a
|
||||
consistent aesthetic across your application, enhancing the user experience and maintaining
|
||||
visual uniformity.
|
||||
|
||||
In NextUI, we facilitate easy and flexible theme customization using a
|
||||
TailwindCSS plugin. This plugin, which is based on the [tw-colors](https://github.com/L-Blondy/tw-colors)
|
||||
plugin developed by [L-Blondy](https://github.com/L-Blondy), allows you to customize color schemes,
|
||||
In NextUI, we facilitate easy and flexible theme customization using a
|
||||
TailwindCSS plugin. This plugin, which is based on the [tw-colors](https://github.com/L-Blondy/tw-colors)
|
||||
plugin developed by [L-Blondy](https://github.com/L-Blondy), allows you to customize color schemes,
|
||||
layout configurations, and more, across different components of your application.
|
||||
|
||||
|
||||
## What is a Theme?
|
||||
|
||||
A theme, in the context of NextUI, is a predefined set of colors, layout attributes, and other
|
||||
UI elements that you can consistently apply across your application. Themes ensure visual
|
||||
consistency, enrich the user experience, and simplify the management and updates of your
|
||||
A theme, in the context of NextUI, is a predefined set of colors, layout attributes, and other
|
||||
UI elements that you can consistently apply across your application. Themes ensure visual
|
||||
consistency, enrich the user experience, and simplify the management and updates of your
|
||||
app's look and feel.
|
||||
|
||||
|
||||
## Setup
|
||||
|
||||
The first step to using NextUI's theming capability is adding the `nextui` plugin to your
|
||||
The first step to using NextUI's theming capability is adding the `nextui` plugin to your
|
||||
`tailwind.config.js` file. Below is an example of how to do this:
|
||||
|
||||
```js {8,13-14}
|
||||
@ -48,7 +46,7 @@ module.exports = {
|
||||
|
||||
### Usage
|
||||
|
||||
After adding the plugin to your `tailwind.config.js` file, you can utilize any of the default
|
||||
After adding the plugin to your `tailwind.config.js` file, you can utilize any of the default
|
||||
themes (light/dark) or a custom one. Here's how you can apply these themes in your `main.jsx` or `main.tsx`:
|
||||
|
||||
Go to the src directory and inside `main.jsx` or `main.tsx`, apply the following class names to the root element:
|
||||
@ -165,13 +163,11 @@ examples of how to do this:
|
||||
</div>
|
||||
```
|
||||
|
||||
|
||||
### API Reference
|
||||
|
||||
The following table provides an overview of the various attributes you can use when working
|
||||
The following table provides an overview of the various attributes you can use when working
|
||||
with themes in NextUI:
|
||||
|
||||
|
||||
| Attribute | Type | Description | Default |
|
||||
| ------------------ | ----------------------------- | --------------------------------------------------------------------------------------------------------------- | -------- |
|
||||
| prefix | `string` | The prefix for the css variables. | `nextui` |
|
||||
|
||||
@ -1,8 +1,22 @@
|
||||
import {defineDocumentType, makeSource} from "contentlayer/source-files";
|
||||
import {defineDocumentType, defineNestedType, makeSource} from "contentlayer/source-files";
|
||||
import remarkGfm from "remark-gfm";
|
||||
import rehypeSlug from "rehype-slug";
|
||||
import {visit} from "unist-util-visit";
|
||||
|
||||
/** @type {import('contentlayer/source-files').ComputedFields} */
|
||||
const computedFields = {
|
||||
slug: {
|
||||
type: "string",
|
||||
resolve: (doc) => `/${doc._raw.flattenedPath}`,
|
||||
},
|
||||
slugAsParams: {
|
||||
type: "string",
|
||||
resolve: (doc) => doc._raw.flattenedPath.split("/").slice(1).join("/"),
|
||||
},
|
||||
url: {type: "string", resolve: (doc) => `/${doc._raw.flattenedPath}`},
|
||||
}
|
||||
|
||||
|
||||
export const Doc = defineDocumentType(() => ({
|
||||
name: "Doc",
|
||||
filePathPattern: `docs/**/*.mdx`,
|
||||
@ -12,22 +26,58 @@ export const Doc = defineDocumentType(() => ({
|
||||
description: {type: "string", required: false},
|
||||
date: {type: "date", required: false},
|
||||
},
|
||||
computedFields: {
|
||||
slug: {
|
||||
type: "string",
|
||||
resolve: (doc) => `/${doc._raw.flattenedPath}`,
|
||||
},
|
||||
slugAsParams: {
|
||||
type: "string",
|
||||
resolve: (doc) => doc._raw.flattenedPath.split("/").slice(1).join("/"),
|
||||
},
|
||||
url: {type: "string", resolve: (doc) => `/${doc._raw.flattenedPath}`},
|
||||
computedFields
|
||||
}));
|
||||
|
||||
|
||||
const AuthorProperties = defineNestedType(() => ({
|
||||
name: "AuthorProperties",
|
||||
fields: {
|
||||
name: {type: "string", required: true},
|
||||
link: {type: "string", required: false},
|
||||
avatar: {type: "string", required: false},
|
||||
username: {type: "string", required: false},
|
||||
}
|
||||
}));
|
||||
|
||||
export const BlogPost = defineDocumentType(() => ({
|
||||
name: "BlogPost",
|
||||
filePathPattern: `blog/**/*.mdx`,
|
||||
contentType: "mdx",
|
||||
fields: {
|
||||
title: {type: "string", required: true},
|
||||
description: {type: "string", required: true},
|
||||
date: {type: "date", required: true},
|
||||
author: {type: "nested",of: AuthorProperties, required: false},
|
||||
image: {type: "string", required: false},
|
||||
},
|
||||
computedFields: {
|
||||
...computedFields,
|
||||
// Date format June 22nd 2023
|
||||
formattedDate: {
|
||||
type: "string",
|
||||
resolve: (doc) => {
|
||||
const date = new Date(doc.date);
|
||||
const options = {year: "numeric", month: "long", day: "numeric"};
|
||||
return date.toLocaleDateString("en-US", options);
|
||||
}
|
||||
},
|
||||
// add https://nextui.org to the image path
|
||||
imageAsParams: {
|
||||
type: "string",
|
||||
resolve: (doc) => {
|
||||
const image = doc.image;
|
||||
if (image) {
|
||||
return `https://nextui.org${image}`;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
export default makeSource({
|
||||
contentDirPath: "./content",
|
||||
documentTypes: [Doc],
|
||||
documentTypes: [Doc, BlogPost],
|
||||
mdx: {
|
||||
remarkPlugins: [remarkGfm],
|
||||
rehypePlugins: [
|
||||
|
||||
@ -62,6 +62,7 @@
|
||||
"react-icons": "^4.10.1",
|
||||
"react-live": "^2.3.0",
|
||||
"react-multi-ref": "^1.0.1",
|
||||
"react-wrap-balancer": "^1.0.0",
|
||||
"refractor": "3.3.1",
|
||||
"rehype": "11.0.0",
|
||||
"rehype-parse": "7.0.1",
|
||||
|
||||
BIN
apps/docs/public/avatars/junior-garcia.jpeg
Normal file
BIN
apps/docs/public/avatars/junior-garcia.jpeg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 34 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 59 KiB |
BIN
apps/docs/public/blog/nextuiv2.jpg
Normal file
BIN
apps/docs/public/blog/nextuiv2.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 21 KiB |
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nextui-org/accordion",
|
||||
"version": "0.0.0-dev-v2-20230729152229",
|
||||
"version": "0.0.0-dev-v2-20230730211830",
|
||||
"description": "Collapse display a list of high-level options that can expand/collapse to reveal more information.",
|
||||
"keywords": [
|
||||
"react",
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nextui-org/avatar",
|
||||
"version": "0.0.0-dev-v2-20230729152229",
|
||||
"version": "0.0.0-dev-v2-20230730211830",
|
||||
"description": "The Avatar component is used to represent a user, and displays the profile picture, initials or fallback icon.",
|
||||
"keywords": [
|
||||
"avatar"
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nextui-org/badge",
|
||||
"version": "0.0.0-dev-v2-20230729152229",
|
||||
"version": "0.0.0-dev-v2-20230730211830",
|
||||
"description": "Badges are used as a small numerical value or status descriptor for UI elements.",
|
||||
"keywords": [
|
||||
"badge"
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nextui-org/button",
|
||||
"version": "0.0.0-dev-v2-20230729152229",
|
||||
"version": "0.0.0-dev-v2-20230730211830",
|
||||
"description": "Buttons allow users to perform actions and choose with a single tap.",
|
||||
"keywords": [
|
||||
"button"
|
||||
|
||||
@ -53,7 +53,7 @@ interface Props extends HTMLNextUIProps<"button"> {
|
||||
isLoading?: boolean;
|
||||
/**
|
||||
* The native button click event handler.
|
||||
* @deprecated - use `onPress` instead.
|
||||
* use `onPress` instead.
|
||||
*/
|
||||
onClick?: MouseEventHandler<HTMLButtonElement>;
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nextui-org/card",
|
||||
"version": "0.0.0-dev-v2-20230729152229",
|
||||
"version": "0.0.0-dev-v2-20230730211830",
|
||||
"description": "Card is a container for text, photos, and actions in the context of a single subject.",
|
||||
"keywords": [
|
||||
"card"
|
||||
|
||||
@ -3,7 +3,7 @@ import type {SlotsToClasses, CardSlots, CardReturnType, CardVariantProps} from "
|
||||
import type {AriaButtonProps} from "@nextui-org/use-aria-button";
|
||||
|
||||
import {card} from "@nextui-org/theme";
|
||||
import {MouseEvent, useCallback, useMemo} from "react";
|
||||
import {MouseEvent, ReactNode, useCallback, useMemo} from "react";
|
||||
import {chain, mergeProps} from "@react-aria/utils";
|
||||
import {useFocusRing} from "@react-aria/focus";
|
||||
import {useHover} from "@react-aria/interactions";
|
||||
@ -18,7 +18,11 @@ export interface Props extends HTMLNextUIProps<"div"> {
|
||||
/**
|
||||
* Ref to the DOM node.
|
||||
*/
|
||||
ref: ReactRef<HTMLDivElement | null>;
|
||||
ref?: ReactRef<HTMLDivElement | null>;
|
||||
/**
|
||||
* Usually the Card parts, `CardHeader`, `CardBody` and `CardFooter`.
|
||||
*/
|
||||
children?: ReactNode | ReactNode[];
|
||||
/**
|
||||
* Whether the card should show a ripple animation on press, this prop is ignored if `disableAnimation` is true or `isPressable` is false.
|
||||
* @default false
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nextui-org/checkbox",
|
||||
"version": "0.0.0-dev-v2-20230729152229",
|
||||
"version": "0.0.0-dev-v2-20230730211830",
|
||||
"description": "Checkboxes allow users to select multiple items from a list of individual items, or to mark one individual item as selected.",
|
||||
"keywords": [
|
||||
"checkbox"
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nextui-org/chip",
|
||||
"version": "0.0.0-dev-v2-20230729152229",
|
||||
"version": "0.0.0-dev-v2-20230730211830",
|
||||
"description": "Chips help people enter information, make selections, filter content, or trigger actions.",
|
||||
"keywords": [
|
||||
"chip"
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nextui-org/code",
|
||||
"version": "0.0.0-dev-v2-20230729152229",
|
||||
"version": "0.0.0-dev-v2-20230730211830",
|
||||
"description": "Code is a component used to display inline code.",
|
||||
"keywords": [
|
||||
"code"
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nextui-org/divider",
|
||||
"version": "0.0.0-dev-v2-20230729152229",
|
||||
"version": "0.0.0-dev-v2-20230730211830",
|
||||
"description": ". A separator is a visual divider between two groups of content",
|
||||
"keywords": [
|
||||
"divider"
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nextui-org/dropdown",
|
||||
"version": "0.0.0-dev-v2-20230729152229",
|
||||
"version": "0.0.0-dev-v2-20230730211830",
|
||||
"description": "A dropdown displays a list of actions or options that a user can choose.",
|
||||
"keywords": [
|
||||
"dropdown"
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nextui-org/image",
|
||||
"version": "0.0.0-dev-v2-20230729152229",
|
||||
"version": "0.0.0-dev-v2-20230730211830",
|
||||
"description": "A simple image component",
|
||||
"keywords": [
|
||||
"image"
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nextui-org/input",
|
||||
"version": "0.0.0-dev-v2-20230729152229",
|
||||
"version": "0.0.0-dev-v2-20230730211830",
|
||||
"description": "The input component is designed for capturing user input within a text field.",
|
||||
"keywords": [
|
||||
"input"
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nextui-org/kbd",
|
||||
"version": "0.0.0-dev-v2-20230729152229",
|
||||
"version": "0.0.0-dev-v2-20230730211830",
|
||||
"description": "The keyboard key components indicates which key or set of keys used to execute a specificv action",
|
||||
"keywords": [
|
||||
"kbd"
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nextui-org/link",
|
||||
"version": "0.0.0-dev-v2-20230729152229",
|
||||
"version": "0.0.0-dev-v2-20230730211830",
|
||||
"description": "Links allow users to click their way from page to page. This component is styled to resemble a hyperlink and semantically renders an <a>",
|
||||
"keywords": [
|
||||
"link"
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nextui-org/modal",
|
||||
"version": "0.0.0-dev-v2-20230729152229",
|
||||
"version": "0.0.0-dev-v2-20230730211830",
|
||||
"description": "Displays a dialog with a custom content that requires attention or provides additional information.",
|
||||
"keywords": [
|
||||
"modal"
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nextui-org/navbar",
|
||||
"version": "0.0.0-dev-v2-20230729152229",
|
||||
"version": "0.0.0-dev-v2-20230730211830",
|
||||
"description": "A responsive navigation header positioned on top side of your page that includes support for branding, links, navigation, collapse and more.",
|
||||
"keywords": [
|
||||
"navbar"
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nextui-org/pagination",
|
||||
"version": "0.0.0-dev-v2-20230729152229",
|
||||
"version": "0.0.0-dev-v2-20230730211830",
|
||||
"description": "The Pagination component allows you to display active page and navigate between multiple pages.",
|
||||
"keywords": [
|
||||
"pagination"
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nextui-org/popover",
|
||||
"version": "0.0.0-dev-v2-20230729152229",
|
||||
"version": "0.0.0-dev-v2-20230730211830",
|
||||
"description": "A popover is an overlay element positioned relative to a trigger.",
|
||||
"keywords": [
|
||||
"popover"
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nextui-org/progress",
|
||||
"version": "0.0.0-dev-v2-20230729152229",
|
||||
"version": "0.0.0-dev-v2-20230730211830",
|
||||
"description": "Progress bars show either determinate or indeterminate progress of an operation over time.",
|
||||
"keywords": [
|
||||
"progress"
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nextui-org/radio",
|
||||
"version": "0.0.0-dev-v2-20230729152229",
|
||||
"version": "0.0.0-dev-v2-20230730211830",
|
||||
"description": "Radios allow users to select a single option from a list of mutually exclusive options.",
|
||||
"keywords": [
|
||||
"radio"
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nextui-org/ripple",
|
||||
"version": "0.0.0-dev-v2-20230729152229",
|
||||
"version": "0.0.0-dev-v2-20230730211830",
|
||||
"description": "A simple implementation to display a ripple animation when the source component is clicked",
|
||||
"keywords": [
|
||||
"ripple"
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nextui-org/skeleton",
|
||||
"version": "0.0.0-dev-v2-20230729152229",
|
||||
"version": "0.0.0-dev-v2-20230730211830",
|
||||
"description": "Skeleton is used to display the loading state of some component.",
|
||||
"keywords": [
|
||||
"skeleton"
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nextui-org/snippet",
|
||||
"version": "0.0.0-dev-v2-20230729152229",
|
||||
"version": "0.0.0-dev-v2-20230730211830",
|
||||
"description": "Display a snippet of copyable code for the command line.",
|
||||
"keywords": [
|
||||
"snippet"
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nextui-org/spacer",
|
||||
"version": "0.0.0-dev-v2-20230729152229",
|
||||
"version": "0.0.0-dev-v2-20230730211830",
|
||||
"description": "A flexible spacer component designed to create consistent spacing and maintain alignment in your layout.",
|
||||
"keywords": [
|
||||
"spacer"
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nextui-org/spinner",
|
||||
"version": "0.0.0-dev-v2-20230729152229",
|
||||
"version": "0.0.0-dev-v2-20230730211830",
|
||||
"description": "Loaders express an unspecified wait time or display the length of a process.",
|
||||
"keywords": [
|
||||
"loading",
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nextui-org/switch",
|
||||
"version": "0.0.0-dev-v2-20230729152229",
|
||||
"version": "0.0.0-dev-v2-20230730211830",
|
||||
"description": "A switch is similar to a checkbox, but represents on/off values as opposed to selection.",
|
||||
"keywords": [
|
||||
"switch"
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nextui-org/table",
|
||||
"version": "0.0.0-dev-v2-20230729152229",
|
||||
"version": "0.0.0-dev-v2-20230730211830",
|
||||
"description": "Tables are used to display tabular data using rows and columns. ",
|
||||
"keywords": [
|
||||
"table"
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nextui-org/tabs",
|
||||
"version": "0.0.0-dev-v2-20230729152229",
|
||||
"version": "0.0.0-dev-v2-20230730211830",
|
||||
"description": "Tabs organize content into multiple sections and allow users to navigate between them.",
|
||||
"keywords": [
|
||||
"tabs"
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nextui-org/tooltip",
|
||||
"version": "0.0.0-dev-v2-20230729152229",
|
||||
"version": "0.0.0-dev-v2-20230730211830",
|
||||
"description": "A React Component for rendering dynamically positioned Tooltips",
|
||||
"keywords": [
|
||||
"tooltip"
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nextui-org/user",
|
||||
"version": "0.0.0-dev-v2-20230729152229",
|
||||
"version": "0.0.0-dev-v2-20230730211830",
|
||||
"description": "Flexible User Profile Component.",
|
||||
"keywords": [
|
||||
"user"
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nextui-org/react",
|
||||
"version": "0.0.0-dev-v2-20230729152229",
|
||||
"version": "0.0.0-dev-v2-20230730211830",
|
||||
"description": "🚀 Beautiful and modern React UI library.",
|
||||
"author": "Junior Garcia <jrgarciadev@gmail.com>",
|
||||
"homepage": "https://nextui.org",
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nextui-org/system",
|
||||
"version": "0.0.0-dev-v2-20230729152229",
|
||||
"version": "0.0.0-dev-v2-20230730211830",
|
||||
"description": "NextUI system primitives",
|
||||
"keywords": [
|
||||
"system"
|
||||
|
||||
@ -4,19 +4,21 @@ import {tv} from "@nextui-org/theme";
|
||||
import {cn, mapPropsVariants} from "./utils";
|
||||
|
||||
function getSlots(variants) {
|
||||
return Object.values(variants)
|
||||
.flatMap(Object.values)
|
||||
.reduce((acc, slot) => {
|
||||
if (typeof slot === "object" && slot !== null && !(slot instanceof String)) {
|
||||
Object.keys(slot).forEach((key) => {
|
||||
if (!acc.hasOwnProperty(key)) {
|
||||
acc[key] = "";
|
||||
return variants
|
||||
? Object.values(variants)
|
||||
.flatMap(Object.values)
|
||||
.reduce((acc, slot) => {
|
||||
if (typeof slot === "object" && slot !== null && !(slot instanceof String)) {
|
||||
Object.keys(slot).forEach((key) => {
|
||||
if (!acc.hasOwnProperty(key)) {
|
||||
acc[key] = "";
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return acc;
|
||||
}, {});
|
||||
return acc;
|
||||
}, {})
|
||||
: {};
|
||||
}
|
||||
|
||||
export function extendVariants(BaseComponent, styles = {}, opts = {}) {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nextui-org/theme",
|
||||
"version": "0.0.0-dev-v2-20230729152229",
|
||||
"version": "0.0.0-dev-v2-20230730211830",
|
||||
"description": "The default theme for NextUI components",
|
||||
"keywords": [
|
||||
"theme",
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nextui-org/use-aria-accordion-item",
|
||||
"version": "0.0.0-dev-v2-20230729152229",
|
||||
"version": "0.0.0-dev-v2-20230730211830",
|
||||
"description": "Internal impl for react aria accordion item",
|
||||
"keywords": [
|
||||
"use-aria-accordion-item"
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nextui-org/use-aria-button",
|
||||
"version": "0.0.0-dev-v2-20230729152229",
|
||||
"version": "0.0.0-dev-v2-20230730211830",
|
||||
"description": "Internal hook to handle button a11y and events, this is based on react-aria button hook but without the onClick warning",
|
||||
"keywords": [
|
||||
"use-aria-button"
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nextui-org/use-aria-modal-overlay",
|
||||
"version": "0.0.0-dev-v2-20230729152229",
|
||||
"version": "0.0.0-dev-v2-20230730211830",
|
||||
"description": "A custom implementation of react aria modal overlay, this removes the prevent scroll",
|
||||
"keywords": [
|
||||
"use-aria-modal-overlay"
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nextui-org/use-aria-toggle-button",
|
||||
"version": "0.0.0-dev-v2-20230729152229",
|
||||
"version": "0.0.0-dev-v2-20230730211830",
|
||||
"description": "Internal hook to handle button a11y and events, this is based on react-aria button hook but without the onClick warning",
|
||||
"keywords": [
|
||||
"use-aria-toggle-button"
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nextui-org/use-callback-ref",
|
||||
"version": "0.0.0-dev-v2-20230729152229",
|
||||
"version": "0.0.0-dev-v2-20230730211830",
|
||||
"description": "React hook to persist any value between renders, but keeps it up-to-date if it changes.",
|
||||
"keywords": [
|
||||
"use-callback-ref"
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nextui-org/use-clipboard",
|
||||
"version": "0.0.0-dev-v2-20230729152229",
|
||||
"version": "0.0.0-dev-v2-20230730211830",
|
||||
"description": "Wrapper around navigator.clipboard with feedback timeout",
|
||||
"keywords": [
|
||||
"use-clipboard"
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nextui-org/use-disclosure",
|
||||
"version": "0.0.0-dev-v2-20230729152229",
|
||||
"version": "0.0.0-dev-v2-20230730211830",
|
||||
"description": "The hook in charge of managing modals",
|
||||
"keywords": [
|
||||
"use-disclosure"
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nextui-org/use-image",
|
||||
"version": "0.0.0-dev-v2-20230729152229",
|
||||
"version": "0.0.0-dev-v2-20230730211830",
|
||||
"description": "React hook for progressing image loading",
|
||||
"keywords": [
|
||||
"use-image"
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nextui-org/use-infinite-scroll",
|
||||
"version": "0.0.0-dev-v2-20230729152229",
|
||||
"version": "0.0.0-dev-v2-20230730211830",
|
||||
"description": "A hook for handling infinity scroll based on the IntersectionObserver API",
|
||||
"keywords": [
|
||||
"use-infinite-scroll"
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nextui-org/use-is-mobile",
|
||||
"version": "0.0.0-dev-v2-20230729152229",
|
||||
"version": "0.0.0-dev-v2-20230730211830",
|
||||
"description": "A hook that returns whether the device is mobile or not",
|
||||
"keywords": [
|
||||
"use-is-mobile"
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nextui-org/use-is-mounted",
|
||||
"version": "0.0.0-dev-v2-20230729152229",
|
||||
"version": "0.0.0-dev-v2-20230730211830",
|
||||
"description": "This hook can be used to render client-based components or run client logic",
|
||||
"keywords": [
|
||||
"use-is-mounted"
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nextui-org/use-pagination",
|
||||
"version": "0.0.0-dev-v2-20230729152229",
|
||||
"version": "0.0.0-dev-v2-20230730211830",
|
||||
"description": "State management hook for Pagination component, it lets you manage pagination with controlled and uncontrolled state",
|
||||
"keywords": [
|
||||
"use-pagination"
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nextui-org/use-real-shape",
|
||||
"version": "0.0.0-dev-v2-20230729152229",
|
||||
"version": "0.0.0-dev-v2-20230730211830",
|
||||
"description": "Hook that returns the real dimensions of an element",
|
||||
"keywords": [
|
||||
"use-real-shape"
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nextui-org/use-ref-state",
|
||||
"version": "0.0.0-dev-v2-20230729152229",
|
||||
"version": "0.0.0-dev-v2-20230730211830",
|
||||
"description": "Hook for saving the state in a ref value",
|
||||
"keywords": [
|
||||
"use-ref-state"
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nextui-org/use-resize",
|
||||
"version": "0.0.0-dev-v2-20230729152229",
|
||||
"version": "0.0.0-dev-v2-20230730211830",
|
||||
"description": "Hook that adds an event listener to the resize window event",
|
||||
"keywords": [
|
||||
"use-resize"
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nextui-org/use-safe-layout-effect",
|
||||
"version": "0.0.0-dev-v2-20230729152229",
|
||||
"version": "0.0.0-dev-v2-20230730211830",
|
||||
"description": "",
|
||||
"keywords": [
|
||||
"use-safe-layout-effect"
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nextui-org/use-scroll-position",
|
||||
"version": "0.0.0-dev-v2-20230729152229",
|
||||
"version": "0.0.0-dev-v2-20230730211830",
|
||||
"description": "Provides the logic to control the scroll over an element",
|
||||
"keywords": [
|
||||
"use-scroll-position"
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nextui-org/use-ssr",
|
||||
"version": "0.0.0-dev-v2-20230729152229",
|
||||
"version": "0.0.0-dev-v2-20230730211830",
|
||||
"description": "",
|
||||
"keywords": [
|
||||
"use-ssr"
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nextui-org/use-update-effect",
|
||||
"version": "0.0.0-dev-v2-20230729152229",
|
||||
"version": "0.0.0-dev-v2-20230730211830",
|
||||
"description": "React effect hook that invokes only on update",
|
||||
"keywords": [
|
||||
"use-update-effect"
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nextui-org/aria-utils",
|
||||
"version": "0.0.0-dev-v2-20230729152229",
|
||||
"version": "0.0.0-dev-v2-20230730211830",
|
||||
"description": "A package for managing @react-aria nextui utils.",
|
||||
"keywords": [
|
||||
"aria-utils"
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nextui-org/framer-transitions",
|
||||
"version": "0.0.0-dev-v2-20230729152229",
|
||||
"version": "0.0.0-dev-v2-20230730211830",
|
||||
"description": "A set of framer motion transitions for react",
|
||||
"keywords": [
|
||||
"framer-transitions"
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nextui-org/react-utils",
|
||||
"version": "0.0.0-dev-v2-20230729152229",
|
||||
"version": "0.0.0-dev-v2-20230730211830",
|
||||
"description": "A set of utilities for react on client side",
|
||||
"keywords": [
|
||||
"react-utils"
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nextui-org/shared-icons",
|
||||
"version": "0.0.0-dev-v2-20230729152229",
|
||||
"version": "0.0.0-dev-v2-20230730211830",
|
||||
"description": "Internal icons set, commonly used in the components stories",
|
||||
"keywords": [
|
||||
"icons-utils"
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nextui-org/shared-utils",
|
||||
"version": "0.0.0-dev-v2-20230729152229",
|
||||
"version": "0.0.0-dev-v2-20230730211830",
|
||||
"description": "A set of NextUI utilities",
|
||||
"keywords": [
|
||||
"system"
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nextui-org/test-utils",
|
||||
"version": "0.0.0-dev-v2-20230729152229",
|
||||
"version": "0.0.0-dev-v2-20230730211830",
|
||||
"description": "A set of utilities for react testing",
|
||||
"keywords": [
|
||||
"test-utils"
|
||||
|
||||
11
pnpm-lock.yaml
generated
11
pnpm-lock.yaml
generated
@ -408,6 +408,9 @@ importers:
|
||||
react-multi-ref:
|
||||
specifier: ^1.0.1
|
||||
version: 1.0.1
|
||||
react-wrap-balancer:
|
||||
specifier: ^1.0.0
|
||||
version: 1.0.0(react@18.2.0)
|
||||
refractor:
|
||||
specifier: 3.3.1
|
||||
version: 3.3.1
|
||||
@ -22978,6 +22981,14 @@ packages:
|
||||
- '@types/react'
|
||||
dev: false
|
||||
|
||||
/react-wrap-balancer@1.0.0(react@18.2.0):
|
||||
resolution: {integrity: sha512-yjDH+I8WGyDfh95gKhX/6ckfSBAltwQkxiYxtLPlyIRQNUVSjvz1uHR6Hpy+zHyOkJQw6GEC5RPglA41QXvzyw==}
|
||||
peerDependencies:
|
||||
react: '>=16.8.0 || ^17.0.0 || ^18'
|
||||
dependencies:
|
||||
react: 18.2.0
|
||||
dev: false
|
||||
|
||||
/react@18.2.0:
|
||||
resolution: {integrity: sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user