Skip to content

Commit

Permalink
Merge branch 'canary' into pr/3698
Browse files Browse the repository at this point in the history
  • Loading branch information
wingkwong committed Sep 12, 2024
2 parents c513e72 + 142f394 commit 3a3cd11
Show file tree
Hide file tree
Showing 20 changed files with 266 additions and 81 deletions.
5 changes: 5 additions & 0 deletions .changeset/curvy-eels-tap.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@nextui-org/system": patch
---

Fix missing `useHref` logic (#2934)
5 changes: 5 additions & 0 deletions .changeset/eleven-eels-fix.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@nextui-org/theme": patch
---

fix(theme): use data-hover instead of hover (#2095)
5 changes: 5 additions & 0 deletions .changeset/few-roses-sniff.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@nextui-org/select": patch
---

added missing onChange when there are more than 300 items (#3455)
5 changes: 5 additions & 0 deletions .changeset/nervous-mirrors-rule.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@nextui-org/theme": patch
---

set the min-height of base height to 100dvh where size equals `full` (#2681)
5 changes: 5 additions & 0 deletions .changeset/proud-peas-flash.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@nextui-org/theme": patch
---

Improved RTL support for the table component
5 changes: 5 additions & 0 deletions .changeset/tall-balloons-sleep.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@nextui-org/react-rsc-utils": patch
---

added react to peerDependencies to remove react copy from react-rsc-utils bundle (#3531)
5 changes: 5 additions & 0 deletions .changeset/tough-mangos-deliver.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@nextui-org/theme": patch
---

Updates the text colors for the flat variant in the theme so that elements using this variant are accessible (#3738)
4 changes: 2 additions & 2 deletions apps/docs/components/navbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -209,8 +209,8 @@ export const Navbar: FC<NavbarProps> = ({children, routes, mobileRoutes = [], sl
className={navLinkClasses}
color="foreground"
data-active={includes(pathname, "components")}
href="/docs/components/avatar"
onClick={() => handlePressNavbarItem("Components", "/docs/components/avatar")}
href="/docs/components/accordion"
onClick={() => handlePressNavbarItem("Components", "/docs/components/accordion")}
>
Components
</NextLink>
Expand Down
2 changes: 1 addition & 1 deletion apps/docs/content/components/pagination/custom-items.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ export default function App() {
onPrevious,
setPage,
className,
}: PaginationItemRenderProps<HTMLButtonElement>) => {
}: PaginationItemRenderProps) => {
if (value === PaginationItemType.NEXT) {
return (
<button key={key} className={cn(className, "bg-default-200/50 min-w-8 w-8 h-8")} onClick={onNext}>
Expand Down
20 changes: 16 additions & 4 deletions apps/docs/content/docs/guide/installation.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,21 @@ Requirements:

Using the CLI is now the easiest way to start a NextUI project. You can initialize your project and add components directly via the CLI:

```codeBlock bash
npm install -g nextui-cli
```
<Steps>

<Spacer y={4}/>
### Installation
Execute one of the following commands in your terminal:
<PackageManagers
commands={{
npm: "npm install -g nextui-cli",
yarn: "yarn add -g nextui-cli",
pnpm: "pnpm add -g nextui-cli",
bun: "bun add -g nextui-cli",
}}
/>

### Initialization and Starting the App
Initialize the project by using the `init` command.
```codeBlock bash
nextui init my-nextui-app
```
Expand All @@ -48,6 +57,7 @@ Start the local server:
npm run dev
```

### Adding the Components
Once your NextUI project is ready to develop, you can add individual components using the CLI. For example, to add a button component:

```codeBlock bash
Expand Down Expand Up @@ -92,6 +102,8 @@ Filtered results for: Enter something to filter
◯ code
```

</Steps>

## Manual Installation

If you prefer not to use the CLI, you may try either global installation or individual installation to set up NextUI in your project:
Expand Down
93 changes: 74 additions & 19 deletions apps/docs/content/docs/guide/routing.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ component configures all NextUI components within it to navigate using the clien
Set this up once in the root of your app, and any NextUI component with the href prop will automatically navigate
using your router.

### NextUIProvider Setup
## NextUIProvider Setup

The `NextUIProvider` accepts a prop called `navigate`. This should be set to a function received from your
router for performing a client side navigation programmatically. The following example shows the general
Expand All @@ -43,9 +43,9 @@ function App() {

<Spacer y={2} />

### Next.js
## Next.js

#### App Router
### App Router

Go to your `app/providers.tsx` or `app/providers.jsx` (create it if it doesn't exist) and add the
`useRouter` hook from `next/navigation`, it returns a router object that can be used to perform navigation.
Expand Down Expand Up @@ -95,15 +95,49 @@ export default function RootLayout({children}: { children: React.ReactNode }) {

> **Note**: Skip this step if you already set up the `NextUIProvider` in your app.
#### Add useHref (Optional)

If you are using the Next.js [basePath](https://nextjs.org/docs/app/api-reference/next-config-js/basePath) setting, you'll need to configure an environment variable to access it.

```js
// next.config.js
const basePath = '...';
const nextConfig = {
basePath,
env: {
BASE_PATH: basePath
}
};
```
Then, provide a custom `useHref` function to prepend it to the href for all links.

```tsx {9,12}
// app/providers.tsx
'use client'

import {NextUIProvider} from '@nextui-org/react';
import {useRouter} from 'next/navigation'

export function Providers({children}: { children: React.ReactNode }) {
const router = useRouter();
const useHref = (href: string) => process.env.BASE_PATH + href;

return (
<NextUIProvider navigate={router.push} useHref={useHref}>
{children}
</NextUIProvider>
)
}
```

</Steps>

#### Pages Router
### Pages Router

Go to pages`/_app.js` or `pages/_app.tsx` (create it if it doesn't exist) and add the`useRouter` hook
from `next/router`, it returns a router object that can be used to perform navigation.


```tsx {7}
```tsx {7,10}
// pages/_app.tsx
import type { AppProps } from 'next/app';
import {NextUIProvider} from '@nextui-org/react';
Expand All @@ -122,23 +156,47 @@ function MyApp({ Component, pageProps }: AppProps) {
export default MyApp;
```

### React Router
When using the [basePath](https://nextjs.org/docs/app/api-reference/next-config-js/basePath) configuration option, provide a `useHref` option to the router passed to Provider to prepend it to links automatically.

```tsx {8,11}
// pages/_app.tsx
import type { AppProps } from 'next/app';
import {NextUIProvider} from '@nextui-org/react';
import {useRouter} from 'next/router';

function MyApp({ Component, pageProps }: AppProps) {
const router = useRouter();
const useHref = (href: string) => router.basePath + href;

return (
<NextUIProvider navigate={router.push} useHref={useHref}>
<Component {...pageProps} />
</NextUIProvider>
)
}

export default MyApp;
```

## React Router

The `useNavigate` hook from `react-router-dom` returns a `navigate` function that can be used to perform navigation.
The `useNavigate` hook from `react-router-dom` returns a `navigate` function that can be used to perform navigation.

The `useHref` hook can also be provided if you're using React Router's `basename` option. Ensure that the component that calls useNavigate and renders Provider is inside the router component (e.g. `BrowserRouter`) so that it has access to React Router's internal context. The React Router `<Routes>` element should also be defined inside `<NextUIProvider>` so that links inside the rendered routes have access to the router.

Go to the `App` file commonly called `App.jsx` or `App.tsx`, add the `useNavigate` hook and pass the
`navigate` function to the `NextUIProvider`:

```jsx {6,9}
// App.tsx or App.jsx
import {BrowserRouter, useNavigate} from 'react-router-dom';
import {BrowserRouter, useNavigate, useHref} from 'react-router-dom';
import {NextUIProvider} from '@nextui-org/react';

function App() {
const navigate = useNavigate();

return (
<NextUIProvider navigate={navigate}>
<NextUIProvider navigate={navigate} useHref={useHref}>
{/* Your app here... */}
<Routes>
<Route path="/" element={<HomePage />} />
Expand All @@ -164,17 +222,16 @@ component (e.g. `BrowserRouter`) so that it has access to React Router's interna
element should also be defined inside `NextUIProvider` so that links inside the rendered routes have access
to the router.

## Remix

### Remix

Remix uses React Router under the hood, so the same `useNavigate` hook described above also works in Remix
Remix uses React Router under the hood, so the same `useNavigate` and `useHref` hook described above also works in Remix
apps. `NextUIProvider` should be rendered at the `root` of each page that includes NextUI components, or in
`app/root.tsx` to add it to all pages. See the [Remix docs](https://remix.run/docs/en/main/file-conventions/root)
for more details.

```jsx {14}
// app/root.tsx
import {useNavigate, Outlet} from '@remix-run/react';
import {useNavigate, useHref, Outlet} from '@remix-run/react';
import {NextUIProvider} from '@nextui-org/react';

export default function App() {
Expand All @@ -186,7 +243,7 @@ export default function App() {
{/* ... */}
</head>
<body>
<NextUIProvider navigate={navigate}>
<NextUIProvider navigate={navigate} useHref={useHref}>
<Outlet />
</NextUIProvider>
{/* ... */}
Expand All @@ -196,8 +253,7 @@ export default function App() {
}
```


### TanStack
## TanStack

To use [TanStack Router](https://tanstack.com/router/latest) with NextUI, render NextUI's RouterProvider inside your root route. Use `router.navigate` in the `navigate` prop, and `router.buildLocation` in the `useHref` prop.

Expand All @@ -219,8 +275,7 @@ function RootRoute() {
}
```


### Usage examples
## Usage examples

Now that you have set up the `NextUIProvider` in your app, you can use the `href` prop in the `Tabs`,
`Listbox` and `Dropdown` items to navigate between pages.
Expand Down
68 changes: 68 additions & 0 deletions packages/components/select/__tests__/select.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -653,6 +653,74 @@ describe("Select", () => {
expect(select).toHaveAttribute("aria-expanded", "false");
});

it("should work with onChange (< 300 select items)", async () => {
const onChange = jest.fn();

let options = new Array(10).fill("");

options = options.map((_, i) => {
return `option ${i}`;
});

const wrapper = render(
<Select isOpen aria-label="Favorite Animal" label="Favorite Animal" onChange={onChange}>
{options.map((o) => (
<SelectItem key={o} value={o}>
{o}
</SelectItem>
))}
</Select>,
);

let listbox = wrapper.getByRole("listbox");

expect(listbox).toBeTruthy();

let listboxItems = wrapper.getAllByRole("option");

expect(listboxItems.length).toBe(10);

await act(async () => {
await user.click(listboxItems[1]);

expect(onChange).toBeCalledTimes(1);
});
});

it("should work with onChange (>= 300 select items)", async () => {
let onChange = jest.fn();

let options = new Array(300).fill("");

options = options.map((_, i) => {
return `option ${i}`;
});

const wrapper = render(
<Select isOpen aria-label="Favorite Animal" label="Favorite Animal" onChange={onChange}>
{options.map((o) => (
<SelectItem key={o} value={o}>
{o}
</SelectItem>
))}
</Select>,
);

let listbox = wrapper.getByRole("listbox");

expect(listbox).toBeTruthy();

let listboxItems = wrapper.getAllByRole("option");

expect(listboxItems.length).toBe(300);

await act(async () => {
await user.click(listboxItems[1]);

expect(onChange).toBeCalledTimes(1);
});
});

it("should not close when parent is scrollable", async () => {
const wrapper = render(
<div className="h-screen w-screen m-10">
Expand Down
14 changes: 7 additions & 7 deletions packages/components/select/src/use-select.ts
Original file line number Diff line number Diff line change
Expand Up @@ -250,16 +250,16 @@ export function useSelect<T extends object>(originalProps: UseSelectProps<T>) {
},
onSelectionChange: (keys) => {
onSelectionChange?.(keys);
if (onChange && typeof onChange === "function" && domRef.current) {
const event = {
if (onChange && typeof onChange === "function") {
onChange({
target: {
...domRef.current,
...(domRef.current && {
...domRef.current,
name: domRef.current.name,
}),
value: Array.from(keys).join(","),
name: domRef.current.name,
},
} as React.ChangeEvent<HTMLSelectElement>;

onChange(event);
} as React.ChangeEvent<HTMLSelectElement>);
}
},
});
Expand Down
Loading

0 comments on commit 3a3cd11

Please sign in to comment.