diff --git a/apps/docs/app/blog/[slug]/page.tsx b/apps/docs/app/blog/[slug]/page.tsx index 786a9f5867..f62a849e0d 100644 --- a/apps/docs/app/blog/[slug]/page.tsx +++ b/apps/docs/app/blog/[slug]/page.tsx @@ -7,6 +7,7 @@ import {format, parseISO} from "date-fns"; import NextLink from "next/link"; import {Balancer} from "react-wrap-balancer"; +import {__DEV__, __PREVIEW__} from "@/utils"; import {MDXContent} from "@/components/mdx-content"; import {siteConfig} from "@/config/site"; import {Route} from "@/libs/docs/page"; @@ -18,6 +19,8 @@ interface BlogPostProps { }; } +const isDraftVisible = __DEV__ || __PREVIEW__; + async function getBlogPostFromParams({params}: BlogPostProps) { const slug = params.slug || ""; const post = allBlogPosts.find((post) => post.slugAsParams === slug); @@ -78,7 +81,7 @@ export async function generateStaticParams(): Promise export default async function DocPage({params}: BlogPostProps) { const {post} = await getBlogPostFromParams({params}); - if (!post) { + if (!post || (post.draft && !isDraftVisible)) { notFound(); } @@ -96,6 +99,7 @@ export default async function DocPage({params}: BlogPostProps) { Back to blog + @@ -119,6 +123,7 @@ export default async function DocPage({params}: BlogPostProps) {

{post.title} + {post?.draft && " (Draft)"}

diff --git a/apps/docs/app/blog/page.tsx b/apps/docs/app/blog/page.tsx index 309386e9bb..4662e294a1 100644 --- a/apps/docs/app/blog/page.tsx +++ b/apps/docs/app/blog/page.tsx @@ -2,9 +2,20 @@ import {allBlogPosts} from "contentlayer/generated"; import {compareDesc} from "date-fns"; import {BlogPostList} from "@/components/blog-post"; +import {__DEV__, __PREVIEW__} from "@/utils"; + +const isDraftVisible = __DEV__ || __PREVIEW__; export default function Blog() { - const posts = allBlogPosts.sort((a, b) => compareDesc(new Date(a.date), new Date(b.date))); + const posts = allBlogPosts + .sort((a, b) => compareDesc(new Date(a.date), new Date(b.date))) + ?.filter((post) => { + if (post.draft && !isDraftVisible) { + return false; + } + + return true; + }); return (
diff --git a/apps/docs/components/blog-post.tsx b/apps/docs/components/blog-post.tsx index 5c78301351..b73b67fe75 100644 --- a/apps/docs/components/blog-post.tsx +++ b/apps/docs/components/blog-post.tsx @@ -57,7 +57,7 @@ const BlogPostCard = (post: BlogPost) => { diff --git a/apps/docs/components/marketing/hero/hero.tsx b/apps/docs/components/marketing/hero/hero.tsx index 1cdba969bf..6b7a144665 100644 --- a/apps/docs/components/marketing/hero/hero.tsx +++ b/apps/docs/components/marketing/hero/hero.tsx @@ -1,7 +1,7 @@ "use client"; import NextLink from "next/link"; -import {Button, Link} from "@nextui-org/react"; +import {Button, Link, Chip} from "@nextui-org/react"; import {ArrowRightIcon} from "@nextui-org/shared-icons"; import dynamic from "next/dynamic"; @@ -16,32 +16,32 @@ const BgLooper = dynamic(() => import("./bg-looper").then((mod) => mod.BgLooper) }); export const Hero = () => { - // const handlePressAnnouncement = (name: string, url: string) => { - // trackEvent("NavbarItem", { - // name, - // action: "press", - // category: "home - gero", - // data: url, - // }); - // }; + const handlePressAnnouncement = (name: string, url: string) => { + trackEvent("NavbarItem", { + name, + action: "press", + category: "home - gero", + data: url, + }); + }; return (
- {/* handlePressAnnouncement("Introducing v2.2.0", "/blog/v2.2.0")} + onClick={() => handlePressAnnouncement("Introducing v2.3.0", "/blog/v2.3.0")} > - Introducing v2.2.0  - - 🚀 + Introducing v2.3.0  + + 🎉 - */} +
diff --git a/apps/docs/components/mdx-components.tsx b/apps/docs/components/mdx-components.tsx index 565200bd1a..1071270d37 100644 --- a/apps/docs/components/mdx-components.tsx +++ b/apps/docs/components/mdx-components.tsx @@ -105,7 +105,7 @@ const List: React.FC<{children?: React.ReactNode}> = ({children}) => { const InlineCode = ({children}: {children?: React.ReactNode}) => { return ( - + {children} ); diff --git a/apps/docs/components/navbar.tsx b/apps/docs/components/navbar.tsx index d91b1431f3..19d70e3a40 100644 --- a/apps/docs/components/navbar.tsx +++ b/apps/docs/components/navbar.tsx @@ -16,6 +16,7 @@ import { DropdownMenu, DropdownItem, DropdownTrigger, + Chip, } from "@nextui-org/react"; import {dataFocusVisibleClasses} from "@nextui-org/theme"; import {ChevronDownIcon, LinkIcon} from "@nextui-org/shared-icons"; @@ -33,13 +34,7 @@ import {currentVersion} from "@/utils/version"; import {siteConfig} from "@/config/site"; import {Route} from "@/libs/docs/page"; import {LargeLogo, SmallLogo, ThemeSwitch} from "@/components"; -import { - TwitterIcon, - GithubIcon, - DiscordIcon, - HeartFilledIcon, - SearchLinearIcon, -} from "@/components/icons"; +import {TwitterIcon, GithubIcon, DiscordIcon, SearchLinearIcon} from "@/components/icons"; import {useIsMounted} from "@/hooks/use-is-mounted"; import {DocsSidebar} from "@/components/docs/sidebar"; import {useCmdkStore} from "@/components/cmdk"; @@ -312,6 +307,21 @@ export const Navbar: FC = ({children, routes, mobileRoutes = [], sl + + handlePressNavbarItem("Introducing v2.3.0", "/blog/v2.3.0")} + > + Introducing v2.3.0  + + 🎉 + + + = ({children, routes, mobileRoutes = [], sl {searchButton} - + {/* - + */} + +We are excited to announce the latest update to NextUI, version **2.3.0**! This release introduces 6 new components, +our new CLI, and several enhancements and bug fixes. + +## What's New in v2.3.0? + +- [NextUI CLI](/docs/guide/cli) - A command-line interface for creating and managing NextUI projects. +- [DateInput](/docs/components/date-input) - Allows users to enter and edit date and time values using a keyboard. +- [TimeInput](/docs/components/time-input) - Allows users to enter and edit time values using a keyboard. +- [Calendar](/docs/components/calendar) - Displays a calendar for selecting dates and times. +- [RangeCalendar](/docs/components/range-calendar) - Displays a calendar for selecting date ranges. +- [DatePicker](/docs/components/date-picker) - Allows users to select a date from a calendar. +- [DateRangePicker](/docs/components/date-range-picker) - Allows users to select a date range from a calendar. +- [Other Changes](#other-changes) - Includes styling improvements, accessibility and usability enhancements. + + + +Requirements: + +- [Tailwind CSS 3.4](https://tailwindcss.com/) or later + +Upgrade today by running one of the following commands: + + + + + + + +## NextUI CLI + +We are thrilled to introduce the [NextUI CLI](https://github.com/nextui-org/nextui-cli), a command-line interface, It offers a comprehensive suite +of commands to initialize, manage, and improve your NextUI projects. It enables you to `add`, `remove`, or +`upgrade` individual components, assess the health of your project, and more. + +### Installation + +To install the CLI globally, execute one of the following commands in your terminal: + + + +Alternatively, you can use the CLI without a global installation by employing `npx`: + +```bash +npx nextui-cli@latest +``` + +### Usage + +Once the CLI is installed, run the following command to display available commands: + +```bash +nextui +``` + +NextUI CLI can help you create new projects, add components, upgrade components, remove components, detect issues in +you setup, know your environment, and more. + + + +To initialize a new project, you can simply run: + +```bash +nextui init my-nextui-app +``` + + + +You will be prompted to configure your project: + +```codeBlock bash +? Select a template › - Use arrow-keys. Return to submit. +❯ App + A Next.js 13 with app directory template pre-configured with NextUI (v2) and Tailwind CSS. + Pages + A Next.js 13 with pages directory template pre-configured with NextUI (v2) and Tailwind CSS. +``` + +Select the template you want to use and the CLI will create a new project for you. + +> We're working on adding more templates to the CLI, so stay tuned for updates! + + + +If you already have a NextUI project, you can add components to it using the `add` command: + +```bash +nextui add date-input +``` + +It will automatically detect the required dependencies, modify your `tailwind.config.(js|ts)` file, +detect whether using `pnpm` if so, add the required configuration to your `.npmrc` file and add the component to your project. + +If instead of installing a single component you want to install multiple components, you can do so by separating them with a space: + +```bash +nextui add date-input time-input calendar +``` + +You can alternatively install the `main` package which includes all the components by passing the `--all` flag: + +```bash +nextui add --all +``` + + + +> The CLI is currentl in `Alpha` stage, we're working on adding more features and improvements. If you find any issues or have any suggestions, please let us know by [opening an issue](https://github.com/nextui-org/nextui-cli/issues/new). + +To learn more about the CLI and its commands, please refer to the [CLI documentation](/docs/guide/cli) and the [CLI API reference](/docs/api-references/cli-api). + +## New Components + +Since the beginning of NextUI, devs have been asking for date and time input components. After +months of iteration and development, we are excited to introduce the following new components: + +### DateInput + +DateInput is a component that allows users to enter and edit date and time values using a keyboard. +Each part of a date value is displayed in an individually editable segment. + + + +Go to the [DateInput documentation](/docs/components/date-input) to learn more about the component. + +### TimeInput + +The `TimeInput` component consists of a label, and a group of segments representing each unit of a time (e.g. hours, minutes, and seconds). Each segment is individually focusable and editable by the user, by typing or using the arrow keys to increment and decrement the value. This approach allows values to be formatted and parsed correctly regardless of the locale or time format, and offers an easy and error-free way to edit times using the keyboard. + + + +Go to the [TimeInput documentation](/docs/components/time-input) to learn more about the component. + +### Calendar + +A Calendar consists of a grouping element containing one or more date grids (e.g. months), and a previous and next button for navigating between date ranges. Each calendar grid consists of cells containing button elements that can be pressed and navigated to using the arrow keys to select a date. + + + +The calendar also supports selecting years and months for rapid selection. + + + +Go to the [Calendar documentation](/docs/components/calendar) to learn more about the component. + +### RangeCalendar + +A Range calendar consists of a grouping element containing one or more date grids (e.g. months), and a previous and next button for navigating through time. Each calendar grid consists of cells containing button elements that can be pressed and navigated to using the arrow keys to select a date range. Once a start date is selected, the user can navigate to another date using the keyboard or by hovering over it, and clicking it or pressing the Enter key commits the selected date range. + + + +Go to the [RangeCalendar documentation](/docs/components/range-calendar) to learn more about the component. + +### DatePicker + +A Date Picker combines a DateInput and a Calendar popover to allow users to enter or select a date and time value. + + + +Go to the [DatePicker documentation](/docs/components/date-picker) to learn more about the component. + +### DateRangePicker + +Date Range Picker combines two DateInputs and a RangeCalendar popover to allow users to enter or select a date and time range. + + + +Go to the [DateRangePicker documentation](/docs/components/date-range-picker) to learn more about the component. + +### Internationalization + +These new components have built-in internationalization, time zones and granularity support, they supports selecting dates +in many calendar systems used around the world, including `Gregorian`, `Hebrew`, `Indian`, `Islamic`, `Buddhist`, and more. + +Dates are automatically displayed in the appropriate calendar system for the user's locale this is possible thanks to [@internationalized/date](https://react-spectrum.adobe.com/internationalized/date/) package, which +includes functions for parsing strings in multiple formats into `ZonedDateTime` objects. + +Here's and example using the `Indian` calendar system: + + + +Alternatively you can set the `locale` globally by using the `NextUIProvider` component: + +```jsx +// Next.js App Router example +"use client"; + +import {NextUIProvider} from "@nextui-org/react"; + +export interface ProvidersProps { + children: React.ReactNode; +} + +export function Providers({children}: ProvidersProps) { + const router = useRouter(); + + return {children}; +} +``` + +If no `locale` is provided, it will extract the locale from the browser. + +### NextUI Provider + +The `NextUIProvider` component was updated to include the `createCalendar` function, which allows you to create a calendar instance with the specified locale and time zone, +and the `defaultDates` object which allows you to set global minimum and maximum dates for the components. + +```jsx +// Next.js App Router example +"use client"; + +import {NextUIProvider, SupportedCalendars} from "@nextui-org/react"; +import {CalendarDate, GregorianCalendar} from "@internationalized/date"; + +export interface ProvidersProps { + children: React.ReactNode; +} + +function createCalendar(identifier: SupportedCalendars) { + switch (identifier) { + case "gregory": + return new GregorianCalendar(); + default: + throw new Error(`Unsupported calendar ${identifier}`); + } +} + +export function Providers({children}: ProvidersProps) { + const router = useRouter(); + + return ( + + {children} + + ); +} +``` + +## Other Changes + +- Bug Fixes: + +- Styling Improvements: + +- Accessibility and Usability Enhancements: + +- Right-to-Left (RTL) Support: + + - Implemented RTL support across various components including Accordion, Avatar & AvatarGroup, and ButtonGroup, enhancing usability for RTL languages. + +- Performance Improvements: + + - We removed the custom `units` creation from the `nextui` plugin, it is no longer needed with TailwindCSS v3.4 and above. + +- Visual and Interactive Tweaks: + + + +## Breaking Changes + + + +We hope you enjoy these new components and the new features. We're excited to see what you build with them! + +Thanks for reading and happy coding! 🚀 + +--- + +## Community + +We're excited to see the community adopt NextUI, raise issues, and provide feedback. +Whether it's a feature request, bug report, or a project to showcase, please get involved! + + + +## Contributing + +PR's on NextUI are always welcome, please see our [contribution guidelines](https://github.com/nextui-org/nextui/blob/main/CONTRIBUTING.md) to learn how you can contribute to this project. diff --git a/apps/docs/content/components/date-input/usage.ts b/apps/docs/content/components/date-input/usage.ts index 59a9c16570..eed0992112 100644 --- a/apps/docs/content/components/date-input/usage.ts +++ b/apps/docs/content/components/date-input/usage.ts @@ -4,7 +4,7 @@ import {CalendarDate} from "@internationalized/date"; export default function App() { return (
- +
); }`; diff --git a/apps/docs/content/components/date-picker/international-calendar.ts b/apps/docs/content/components/date-picker/international-calendar.ts index 598f15dff1..ba86ec20fd 100644 --- a/apps/docs/content/components/date-picker/international-calendar.ts +++ b/apps/docs/content/components/date-picker/international-calendar.ts @@ -9,6 +9,8 @@ export default function App() {
- ## Import @@ -321,9 +319,9 @@ import {parseZonedDateTime} from "@internationalized/date"; ### DateInput Events -| Attribute | Type | Description | +| Attribute | Type | Description | | | ------------- | ---------------------------------------------------------------------- | --------------------------------------------------------------- | --- | -| onChange | `((value: ZonedDateTime \| CalendarDate \| CalendarDateTime) => void)` | Handler that is called when the date-input's value changes. | +| onChange | `((value: ZonedDateTime \| CalendarDate \| CalendarDateTime) => void)` | Handler that is called when the date-input's value changes. | - | | onFocus | `(e: FocusEvent) => void` | Handler that is called when the element receives focus. | - | | onBlur | `(e: FocusEvent) => void` | Handler that is called when the element loses focus. | - | | onFocusChange | `(isFocused: boolean) => void` | Handler that is called when the element's focus status changes. | - | diff --git a/apps/docs/contentlayer.config.js b/apps/docs/contentlayer.config.js index 8a63670bb2..59331a3d6a 100644 --- a/apps/docs/contentlayer.config.js +++ b/apps/docs/contentlayer.config.js @@ -49,6 +49,7 @@ export const BlogPost = defineDocumentType(() => ({ title: {type: "string", required: true}, description: {type: "string", required: true}, date: {type: "date", required: true}, + draft: {type: "boolean", required: false}, tags: { type: 'list', of: { type: 'string' } }, author: {type: "nested",of: AuthorProperties, required: false}, image: {type: "string", required: false}, diff --git a/apps/docs/public/blog/v2.3.0.jpg b/apps/docs/public/blog/v2.3.0.jpg new file mode 100644 index 0000000000..de7ac42259 Binary files /dev/null and b/apps/docs/public/blog/v2.3.0.jpg differ diff --git a/apps/docs/public/blog/v2.3.0_2x.jpg b/apps/docs/public/blog/v2.3.0_2x.jpg new file mode 100644 index 0000000000..96f9d306e5 Binary files /dev/null and b/apps/docs/public/blog/v2.3.0_2x.jpg differ diff --git a/apps/docs/tailwind.config.js b/apps/docs/tailwind.config.js index 452cd774ff..874b311acc 100644 --- a/apps/docs/tailwind.config.js +++ b/apps/docs/tailwind.config.js @@ -210,6 +210,12 @@ module.exports = { fontWeight: theme("fontWeight.normal"), fontStyle: "font-normal", }, + "code::before": { + content: "", + }, + "code::after": { + content: "", + }, "blockquote p:first-of-type::before": { content: "", }, diff --git a/packages/components/date-input/src/use-date-input.ts b/packages/components/date-input/src/use-date-input.ts index 737bc4d92f..f250153eb7 100644 --- a/packages/components/date-input/src/use-date-input.ts +++ b/packages/components/date-input/src/use-date-input.ts @@ -109,7 +109,7 @@ interface Props extends NextUIBaseProps { export type UseDateInputProps = Props & DateInputVariantProps & - Omit, "validationBehavior">; + AriaDateFieldProps; export function useDateInput(originalProps: UseDateInputProps) { const [props, variantProps] = mapPropsVariants(originalProps, dateInput.variantKeys); @@ -132,7 +132,7 @@ export function useDateInput(originalProps: UseDateInputPro fieldProps: fieldPropsProp, errorMessageProps: errorMessagePropsProp, descriptionProps: descriptionPropsProp, - // validationBehavior = "native", TODO: Uncomment this one we support `native` and `aria` validations + validationBehavior, shouldForceLeadingZeros = true, minValue = providerContext?.defaultDates?.minDate ?? new CalendarDate(1900, 1, 1), maxValue = providerContext?.defaultDates?.maxDate ?? new CalendarDate(2099, 12, 31), @@ -152,7 +152,7 @@ export function useDateInput(originalProps: UseDateInputPro locale, minValue, maxValue, - validationBehavior: "native", + validationBehavior, isInvalid: isInvalidProp, shouldForceLeadingZeros, createCalendar: @@ -170,11 +170,7 @@ export function useDateInput(originalProps: UseDateInputPro descriptionProps, errorMessageProps, isInvalid: ariaIsInvalid, - } = useAriaDateField( - {...originalProps, label, validationBehavior: "native", inputRef}, - state, - domRef, - ); + } = useAriaDateField({...originalProps, label, validationBehavior, inputRef}, state, domRef); const baseStyles = clsx(classNames?.base, className); diff --git a/packages/components/date-picker/src/use-date-picker-base.ts b/packages/components/date-picker/src/use-date-picker-base.ts index c5598626b4..248ca2397b 100644 --- a/packages/components/date-picker/src/use-date-picker-base.ts +++ b/packages/components/date-picker/src/use-date-picker-base.ts @@ -213,7 +213,6 @@ export function useDatePickerBase(originalProps: UseDatePic description, startContent, validationState, - validationBehavior: "native", shouldForceLeadingZeros, isInvalid, errorMessage,