mirror of
https://github.com/nextui-org/nextui.git
synced 2025-12-08 19:26:11 +00:00
commit
2b0442b9ef
@ -1,7 +1,8 @@
|
||||
import {FC} from "react";
|
||||
import {Button, ButtonProps} from "@nextui-org/react";
|
||||
import {ButtonProps} from "@nextui-org/react";
|
||||
import {useClipboard} from "@nextui-org/use-clipboard";
|
||||
import {clsx} from "@nextui-org/shared-utils";
|
||||
import {memo} from "react";
|
||||
|
||||
import {PreviewButton} from "./preview-button";
|
||||
|
||||
import {CheckLinearIcon, CopyLinearIcon} from "@/components/icons";
|
||||
|
||||
@ -9,35 +10,28 @@ export interface CopyButtonProps extends ButtonProps {
|
||||
value?: string;
|
||||
}
|
||||
|
||||
export const CopyButton: FC<CopyButtonProps> = ({value, className, ...buttonProps}) => {
|
||||
export const CopyButton = memo<CopyButtonProps>(({value, className, ...buttonProps}) => {
|
||||
const {copy, copied} = useClipboard();
|
||||
|
||||
const icon = copied ? (
|
||||
<CheckLinearIcon
|
||||
className="opacity-0 scale-50 data-[visible=true]:opacity-100 data-[visible=true]:scale-100 transition-transform-opacity"
|
||||
data-visible={copied}
|
||||
size={16}
|
||||
/>
|
||||
) : (
|
||||
<CopyLinearIcon
|
||||
className="opacity-0 scale-50 data-[visible=true]:opacity-100 data-[visible=true]:scale-100 transition-transform-opacity"
|
||||
data-visible={!copied}
|
||||
size={16}
|
||||
/>
|
||||
);
|
||||
|
||||
const handleCopy = () => {
|
||||
copy(value);
|
||||
};
|
||||
|
||||
return (
|
||||
<Button
|
||||
isIconOnly
|
||||
className={clsx(
|
||||
"absolute z-50 right-3 text-zinc-300 top-8 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",
|
||||
className,
|
||||
)}
|
||||
size="sm"
|
||||
variant="bordered"
|
||||
onPress={handleCopy}
|
||||
{...buttonProps}
|
||||
>
|
||||
<CheckLinearIcon
|
||||
className="absolute opacity-0 scale-50 data-[visible=true]:opacity-100 data-[visible=true]:scale-100 transition-transform-opacity"
|
||||
data-visible={copied}
|
||||
size={16}
|
||||
/>
|
||||
<CopyLinearIcon
|
||||
className="absolute opacity-0 scale-50 data-[visible=true]:opacity-100 data-[visible=true]:scale-100 transition-transform-opacity"
|
||||
data-visible={!copied}
|
||||
size={16}
|
||||
/>
|
||||
</Button>
|
||||
);
|
||||
};
|
||||
return <PreviewButton className={className} icon={icon} onPress={handleCopy} {...buttonProps} />;
|
||||
});
|
||||
|
||||
CopyButton.displayName = "CopyButton";
|
||||
|
||||
@ -10,6 +10,8 @@ import {SandpackFiles} from "@codesandbox/sandpack-react/types";
|
||||
import {BgGridContainer} from "@/components/bg-grid-container";
|
||||
import {GradientBox, GradientBoxProps} from "@/components/gradient-box";
|
||||
import {CopyButton} from "@/components/copy-button";
|
||||
import {StackblitzButton} from "@/components/stackblitz-button";
|
||||
import {PreviewButton} from "@/components/preview-button";
|
||||
|
||||
export interface ReactLiveDemoProps {
|
||||
code: string;
|
||||
@ -21,6 +23,7 @@ export interface ReactLiveDemoProps {
|
||||
className?: string;
|
||||
gradientColor?: GradientBoxProps["color"];
|
||||
overflow?: "auto" | "visible" | "hidden";
|
||||
typescriptStrict?: boolean;
|
||||
}
|
||||
|
||||
// 🚨 Do not pass react-hook-form to scope, it will break the live preview since
|
||||
@ -49,11 +52,18 @@ export const ReactLiveDemo: React.FC<ReactLiveDemoProps> = ({
|
||||
height,
|
||||
className,
|
||||
noInline,
|
||||
typescriptStrict = false,
|
||||
}) => {
|
||||
const content = (
|
||||
<>
|
||||
{files?.[DEFAULT_FILE] && (
|
||||
<div className="absolute top-[-28px] right-[-8px] z-50">
|
||||
<div className="absolute top-[-26px] right-[3px] z-50 flex items-center">
|
||||
<StackblitzButton
|
||||
button={<PreviewButton icon={undefined} />}
|
||||
className="before:hidden opacity-0 group-hover/code-demo:opacity-100 transition-opacity text-zinc-400"
|
||||
files={files}
|
||||
typescriptStrict={typescriptStrict}
|
||||
/>
|
||||
<CopyButton
|
||||
className="before:hidden opacity-0 group-hover/code-demo:opacity-100 transition-opacity text-zinc-400"
|
||||
value={files?.[DEFAULT_FILE] as string}
|
||||
|
||||
@ -423,6 +423,23 @@ const CodeSandboxIcon: React.FC<IconSvgProps> = ({width = "1em", height = "1em",
|
||||
);
|
||||
};
|
||||
|
||||
const StackblitzIcon: React.FC<IconSvgProps> = ({...props}) => {
|
||||
return (
|
||||
<svg
|
||||
height={16}
|
||||
viewBox="0 0 1024 1024"
|
||||
width={16}
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
{...props}
|
||||
>
|
||||
<path
|
||||
d="M848 359.3H627.7L825.8 109c4.1-5.3.4-13-6.3-13H436c-2.8 0-5.5 1.5-6.9 4L170 547.5c-3.1 5.3.7 12 6.9 12h174.4l-89.4 357.6c-1.9 7.8 7.5 13.3 13.3 7.7L853.5 373c5.2-4.9 1.7-13.7-5.5-13.7M378.2 732.5l60.3-241H281.1l189.6-327.4h224.6L487 427.4h211z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
};
|
||||
|
||||
const JavascriptIcon: React.FC<IconSvgProps> = ({width = "1em", height = "1em", ...props}) => {
|
||||
return (
|
||||
<svg
|
||||
@ -470,6 +487,7 @@ export {
|
||||
NewNextJSIcon,
|
||||
StorybookIcon,
|
||||
CodeSandboxIcon,
|
||||
StackblitzIcon,
|
||||
JavascriptIcon,
|
||||
TypescriptIcon,
|
||||
BunIcon,
|
||||
|
||||
31
apps/docs/components/preview-button.tsx
Normal file
31
apps/docs/components/preview-button.tsx
Normal file
@ -0,0 +1,31 @@
|
||||
import {forwardRef} from "react";
|
||||
import {Button, ButtonProps} from "@nextui-org/react";
|
||||
import {clsx} from "@nextui-org/shared-utils";
|
||||
|
||||
export interface PreviewButtonProps extends ButtonProps {
|
||||
icon: React.ReactNode;
|
||||
}
|
||||
|
||||
export const PreviewButton = forwardRef<HTMLButtonElement | null, PreviewButtonProps>(
|
||||
(props, ref) => {
|
||||
const {icon, className, ...buttonProps} = props;
|
||||
|
||||
return (
|
||||
<Button
|
||||
ref={ref}
|
||||
isIconOnly
|
||||
className={clsx(
|
||||
"relative z-50 text-zinc-300 top-8 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",
|
||||
className,
|
||||
)}
|
||||
size="sm"
|
||||
variant="light"
|
||||
{...buttonProps}
|
||||
>
|
||||
{icon}
|
||||
</Button>
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
PreviewButton.displayName = "PreviewButton";
|
||||
@ -3,6 +3,8 @@
|
||||
import {FC, useRef} from "react";
|
||||
import {SandpackProvider, SandpackLayout, SandpackPreview} from "@codesandbox/sandpack-react";
|
||||
|
||||
import {StackblitzButton} from "../stackblitz-button";
|
||||
|
||||
import {SandpackCodeViewer} from "./code-viewer";
|
||||
import {nextuiTheme} from "./theme";
|
||||
import {UseSandpackProps, useSandpack} from "./use-sandpack";
|
||||
@ -72,6 +74,18 @@ export const Sandpack: FC<SandpackProps> = ({
|
||||
{showReportBug && <BugReportButton />}
|
||||
{showCopyCode && <CopyButton />}
|
||||
{!showPreview && showOpenInCodeSandbox && <CodeSandboxButton />}
|
||||
{!showPreview && showOpenInCodeSandbox && (
|
||||
<StackblitzButton
|
||||
isIconOnly
|
||||
as="span"
|
||||
className="dark:text-zinc-500 text-white"
|
||||
files={files}
|
||||
size="sm"
|
||||
title="Open in Stackblitz"
|
||||
typescriptStrict={typescriptStrict}
|
||||
variant="light"
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
{hasTypescript && sandpackTemplate && (
|
||||
<LanguageSelector template={sandpackTemplate} onChange={setCurrentTemplate} />
|
||||
|
||||
58
apps/docs/components/stackblitz-button.tsx
Normal file
58
apps/docs/components/stackblitz-button.tsx
Normal file
@ -0,0 +1,58 @@
|
||||
import React, {forwardRef} from "react";
|
||||
import stackblitzSdk from "@stackblitz/sdk";
|
||||
import {SandpackFiles} from "@codesandbox/sandpack-react/types";
|
||||
|
||||
import {StackblitzIcon} from "./icons";
|
||||
|
||||
import {useStackblitz} from "@/hooks/use-stackblitz";
|
||||
import {Tooltip} from "@/../../packages/components/tooltip/src";
|
||||
import {Button, ButtonProps} from "@/../../packages/components/button/src";
|
||||
|
||||
export interface StackblitzButtonProps extends ButtonProps {
|
||||
files: SandpackFiles;
|
||||
typescriptStrict?: boolean;
|
||||
className?: string;
|
||||
button?: React.ReactElement;
|
||||
icon?: React.ReactNode;
|
||||
}
|
||||
|
||||
export const StackblitzButton = forwardRef<HTMLButtonElement, StackblitzButtonProps>(
|
||||
(props, ref) => {
|
||||
const {
|
||||
files,
|
||||
typescriptStrict = false,
|
||||
className,
|
||||
button = <Button />,
|
||||
icon = (
|
||||
<StackblitzIcon
|
||||
data-visible
|
||||
className="opacity-0 data-[visible=true]:opacity-100 transition-transform-opacity"
|
||||
/>
|
||||
),
|
||||
...rest
|
||||
} = props;
|
||||
const {stackblitzPrefillConfig, entryFile} = useStackblitz({
|
||||
files,
|
||||
typescriptStrict,
|
||||
});
|
||||
|
||||
return (
|
||||
<Tooltip closeDelay={0} content="Open in Stackblitz">
|
||||
{React.cloneElement(button, {
|
||||
ref,
|
||||
className,
|
||||
icon,
|
||||
onPress: () => {
|
||||
stackblitzSdk.openProject(stackblitzPrefillConfig, {
|
||||
openFile: [entryFile],
|
||||
});
|
||||
},
|
||||
children: icon,
|
||||
...rest,
|
||||
})}
|
||||
</Tooltip>
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
StackblitzButton.displayName = "StackblitzButton";
|
||||
@ -81,6 +81,13 @@
|
||||
"title": "Astro",
|
||||
"keywords": "astro, nextui",
|
||||
"path": "/docs/frameworks/astro.mdx"
|
||||
},
|
||||
{
|
||||
"key": "laravel",
|
||||
"title": "Laravel",
|
||||
"keywords": "laravel, nextui",
|
||||
"path": "/docs/frameworks/laravel.mdx",
|
||||
"newPost": true
|
||||
}
|
||||
]
|
||||
},
|
||||
@ -515,4 +522,4 @@
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@ -331,7 +331,7 @@ In case you need to customize the input even further, you can use the `useInput`
|
||||
},
|
||||
{
|
||||
attribute: "type",
|
||||
type: "text | email | url | password | tel | search",
|
||||
type: "text | email | url | password | tel | search | file",
|
||||
description: "The type of the input.",
|
||||
default: "text"
|
||||
},
|
||||
|
||||
238
apps/docs/content/docs/frameworks/laravel.mdx
Normal file
238
apps/docs/content/docs/frameworks/laravel.mdx
Normal file
@ -0,0 +1,238 @@
|
||||
---
|
||||
title: Laravel
|
||||
description: How to use NextUI with Laravel
|
||||
---
|
||||
|
||||
# Laravel
|
||||
|
||||
Requirements:
|
||||
|
||||
- [Laravel 11](https://laravel.com/)
|
||||
- [PHP v8.2](https://www.php.net/)
|
||||
- [React 18](https://reactjs.org/) or later
|
||||
- [Tailwind CSS 3.4](https://tailwindcss.com/docs/guides/vite#react) or later
|
||||
- [Framer Motion 11.9](https://www.framer.com/motion/) or later
|
||||
|
||||
------
|
||||
|
||||
<CarbonAd/>
|
||||
|
||||
To use NextUI in your Laravel project, you need to follow the following steps:
|
||||
|
||||
### Using NextUI + Laravel template
|
||||
|
||||
If you are starting a new project, you can run one of the following commands to create a Laravel project pre-configured with NextUI:
|
||||
|
||||
<PackageManagers
|
||||
commands={{
|
||||
npm: 'npx create-laravel@latest --template https://github.com/nextui-org/laravel-template',
|
||||
yarn: 'yarn create laravel --template https://github.com/nextui-org/laravel-template',
|
||||
pnpm: 'pnpm create laravel --template https://github.com/nextui-org/laravel-template',
|
||||
bun: 'bunx create-laravel@latest --template https://github.com/nextui-org/laravel-template',
|
||||
}}
|
||||
/>
|
||||
|
||||
### Automatic Installation
|
||||
|
||||
You can add individual components using the CLI. For example, to add a button component:
|
||||
|
||||
```codeBlock bash
|
||||
nextui add button
|
||||
```
|
||||
|
||||
This command adds the Button component to your project and manages all related dependencies.
|
||||
|
||||
You can also add multiple components at once:
|
||||
|
||||
```codeBlock bash
|
||||
nextui add button input
|
||||
```
|
||||
|
||||
Or you can add the main library `@nextui-org/react` by running the following command:
|
||||
|
||||
```codeBlock bash
|
||||
nextui add --all
|
||||
```
|
||||
|
||||
If you leave out the component name, the CLI will prompt you to select the components you want to add.
|
||||
|
||||
```codeBlock bash
|
||||
? Which components would you like to add? › - Space to select. Return to submit
|
||||
Instructions:
|
||||
↑/↓: Highlight option
|
||||
←/→/[space]: Toggle selection
|
||||
[a,b,c]/delete: Filter choices
|
||||
enter/return: Complete answer
|
||||
|
||||
Filtered results for: Enter something to filter
|
||||
|
||||
◯ accordion
|
||||
◯ autocomplete
|
||||
◯ avatar
|
||||
◯ badge
|
||||
◯ breadcrumbs
|
||||
◉ button
|
||||
◯ card
|
||||
◯ checkbox
|
||||
◯ chip
|
||||
◯ code
|
||||
```
|
||||
|
||||
You still need to add the provider to your app manually (we are working on automating this step).
|
||||
|
||||
```jsx {3,7,9}
|
||||
// app/providers.tsx
|
||||
|
||||
import {NextUIProvider} from '@nextui-org/react'
|
||||
|
||||
export function Providers({children}: { children: React.ReactNode }) {
|
||||
return (
|
||||
<NextUIProvider>
|
||||
{children}
|
||||
</NextUIProvider>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
<Spacer y={4} />
|
||||
|
||||
```jsx {8,23,25}
|
||||
// app.tsx or app.jsx
|
||||
import '../css/app.css';
|
||||
import './bootstrap';
|
||||
|
||||
import { createInertiaApp } from '@inertiajs/react';
|
||||
import { resolvePageComponent } from 'laravel-vite-plugin/inertia-helpers';
|
||||
import { createRoot } from 'react-dom/client';
|
||||
import {NextUIProvider} from "@nextui-org/react";
|
||||
|
||||
const appName = import.meta.env.VITE_APP_NAME || 'Laravel';
|
||||
|
||||
createInertiaApp({
|
||||
title: (title) => `${title} - ${appName}`,
|
||||
resolve: (name) =>
|
||||
resolvePageComponent(
|
||||
`./Pages/${name}.tsx`,
|
||||
import.meta.glob('./Pages/**/*.tsx'),
|
||||
),
|
||||
setup({ el, App, props }) {
|
||||
const root = createRoot(el);
|
||||
|
||||
root.render(
|
||||
<NextUIProvider>
|
||||
<App {...props} />
|
||||
</NextUIProvider>
|
||||
);
|
||||
},
|
||||
progress: {
|
||||
color: '#4B5563',
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
### Manual Installation
|
||||
|
||||
<Steps>
|
||||
|
||||
### Add dependencies
|
||||
|
||||
In your Laravel project, run one of the following command to install NextUI:
|
||||
|
||||
<PackageManagers
|
||||
commands={{
|
||||
npm: 'npm i @nextui-org/react framer-motion',
|
||||
yarn: 'yarn add @nextui-org/react framer-motion',
|
||||
pnpm: 'pnpm add @nextui-org/react framer-motion',
|
||||
bun: "bun add @nextui-org/react framer-motion"
|
||||
}}
|
||||
/>
|
||||
|
||||
### Hoisted Dependencies Setup
|
||||
|
||||
<Blockquote color="primary">
|
||||
**Note**: This step is only for those who use `pnpm` to install. If you install NextUI using other package managers, you may skip this step.
|
||||
</Blockquote>
|
||||
|
||||
If you are using pnpm, you need to add the following line to your `.npmrc` file to hoist our packages to the root `node_modules`.
|
||||
|
||||
```bash
|
||||
public-hoist-pattern[]=*@nextui-org/*
|
||||
```
|
||||
|
||||
After modifying the `.npmrc` file, you need to run `pnpm install` again to ensure that the dependencies are installed correctly.
|
||||
|
||||
### Tailwind CSS Setup
|
||||
|
||||
NextUI is built on top of Tailwind CSS, so you need to install Tailwind CSS first. You can follow the official
|
||||
[installation guide](https://tailwindcss.com/docs/guides/vite#react) to install Tailwind CSS. Then you need to add
|
||||
the following code to your `tailwind.config.js` file:
|
||||
|
||||
<Blockquote color="primary">
|
||||
**Note**: If you are using pnpm and monorepo architecture, please make sure you are pointing to the ROOT `node_modules`
|
||||
</Blockquote>
|
||||
|
||||
```js {2,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()]
|
||||
}
|
||||
```
|
||||
|
||||
### Provider Setup
|
||||
|
||||
After installing NextUI, you need to set up the `NextUIProvider` at the `root` of your application.
|
||||
|
||||
Go to the src directory and inside `app.jsx` or `app.tsx`, wrap `NextUIProvider` around App:
|
||||
|
||||
```jsx {8,23,25}
|
||||
// app.tsx or app.jsx
|
||||
import '../css/app.css';
|
||||
import './bootstrap';
|
||||
|
||||
import { createInertiaApp } from '@inertiajs/react';
|
||||
import { resolvePageComponent } from 'laravel-vite-plugin/inertia-helpers';
|
||||
import { createRoot } from 'react-dom/client';
|
||||
import {NextUIProvider} from "@nextui-org/react";
|
||||
|
||||
const appName = import.meta.env.VITE_APP_NAME || 'Laravel';
|
||||
|
||||
createInertiaApp({
|
||||
title: (title) => `${title} - ${appName}`,
|
||||
resolve: (name) =>
|
||||
resolvePageComponent(
|
||||
`./Pages/${name}.tsx`,
|
||||
import.meta.glob('./Pages/**/*.tsx'),
|
||||
),
|
||||
setup({ el, App, props }) {
|
||||
const root = createRoot(el);
|
||||
|
||||
root.render(
|
||||
<NextUIProvider>
|
||||
<App {...props} />
|
||||
</NextUIProvider>
|
||||
);
|
||||
},
|
||||
progress: {
|
||||
color: '#4B5563',
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
</Steps>
|
||||
|
||||
<Blockquote
|
||||
color="warning"
|
||||
>
|
||||
Version 2 is only compatible with React 18 or later. If you are using React 17 or earlier, please use <Link href="https://v1.nextui.org/docs/getting-started" isExternal>version 1 of NextUI</Link>.
|
||||
</Blockquote>
|
||||
88
apps/docs/hooks/use-stackblitz.ts
Normal file
88
apps/docs/hooks/use-stackblitz.ts
Normal file
@ -0,0 +1,88 @@
|
||||
import {Project} from "@stackblitz/sdk";
|
||||
import {SandpackFiles} from "@codesandbox/sandpack-react/types";
|
||||
|
||||
import {mapKeys, omit} from "@/../../packages/utilities/shared-utils/src";
|
||||
import {useSandpack} from "@/components/sandpack/use-sandpack";
|
||||
|
||||
export interface UseSandpackProps {
|
||||
files: SandpackFiles;
|
||||
typescriptStrict?: boolean;
|
||||
}
|
||||
|
||||
const viteConfig = `import { defineConfig } from "vite";
|
||||
import react from "@vitejs/plugin-react";
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig({
|
||||
plugins: [react()],
|
||||
});
|
||||
`;
|
||||
|
||||
function transformSandpackFiles(files: SandpackFiles) {
|
||||
return Object.fromEntries(
|
||||
Object.entries(files).map(([key, value]) => [
|
||||
key,
|
||||
typeof value === "string" ? value : value.code,
|
||||
]),
|
||||
);
|
||||
}
|
||||
|
||||
export function useStackblitz(props: UseSandpackProps) {
|
||||
const {files, typescriptStrict = false} = props;
|
||||
|
||||
const {
|
||||
customSetup,
|
||||
files: filesData,
|
||||
entryFile,
|
||||
} = useSandpack({
|
||||
files: transformSandpackFiles(files),
|
||||
typescriptStrict,
|
||||
});
|
||||
|
||||
const transformFiles = mapKeys(filesData, (_, key) => key.replace(/^\//, ""));
|
||||
|
||||
const dependencies = {...customSetup.dependencies, ...customSetup.devDependencies};
|
||||
|
||||
const packageJson = `{
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vite build",
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"react": "18.3.1",
|
||||
"react-dom": "18.3.1",
|
||||
${Object.entries(omit(dependencies as any, ["react", "react-dom"]))
|
||||
.map(([key, value]) => `"${key}": "${value}"`)
|
||||
.join(",\n ")}
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vitejs/plugin-react": "4.3.4",
|
||||
"vite": "6.0.6",
|
||||
"autoprefixer": "10.4.20",
|
||||
"postcss": "8.4.49",
|
||||
"tailwindcss": "3.4.17"
|
||||
},
|
||||
"main": "/index.jsx"
|
||||
}`;
|
||||
|
||||
const stackblitzPrefillConfig: Project = {
|
||||
files: {
|
||||
...transformSandpackFiles(transformFiles),
|
||||
"vite.config.js": viteConfig,
|
||||
"package.json": packageJson,
|
||||
},
|
||||
dependencies,
|
||||
title: "NextUI",
|
||||
template: "node",
|
||||
};
|
||||
|
||||
const findEntryFile = Object.keys(stackblitzPrefillConfig.files).find((key) =>
|
||||
key.includes("App"),
|
||||
);
|
||||
|
||||
return {
|
||||
entryFile: findEntryFile ?? entryFile,
|
||||
stackblitzPrefillConfig,
|
||||
};
|
||||
}
|
||||
@ -39,7 +39,6 @@
|
||||
"@nextui-org/use-clipboard": "workspace:*",
|
||||
"@nextui-org/use-infinite-scroll": "workspace:*",
|
||||
"@nextui-org/use-is-mobile": "workspace:*",
|
||||
"clsx": "^1.2.1",
|
||||
"@radix-ui/react-scroll-area": "^1.0.5",
|
||||
"@react-aria/focus": "3.19.0",
|
||||
"@react-aria/i18n": "3.12.4",
|
||||
@ -53,8 +52,10 @@
|
||||
"@react-stately/layout": "4.1.0",
|
||||
"@react-stately/tree": "3.8.6",
|
||||
"@rehooks/local-storage": "^2.4.5",
|
||||
"@tanstack/react-virtual": "3.10.9",
|
||||
"@stackblitz/sdk": "^1.11.0",
|
||||
"@tanstack/react-virtual": "3.11.2",
|
||||
"canvas-confetti": "^1.9.2",
|
||||
"clsx": "^1.2.1",
|
||||
"cmdk": "^0.2.0",
|
||||
"color2k": "2.0.3",
|
||||
"contentlayer2": "0.5.3",
|
||||
|
||||
@ -1,5 +1,15 @@
|
||||
# @nextui-org/accordion
|
||||
|
||||
## 2.2.7
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`e7ff673`](https://github.com/nextui-org/nextui/commit/e7ff6730d7e891f1e9e3ca232b1faaebc5aedef2)]:
|
||||
- @nextui-org/react-utils@2.1.3
|
||||
- @nextui-org/divider@2.2.5
|
||||
- @nextui-org/aria-utils@2.2.7
|
||||
- @nextui-org/framer-utils@2.1.6
|
||||
|
||||
## 2.2.6
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nextui-org/accordion",
|
||||
"version": "2.2.6",
|
||||
"version": "2.2.7",
|
||||
"description": "Collapse display a list of high-level options that can expand/collapse to reveal more information.",
|
||||
"keywords": [
|
||||
"react",
|
||||
|
||||
@ -1,5 +1,15 @@
|
||||
# @nextui-org/alert
|
||||
|
||||
## 2.2.9
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#4447](https://github.com/nextui-org/nextui/pull/4447) [`a83388a`](https://github.com/nextui-org/nextui/commit/a83388aaf4521f0ed8dfed99a54998156df1868b) Thanks [@wingkwong](https://github.com/wingkwong)! - mark description prop as optional (#4445)
|
||||
|
||||
- Updated dependencies [[`e7ff673`](https://github.com/nextui-org/nextui/commit/e7ff6730d7e891f1e9e3ca232b1faaebc5aedef2)]:
|
||||
- @nextui-org/react-utils@2.1.3
|
||||
- @nextui-org/button@2.2.9
|
||||
|
||||
## 2.2.8
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nextui-org/alert",
|
||||
"version": "2.2.8",
|
||||
"version": "2.2.9",
|
||||
"description": "Alerts are temporary notifications that provide concise feedback about an action or event.",
|
||||
"keywords": [
|
||||
"alert"
|
||||
|
||||
@ -19,9 +19,9 @@ interface Props extends HTMLNextUIProps<"div"> {
|
||||
*/
|
||||
title?: string;
|
||||
/**
|
||||
* Main body of the alert message
|
||||
* description of the alert message
|
||||
*/
|
||||
description: ReactNode;
|
||||
description?: ReactNode;
|
||||
/**
|
||||
* Icon to be displayed in the alert - overrides the default icon
|
||||
*/
|
||||
|
||||
@ -1,5 +1,28 @@
|
||||
# @nextui-org/autocomplete
|
||||
|
||||
## 2.3.9
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#4458](https://github.com/nextui-org/nextui/pull/4458) [`7c2bc4a`](https://github.com/nextui-org/nextui/commit/7c2bc4a18ef01424c7ff464cad3401dd6596e7b3) Thanks [@wingkwong](https://github.com/wingkwong)! - clear autocomplete value when pressing clear button (#4402)
|
||||
|
||||
- [#4452](https://github.com/nextui-org/nextui/pull/4452) [`0401f25`](https://github.com/nextui-org/nextui/commit/0401f2548f525fc4194186b54f563cb91c6ccd0c) Thanks [@Peterl561](https://github.com/Peterl561)! - fixed autocomplete validate prop not working after hovering when validation behavior is native
|
||||
|
||||
- [#4462](https://github.com/nextui-org/nextui/pull/4462) [`16c57ec`](https://github.com/nextui-org/nextui/commit/16c57ece6467d755645f109b8de810c9063e5665) Thanks [@vinroger](https://github.com/vinroger)! - add support for dataset with section, add support for scrollshadow
|
||||
|
||||
- [#4496](https://github.com/nextui-org/nextui/pull/4496) [`0c45fed`](https://github.com/nextui-org/nextui/commit/0c45fed420747b41a4d2a7bb07e9582f6f609287) Thanks [@wingkwong](https://github.com/wingkwong)! - fix missing popover props except content (#4484)
|
||||
|
||||
- Updated dependencies [[`d92468a`](https://github.com/nextui-org/nextui/commit/d92468aa1e35d5022c071b5d2674f5bfb6408001), [`33e0418`](https://github.com/nextui-org/nextui/commit/33e0418d08c29f829b00ee3bc41972dfce6a3370), [`16c57ec`](https://github.com/nextui-org/nextui/commit/16c57ece6467d755645f109b8de810c9063e5665), [`e7ff673`](https://github.com/nextui-org/nextui/commit/e7ff6730d7e891f1e9e3ca232b1faaebc5aedef2), [`fb46df2`](https://github.com/nextui-org/nextui/commit/fb46df2430f95cddef0c25fce4639c2078b34f62)]:
|
||||
- @nextui-org/listbox@2.3.9
|
||||
- @nextui-org/popover@2.3.9
|
||||
- @nextui-org/react-utils@2.1.3
|
||||
- @nextui-org/button@2.2.9
|
||||
- @nextui-org/form@2.1.8
|
||||
- @nextui-org/input@2.4.8
|
||||
- @nextui-org/scroll-shadow@2.3.5
|
||||
- @nextui-org/spinner@2.2.6
|
||||
- @nextui-org/aria-utils@2.2.7
|
||||
|
||||
## 2.3.8
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@ -235,6 +235,49 @@ describe("Autocomplete", () => {
|
||||
expect(autocomplete).toHaveFocus();
|
||||
});
|
||||
|
||||
it("should clear arbitrary value after clicking clear button", async () => {
|
||||
const wrapper = render(
|
||||
<Autocomplete aria-label="Favorite Animal" data-testid="autocomplete" label="Favorite Animal">
|
||||
<AutocompleteItem key="penguin" value="penguin">
|
||||
Penguin
|
||||
</AutocompleteItem>
|
||||
<AutocompleteItem key="zebra" value="zebra">
|
||||
Zebra
|
||||
</AutocompleteItem>
|
||||
<AutocompleteItem key="shark" value="shark">
|
||||
Shark
|
||||
</AutocompleteItem>
|
||||
</Autocomplete>,
|
||||
);
|
||||
|
||||
const autocomplete = wrapper.getByTestId("autocomplete");
|
||||
|
||||
// open the select listbox
|
||||
await user.click(autocomplete);
|
||||
|
||||
// assert that the autocomplete listbox is open
|
||||
expect(autocomplete).toHaveAttribute("aria-expanded", "true");
|
||||
|
||||
await user.keyboard("pe");
|
||||
|
||||
const {container} = wrapper;
|
||||
|
||||
const clearButton = container.querySelector(
|
||||
"[data-slot='inner-wrapper'] button:nth-of-type(1)",
|
||||
)!;
|
||||
|
||||
expect(clearButton).not.toBeNull();
|
||||
|
||||
// click the clear button
|
||||
await user.click(clearButton);
|
||||
|
||||
// assert that the input has empty value
|
||||
expect(autocomplete).toHaveValue("");
|
||||
|
||||
// assert that input is focused
|
||||
expect(autocomplete).toHaveFocus();
|
||||
});
|
||||
|
||||
it("should keep the ListBox open after clicking clear button", async () => {
|
||||
const wrapper = render(
|
||||
<Autocomplete aria-label="Favorite Animal" data-testid="autocomplete" label="Favorite Animal">
|
||||
@ -739,6 +782,60 @@ describe("Autocomplete", () => {
|
||||
expect(input).not.toHaveAttribute("aria-describedby");
|
||||
expect(input.validity.valid).toBe(true);
|
||||
});
|
||||
|
||||
// this test is to cover a case where hovering over the combobox causes the validation from use-input to overwrite the validation from use-autocomplete if not handled properly
|
||||
// this causes the first form submit after initial render to always succeed even if the validate function returns an error
|
||||
it("should work with validate after hovering", async () => {
|
||||
const onSubmit = jest.fn((e) => {
|
||||
e.preventDefault();
|
||||
});
|
||||
|
||||
const {getByTestId, findByRole} = render(
|
||||
<Form validationBehavior="native" onSubmit={onSubmit}>
|
||||
<AutocompleteExample
|
||||
data-testid="combobox"
|
||||
name="animal"
|
||||
validate={(value) => {
|
||||
if (!value?.selectedKey) {
|
||||
return "Please select an animal";
|
||||
}
|
||||
}}
|
||||
validationBehavior="native"
|
||||
/>
|
||||
<button data-testid="submit" type="submit">
|
||||
Submit
|
||||
</button>
|
||||
</Form>,
|
||||
);
|
||||
|
||||
const combobox = getByTestId("combobox") as HTMLInputElement;
|
||||
const submit = getByTestId("submit");
|
||||
|
||||
expect(combobox).not.toHaveAttribute("aria-describedby");
|
||||
expect(combobox.validity.valid).toBe(false);
|
||||
|
||||
await user.hover(combobox);
|
||||
await user.click(submit);
|
||||
|
||||
expect(onSubmit).toHaveBeenCalledTimes(0);
|
||||
expect(combobox).toHaveAttribute("aria-describedby");
|
||||
expect(
|
||||
document.getElementById(combobox.getAttribute("aria-describedby")!),
|
||||
).toHaveTextContent("Please select an animal");
|
||||
|
||||
await user.click(combobox);
|
||||
await user.keyboard("pe");
|
||||
|
||||
const listbox = await findByRole("listbox");
|
||||
const items = within(listbox).getAllByRole("option");
|
||||
|
||||
await user.click(items[0]);
|
||||
expect(combobox).toHaveAttribute("aria-describedby");
|
||||
|
||||
await user.click(submit);
|
||||
expect(onSubmit).toHaveBeenCalledTimes(1);
|
||||
expect(combobox).not.toHaveAttribute("aria-describedby");
|
||||
});
|
||||
});
|
||||
|
||||
describe("validationBehavior=aria", () => {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nextui-org/autocomplete",
|
||||
"version": "2.3.8",
|
||||
"version": "2.3.9",
|
||||
"description": "An autocomplete combines a text input with a listbox, allowing users to filter a list of options to items matching a query.",
|
||||
"keywords": [
|
||||
"autocomplete"
|
||||
|
||||
@ -418,13 +418,9 @@ export function useAutocomplete<T extends object>(originalProps: UseAutocomplete
|
||||
onPress: (e: PressEvent) => {
|
||||
slotsProps.clearButtonProps?.onPress?.(e);
|
||||
if (state.selectedItem) {
|
||||
state.setInputValue("");
|
||||
state.setSelectedKey(null);
|
||||
} else {
|
||||
if (allowsCustomValue) {
|
||||
state.setInputValue("");
|
||||
}
|
||||
}
|
||||
state.setInputValue("");
|
||||
state.open();
|
||||
},
|
||||
"data-visible": !!state.selectedItem || state.inputValue?.length > 0,
|
||||
@ -433,12 +429,19 @@ export function useAutocomplete<T extends object>(originalProps: UseAutocomplete
|
||||
}),
|
||||
} as ButtonProps);
|
||||
|
||||
// prevent use-input's useFormValidation hook from overwriting use-autocomplete's useFormValidation hook when there are uncommitted validation errors
|
||||
// see https://github.com/nextui-org/nextui/pull/4452
|
||||
const hasUncommittedValidation =
|
||||
validationBehavior === "native" &&
|
||||
state.displayValidation.isInvalid === false &&
|
||||
state.realtimeValidation.isInvalid === true;
|
||||
|
||||
const getInputProps = () =>
|
||||
({
|
||||
...otherProps,
|
||||
...inputProps,
|
||||
...slotsProps.inputProps,
|
||||
isInvalid,
|
||||
isInvalid: hasUncommittedValidation ? undefined : isInvalid,
|
||||
validationBehavior,
|
||||
errorMessage:
|
||||
typeof errorMessage === "function"
|
||||
@ -461,6 +464,7 @@ export function useAutocomplete<T extends object>(originalProps: UseAutocomplete
|
||||
itemHeight,
|
||||
}
|
||||
: undefined,
|
||||
scrollShadowProps: slotsProps.scrollShadowProps,
|
||||
...mergeProps(slotsProps.listboxProps, listBoxProps, {
|
||||
shouldHighlightOnFocus: true,
|
||||
}),
|
||||
@ -478,6 +482,7 @@ export function useAutocomplete<T extends object>(originalProps: UseAutocomplete
|
||||
triggerType: "listbox",
|
||||
...popoverProps,
|
||||
classNames: {
|
||||
...slotsProps.popoverProps?.classNames,
|
||||
content: slots.popoverContent({
|
||||
class: clsx(
|
||||
classNames?.popoverContent,
|
||||
|
||||
@ -1187,3 +1187,23 @@ export const CustomItemHeight = {
|
||||
itemHeight: 40,
|
||||
},
|
||||
};
|
||||
|
||||
export const PopoverTopOrBottom = {
|
||||
args: {
|
||||
...defaultProps,
|
||||
},
|
||||
render: (args) => (
|
||||
<div className="relative h-screen w-screen">
|
||||
<div className="absolute top-0 p-8">
|
||||
<div className="w-48">
|
||||
<Template {...args} />
|
||||
</div>
|
||||
</div>
|
||||
<div className="absolute top-1/2 p-8">
|
||||
<div className="w-48">
|
||||
<Template {...args} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
};
|
||||
|
||||
@ -1,5 +1,13 @@
|
||||
# @nextui-org/avatar
|
||||
|
||||
## 2.2.6
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`5d0fc9f`](https://github.com/nextui-org/nextui/commit/5d0fc9f786ef522d74333f2dc9384626fd8cad3b), [`ef916ea`](https://github.com/nextui-org/nextui/commit/ef916ead525414d7b62c01f26ae5580fd9ba7f14), [`e7ff673`](https://github.com/nextui-org/nextui/commit/e7ff6730d7e891f1e9e3ca232b1faaebc5aedef2), [`e7ff673`](https://github.com/nextui-org/nextui/commit/e7ff6730d7e891f1e9e3ca232b1faaebc5aedef2)]:
|
||||
- @nextui-org/use-image@2.1.2
|
||||
- @nextui-org/react-utils@2.1.3
|
||||
|
||||
## 2.2.5
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nextui-org/avatar",
|
||||
"version": "2.2.5",
|
||||
"version": "2.2.6",
|
||||
"description": "The Avatar component is used to represent a user, and displays the profile picture, initials or fallback icon.",
|
||||
"keywords": [
|
||||
"avatar"
|
||||
|
||||
@ -1,5 +1,12 @@
|
||||
# @nextui-org/badge
|
||||
|
||||
## 2.2.5
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`e7ff673`](https://github.com/nextui-org/nextui/commit/e7ff6730d7e891f1e9e3ca232b1faaebc5aedef2)]:
|
||||
- @nextui-org/react-utils@2.1.3
|
||||
|
||||
## 2.2.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nextui-org/badge",
|
||||
"version": "2.2.4",
|
||||
"version": "2.2.5",
|
||||
"description": "Badges are used as a small numerical value or status descriptor for UI elements.",
|
||||
"keywords": [
|
||||
"badge"
|
||||
|
||||
@ -1,5 +1,12 @@
|
||||
# @nextui-org/breadcrumbs
|
||||
|
||||
## 2.2.6
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`e7ff673`](https://github.com/nextui-org/nextui/commit/e7ff6730d7e891f1e9e3ca232b1faaebc5aedef2)]:
|
||||
- @nextui-org/react-utils@2.1.3
|
||||
|
||||
## 2.2.5
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nextui-org/breadcrumbs",
|
||||
"version": "2.2.5",
|
||||
"version": "2.2.6",
|
||||
"description": "Breadcrumbs display a hierarchy of links to the current page or resource in an application.",
|
||||
"keywords": [
|
||||
"breadcrumbs"
|
||||
|
||||
@ -1,5 +1,14 @@
|
||||
# @nextui-org/button
|
||||
|
||||
## 2.2.9
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`e7ff673`](https://github.com/nextui-org/nextui/commit/e7ff6730d7e891f1e9e3ca232b1faaebc5aedef2)]:
|
||||
- @nextui-org/react-utils@2.1.3
|
||||
- @nextui-org/ripple@2.2.7
|
||||
- @nextui-org/spinner@2.2.6
|
||||
|
||||
## 2.2.8
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nextui-org/button",
|
||||
"version": "2.2.8",
|
||||
"version": "2.2.9",
|
||||
"description": "Buttons allow users to perform actions and choose with a single tap.",
|
||||
"keywords": [
|
||||
"button"
|
||||
|
||||
@ -1,5 +1,14 @@
|
||||
# @nextui-org/calendar
|
||||
|
||||
## 2.2.9
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`e7ff673`](https://github.com/nextui-org/nextui/commit/e7ff6730d7e891f1e9e3ca232b1faaebc5aedef2)]:
|
||||
- @nextui-org/react-utils@2.1.3
|
||||
- @nextui-org/button@2.2.9
|
||||
- @nextui-org/framer-utils@2.1.6
|
||||
|
||||
## 2.2.8
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nextui-org/calendar",
|
||||
"version": "2.2.8",
|
||||
"version": "2.2.9",
|
||||
"description": "A calendar displays one or more date grids and allows users to select a single date.",
|
||||
"keywords": [
|
||||
"calendar"
|
||||
|
||||
@ -1,5 +1,13 @@
|
||||
# @nextui-org/card
|
||||
|
||||
## 2.2.9
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`e7ff673`](https://github.com/nextui-org/nextui/commit/e7ff6730d7e891f1e9e3ca232b1faaebc5aedef2)]:
|
||||
- @nextui-org/react-utils@2.1.3
|
||||
- @nextui-org/ripple@2.2.7
|
||||
|
||||
## 2.2.8
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nextui-org/card",
|
||||
"version": "2.2.8",
|
||||
"version": "2.2.9",
|
||||
"description": "Card is a container for text, photos, and actions in the context of a single subject.",
|
||||
"keywords": [
|
||||
"card"
|
||||
|
||||
@ -1,5 +1,13 @@
|
||||
# @nextui-org/checkbox
|
||||
|
||||
## 2.3.8
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`e7ff673`](https://github.com/nextui-org/nextui/commit/e7ff6730d7e891f1e9e3ca232b1faaebc5aedef2)]:
|
||||
- @nextui-org/react-utils@2.1.3
|
||||
- @nextui-org/form@2.1.8
|
||||
|
||||
## 2.3.7
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nextui-org/checkbox",
|
||||
"version": "2.3.7",
|
||||
"version": "2.3.8",
|
||||
"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,5 +1,12 @@
|
||||
# @nextui-org/chip
|
||||
|
||||
## 2.2.6
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`e7ff673`](https://github.com/nextui-org/nextui/commit/e7ff6730d7e891f1e9e3ca232b1faaebc5aedef2)]:
|
||||
- @nextui-org/react-utils@2.1.3
|
||||
|
||||
## 2.2.5
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nextui-org/chip",
|
||||
"version": "2.2.5",
|
||||
"version": "2.2.6",
|
||||
"description": "Chips help people enter information, make selections, filter content, or trigger actions.",
|
||||
"keywords": [
|
||||
"chip"
|
||||
|
||||
@ -1,5 +1,13 @@
|
||||
# @nextui-org/code
|
||||
|
||||
## 2.2.6
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`e7ff673`](https://github.com/nextui-org/nextui/commit/e7ff6730d7e891f1e9e3ca232b1faaebc5aedef2)]:
|
||||
- @nextui-org/react-utils@2.1.3
|
||||
- @nextui-org/system-rsc@2.3.5
|
||||
|
||||
## 2.2.5
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nextui-org/code",
|
||||
"version": "2.2.5",
|
||||
"version": "2.2.6",
|
||||
"description": "Code is a component used to display inline code.",
|
||||
"keywords": [
|
||||
"code"
|
||||
|
||||
@ -1,5 +1,13 @@
|
||||
# @nextui-org/date-input
|
||||
|
||||
## 2.3.8
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`e7ff673`](https://github.com/nextui-org/nextui/commit/e7ff6730d7e891f1e9e3ca232b1faaebc5aedef2)]:
|
||||
- @nextui-org/react-utils@2.1.3
|
||||
- @nextui-org/form@2.1.8
|
||||
|
||||
## 2.3.7
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nextui-org/date-input",
|
||||
"version": "2.3.7",
|
||||
"version": "2.3.8",
|
||||
"description": "A date input allows users to enter and edit date and time values using a keyboard.",
|
||||
"keywords": [
|
||||
"date-field"
|
||||
|
||||
@ -1,5 +1,18 @@
|
||||
# @nextui-org/date-picker
|
||||
|
||||
## 2.3.9
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`33e0418`](https://github.com/nextui-org/nextui/commit/33e0418d08c29f829b00ee3bc41972dfce6a3370), [`e7ff673`](https://github.com/nextui-org/nextui/commit/e7ff6730d7e891f1e9e3ca232b1faaebc5aedef2), [`fb46df2`](https://github.com/nextui-org/nextui/commit/fb46df2430f95cddef0c25fce4639c2078b34f62)]:
|
||||
- @nextui-org/popover@2.3.9
|
||||
- @nextui-org/react-utils@2.1.3
|
||||
- @nextui-org/button@2.2.9
|
||||
- @nextui-org/calendar@2.2.9
|
||||
- @nextui-org/date-input@2.3.8
|
||||
- @nextui-org/form@2.1.8
|
||||
- @nextui-org/aria-utils@2.2.7
|
||||
|
||||
## 2.3.8
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nextui-org/date-picker",
|
||||
"version": "2.3.8",
|
||||
"version": "2.3.9",
|
||||
"description": "A date picker combines a DateInput and a Calendar popover to allow users to enter or select a date and time value.",
|
||||
"keywords": [
|
||||
"date-picker"
|
||||
|
||||
@ -1,5 +1,16 @@
|
||||
# @nextui-org/drawer
|
||||
|
||||
## 2.2.7
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#4438](https://github.com/nextui-org/nextui/pull/4438) [`07780a7`](https://github.com/nextui-org/nextui/commit/07780a75a2747405e16af99c1692aef496f54175) Thanks [@wingkwong](https://github.com/wingkwong)! - use top-level type-only import instead of inline type specifiers
|
||||
|
||||
- Updated dependencies [[`e7ff673`](https://github.com/nextui-org/nextui/commit/e7ff6730d7e891f1e9e3ca232b1faaebc5aedef2)]:
|
||||
- @nextui-org/react-utils@2.1.3
|
||||
- @nextui-org/modal@2.2.7
|
||||
- @nextui-org/framer-utils@2.1.6
|
||||
|
||||
## 2.2.6
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nextui-org/drawer",
|
||||
"version": "2.2.6",
|
||||
"version": "2.2.7",
|
||||
"description": "Used to render a content that slides in from the side of the screen.",
|
||||
"keywords": [
|
||||
"drawer"
|
||||
|
||||
@ -1,14 +1,12 @@
|
||||
import {
|
||||
ModalHeader,
|
||||
ModalBody,
|
||||
ModalFooter,
|
||||
ModalContent,
|
||||
type ModalContentProps,
|
||||
type ModalHeaderProps,
|
||||
type ModalBodyProps,
|
||||
type ModalFooterProps,
|
||||
import type {
|
||||
ModalContentProps,
|
||||
ModalHeaderProps,
|
||||
ModalBodyProps,
|
||||
ModalFooterProps,
|
||||
} from "@nextui-org/modal";
|
||||
|
||||
import {ModalHeader, ModalBody, ModalFooter, ModalContent} from "@nextui-org/modal";
|
||||
|
||||
import Drawer from "./drawer";
|
||||
|
||||
// export types
|
||||
|
||||
@ -1,5 +1,17 @@
|
||||
# @nextui-org/dropdown
|
||||
|
||||
## 2.3.9
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#4498](https://github.com/nextui-org/nextui/pull/4498) [`33e0418`](https://github.com/nextui-org/nextui/commit/33e0418d08c29f829b00ee3bc41972dfce6a3370) Thanks [@ryo-manba](https://github.com/ryo-manba)! - Fix incorrect initial popover animation and arrow display (#4466)
|
||||
|
||||
- Updated dependencies [[`33e0418`](https://github.com/nextui-org/nextui/commit/33e0418d08c29f829b00ee3bc41972dfce6a3370), [`e7ff673`](https://github.com/nextui-org/nextui/commit/e7ff6730d7e891f1e9e3ca232b1faaebc5aedef2), [`fb46df2`](https://github.com/nextui-org/nextui/commit/fb46df2430f95cddef0c25fce4639c2078b34f62)]:
|
||||
- @nextui-org/popover@2.3.9
|
||||
- @nextui-org/react-utils@2.1.3
|
||||
- @nextui-org/menu@2.2.9
|
||||
- @nextui-org/aria-utils@2.2.7
|
||||
|
||||
## 2.3.8
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nextui-org/dropdown",
|
||||
"version": "2.3.8",
|
||||
"version": "2.3.9",
|
||||
"description": "A dropdown displays a list of actions or options that a user can choose.",
|
||||
"keywords": [
|
||||
"dropdown"
|
||||
@ -48,7 +48,6 @@
|
||||
"@nextui-org/shared-utils": "workspace:*",
|
||||
"@react-aria/focus": "3.19.0",
|
||||
"@react-aria/menu": "3.16.0",
|
||||
"@react-aria/overlays": "3.24.0",
|
||||
"@react-aria/utils": "3.26.0",
|
||||
"@react-stately/menu": "3.9.0",
|
||||
"@react-types/menu": "3.9.13"
|
||||
|
||||
@ -9,12 +9,11 @@ import {useMenuTrigger} from "@react-aria/menu";
|
||||
import {dropdown} from "@nextui-org/theme";
|
||||
import {clsx} from "@nextui-org/shared-utils";
|
||||
import {ReactRef, mergeRefs} from "@nextui-org/react-utils";
|
||||
import {ariaShouldCloseOnInteractOutside, toReactAriaPlacement} from "@nextui-org/aria-utils";
|
||||
import {ariaShouldCloseOnInteractOutside} from "@nextui-org/aria-utils";
|
||||
import {useMemo, useRef} from "react";
|
||||
import {mergeProps} from "@react-aria/utils";
|
||||
import {MenuProps} from "@nextui-org/menu";
|
||||
import {CollectionElement} from "@react-types/shared";
|
||||
import {useOverlayPosition} from "@react-aria/overlays";
|
||||
|
||||
interface Props extends HTMLNextUIProps<"div"> {
|
||||
/**
|
||||
@ -78,8 +77,6 @@ const getCloseOnSelect = <T extends object>(
|
||||
return props?.closeOnSelect;
|
||||
};
|
||||
|
||||
const DEFAULT_PLACEMENT = "bottom";
|
||||
|
||||
export function useDropdown(props: UseDropdownProps): UseDropdownReturn {
|
||||
const globalContext = useProviderContext();
|
||||
|
||||
@ -92,17 +89,13 @@ export function useDropdown(props: UseDropdownProps): UseDropdownReturn {
|
||||
isDisabled,
|
||||
type = "menu",
|
||||
trigger = "press",
|
||||
placement: placementProp = DEFAULT_PLACEMENT,
|
||||
placement = "bottom",
|
||||
closeOnSelect = true,
|
||||
shouldBlockScroll = true,
|
||||
classNames: classNamesProp,
|
||||
disableAnimation = globalContext?.disableAnimation ?? false,
|
||||
onClose,
|
||||
className,
|
||||
containerPadding = 12,
|
||||
offset = 7,
|
||||
crossOffset = 0,
|
||||
shouldFlip = true,
|
||||
...otherProps
|
||||
} = props;
|
||||
|
||||
@ -139,17 +132,6 @@ export function useDropdown(props: UseDropdownProps): UseDropdownReturn {
|
||||
[className],
|
||||
);
|
||||
|
||||
const {placement} = useOverlayPosition({
|
||||
isOpen: state.isOpen,
|
||||
targetRef: triggerRef,
|
||||
overlayRef: popoverRef,
|
||||
placement: toReactAriaPlacement(placementProp),
|
||||
offset,
|
||||
crossOffset,
|
||||
shouldFlip,
|
||||
containerPadding,
|
||||
});
|
||||
|
||||
const onMenuAction = (menuCloseOnSelect?: boolean) => {
|
||||
if (menuCloseOnSelect !== undefined && !menuCloseOnSelect) {
|
||||
return;
|
||||
@ -164,7 +146,7 @@ export function useDropdown(props: UseDropdownProps): UseDropdownReturn {
|
||||
|
||||
return {
|
||||
state,
|
||||
placement: placement || DEFAULT_PLACEMENT,
|
||||
placement,
|
||||
ref: popoverRef,
|
||||
disableAnimation,
|
||||
shouldBlockScroll,
|
||||
|
||||
@ -835,3 +835,28 @@ export const WithShouldBlockScroll = {
|
||||
...defaultProps,
|
||||
},
|
||||
};
|
||||
|
||||
export const Placements = {
|
||||
args: {
|
||||
...defaultProps,
|
||||
},
|
||||
render: (args) => (
|
||||
<div className="inline-grid grid-cols-3 gap-4">
|
||||
<Template {...args} label="Top Start" placement="top-start" />
|
||||
<Template {...args} label="Top" placement="top" />
|
||||
<Template {...args} label="Top End" placement="top-end" />
|
||||
|
||||
<Template {...args} label="Bottom Start" placement="bottom-start" />
|
||||
<Template {...args} label="Bottom" placement="bottom" />
|
||||
<Template {...args} label="Bottom End" placement="bottom-end" />
|
||||
|
||||
<Template {...args} label="Right Start" placement="right-start" />
|
||||
<Template {...args} label="Right" placement="right" />
|
||||
<Template {...args} label="Right End" placement="right-end" />
|
||||
|
||||
<Template {...args} label="Left Start" placement="left-start" />
|
||||
<Template {...args} label="Left" placement="left" />
|
||||
<Template {...args} label="Left End" placement="left-end" />
|
||||
</div>
|
||||
),
|
||||
};
|
||||
|
||||
@ -1,5 +1,14 @@
|
||||
# @nextui-org/form
|
||||
|
||||
## 2.1.8
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`a83388a`](https://github.com/nextui-org/nextui/commit/a83388aaf4521f0ed8dfed99a54998156df1868b), [`e7ff673`](https://github.com/nextui-org/nextui/commit/e7ff6730d7e891f1e9e3ca232b1faaebc5aedef2)]:
|
||||
- @nextui-org/theme@2.4.5
|
||||
- @nextui-org/react-utils@2.1.3
|
||||
- @nextui-org/system@2.4.6
|
||||
|
||||
## 2.1.7
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nextui-org/form",
|
||||
"version": "2.1.7",
|
||||
"version": "2.1.8",
|
||||
"description": "A form is a group of inputs that allows users submit data to a server and supports field validation errors.",
|
||||
"keywords": [
|
||||
"form"
|
||||
|
||||
@ -1,5 +1,13 @@
|
||||
# @nextui-org/image
|
||||
|
||||
## 2.2.5
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`5d0fc9f`](https://github.com/nextui-org/nextui/commit/5d0fc9f786ef522d74333f2dc9384626fd8cad3b), [`ef916ea`](https://github.com/nextui-org/nextui/commit/ef916ead525414d7b62c01f26ae5580fd9ba7f14), [`e7ff673`](https://github.com/nextui-org/nextui/commit/e7ff6730d7e891f1e9e3ca232b1faaebc5aedef2), [`e7ff673`](https://github.com/nextui-org/nextui/commit/e7ff6730d7e891f1e9e3ca232b1faaebc5aedef2)]:
|
||||
- @nextui-org/use-image@2.1.2
|
||||
- @nextui-org/react-utils@2.1.3
|
||||
|
||||
## 2.2.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nextui-org/image",
|
||||
"version": "2.2.4",
|
||||
"version": "2.2.5",
|
||||
"description": "A simple image component",
|
||||
"keywords": [
|
||||
"image"
|
||||
|
||||
@ -1,5 +1,13 @@
|
||||
# @nextui-org/input-otp
|
||||
|
||||
## 2.1.8
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`e7ff673`](https://github.com/nextui-org/nextui/commit/e7ff6730d7e891f1e9e3ca232b1faaebc5aedef2)]:
|
||||
- @nextui-org/react-utils@2.1.3
|
||||
- @nextui-org/form@2.1.8
|
||||
|
||||
## 2.1.7
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nextui-org/input-otp",
|
||||
"version": "2.1.7",
|
||||
"version": "2.1.8",
|
||||
"description": "",
|
||||
"keywords": [
|
||||
"input-otp"
|
||||
|
||||
@ -1,5 +1,13 @@
|
||||
# @nextui-org/input
|
||||
|
||||
## 2.4.8
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`e7ff673`](https://github.com/nextui-org/nextui/commit/e7ff6730d7e891f1e9e3ca232b1faaebc5aedef2)]:
|
||||
- @nextui-org/react-utils@2.1.3
|
||||
- @nextui-org/form@2.1.8
|
||||
|
||||
## 2.4.7
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nextui-org/input",
|
||||
"version": "2.4.7",
|
||||
"version": "2.4.8",
|
||||
"description": "The input component is designed for capturing user input within a text field.",
|
||||
"keywords": [
|
||||
"input"
|
||||
|
||||
@ -1,5 +1,13 @@
|
||||
# @nextui-org/kbd
|
||||
|
||||
## 2.2.6
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`e7ff673`](https://github.com/nextui-org/nextui/commit/e7ff6730d7e891f1e9e3ca232b1faaebc5aedef2)]:
|
||||
- @nextui-org/react-utils@2.1.3
|
||||
- @nextui-org/system-rsc@2.3.5
|
||||
|
||||
## 2.2.5
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nextui-org/kbd",
|
||||
"version": "2.2.5",
|
||||
"version": "2.2.6",
|
||||
"description": "The keyboard key components indicates which key or set of keys used to execute a specificv action",
|
||||
"keywords": [
|
||||
"kbd"
|
||||
|
||||
@ -1,5 +1,13 @@
|
||||
# @nextui-org/link
|
||||
|
||||
## 2.2.7
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`b2e924f`](https://github.com/nextui-org/nextui/commit/b2e924fe19f4c6620ec0a0e464b9b35386ed2319), [`e7ff673`](https://github.com/nextui-org/nextui/commit/e7ff6730d7e891f1e9e3ca232b1faaebc5aedef2)]:
|
||||
- @nextui-org/use-aria-link@2.2.5
|
||||
- @nextui-org/react-utils@2.1.3
|
||||
|
||||
## 2.2.6
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nextui-org/link",
|
||||
"version": "2.2.6",
|
||||
"version": "2.2.7",
|
||||
"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,5 +1,18 @@
|
||||
# @nextui-org/listbox
|
||||
|
||||
## 2.3.9
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#4463](https://github.com/nextui-org/nextui/pull/4463) [`d92468a`](https://github.com/nextui-org/nextui/commit/d92468aa1e35d5022c071b5d2674f5bfb6408001) Thanks [@wingkwong](https://github.com/wingkwong)! - bump `@tanstack/react-virtual` to support react 19 peer dep
|
||||
|
||||
- [#4462](https://github.com/nextui-org/nextui/pull/4462) [`16c57ec`](https://github.com/nextui-org/nextui/commit/16c57ece6467d755645f109b8de810c9063e5665) Thanks [@vinroger](https://github.com/vinroger)! - add support for dataset with section, add support for scrollshadow
|
||||
|
||||
- Updated dependencies [[`e7ff673`](https://github.com/nextui-org/nextui/commit/e7ff6730d7e891f1e9e3ca232b1faaebc5aedef2)]:
|
||||
- @nextui-org/react-utils@2.1.3
|
||||
- @nextui-org/divider@2.2.5
|
||||
- @nextui-org/aria-utils@2.2.7
|
||||
|
||||
## 2.3.8
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nextui-org/listbox",
|
||||
"version": "2.3.8",
|
||||
"version": "2.3.9",
|
||||
"description": "A listbox displays a list of options and allows a user to select one or more of them.",
|
||||
"keywords": [
|
||||
"listbox"
|
||||
@ -45,7 +45,7 @@
|
||||
"@nextui-org/react-utils": "workspace:*",
|
||||
"@nextui-org/shared-utils": "workspace:*",
|
||||
"@nextui-org/use-is-mobile": "workspace:*",
|
||||
"@tanstack/react-virtual": "3.10.9",
|
||||
"@tanstack/react-virtual": "3.11.2",
|
||||
"@react-aria/utils": "3.26.0",
|
||||
"@react-aria/listbox": "3.13.6",
|
||||
"@react-stately/list": "3.11.1",
|
||||
|
||||
@ -1,7 +1,10 @@
|
||||
import {useRef} from "react";
|
||||
import {useMemo, useRef, useState} from "react";
|
||||
import {mergeProps} from "@react-aria/utils";
|
||||
import {useVirtualizer} from "@tanstack/react-virtual";
|
||||
import {useVirtualizer, VirtualItem} from "@tanstack/react-virtual";
|
||||
import {isEmpty} from "@nextui-org/shared-utils";
|
||||
import {Node} from "@react-types/shared";
|
||||
import {ScrollShadowProps, useScrollShadow} from "@nextui-org/scroll-shadow";
|
||||
import {filterDOMProps} from "@nextui-org/react-utils";
|
||||
|
||||
import ListboxItem from "./listbox-item";
|
||||
import ListboxSection from "./listbox-section";
|
||||
@ -11,8 +14,50 @@ import {UseListboxReturn} from "./use-listbox";
|
||||
interface Props extends UseListboxReturn {
|
||||
isVirtualized?: boolean;
|
||||
virtualization?: VirtualizationProps;
|
||||
/* Here in virtualized listbox, scroll shadow needs custom implementation. Hence this is the only way to pass props to scroll shadow */
|
||||
scrollShadowProps?: Partial<ScrollShadowProps>;
|
||||
}
|
||||
|
||||
const getItemSizesForCollection = (collection: Node<object>[], itemHeight: number) => {
|
||||
const sizes: number[] = [];
|
||||
|
||||
for (const item of collection) {
|
||||
if (item.type === "section") {
|
||||
/* +1 for the section header */
|
||||
sizes.push(([...item.childNodes].length + 1) * itemHeight);
|
||||
} else {
|
||||
sizes.push(itemHeight);
|
||||
}
|
||||
}
|
||||
|
||||
return sizes;
|
||||
};
|
||||
|
||||
const getScrollState = (element: HTMLDivElement | null) => {
|
||||
if (
|
||||
!element ||
|
||||
element.scrollTop === undefined ||
|
||||
element.clientHeight === undefined ||
|
||||
element.scrollHeight === undefined
|
||||
) {
|
||||
return {
|
||||
isTop: false,
|
||||
isBottom: false,
|
||||
isMiddle: false,
|
||||
};
|
||||
}
|
||||
|
||||
const isAtTop = element.scrollTop === 0;
|
||||
const isAtBottom = Math.ceil(element.scrollTop + element.clientHeight) >= element.scrollHeight;
|
||||
const isInMiddle = !isAtTop && !isAtBottom;
|
||||
|
||||
return {
|
||||
isTop: isAtTop,
|
||||
isBottom: isAtBottom,
|
||||
isMiddle: isInMiddle,
|
||||
};
|
||||
};
|
||||
|
||||
const VirtualizedListbox = (props: Props) => {
|
||||
const {
|
||||
Component,
|
||||
@ -29,6 +74,7 @@ const VirtualizedListbox = (props: Props) => {
|
||||
disableAnimation,
|
||||
getEmptyContentProps,
|
||||
getListProps,
|
||||
scrollShadowProps,
|
||||
} = props;
|
||||
|
||||
const {virtualization} = props;
|
||||
@ -45,24 +91,29 @@ const VirtualizedListbox = (props: Props) => {
|
||||
|
||||
const listHeight = Math.min(maxListboxHeight, itemHeight * state.collection.size);
|
||||
|
||||
const parentRef = useRef(null);
|
||||
const parentRef = useRef<HTMLDivElement>(null);
|
||||
const itemSizes = useMemo(
|
||||
() => getItemSizesForCollection([...state.collection], itemHeight),
|
||||
[state.collection, itemHeight],
|
||||
);
|
||||
|
||||
const rowVirtualizer = useVirtualizer({
|
||||
count: state.collection.size,
|
||||
count: [...state.collection].length,
|
||||
getScrollElement: () => parentRef.current,
|
||||
estimateSize: () => itemHeight,
|
||||
estimateSize: (i) => itemSizes[i],
|
||||
});
|
||||
|
||||
const virtualItems = rowVirtualizer.getVirtualItems();
|
||||
|
||||
const renderRow = ({
|
||||
index,
|
||||
style: virtualizerStyle,
|
||||
}: {
|
||||
index: number;
|
||||
style: React.CSSProperties;
|
||||
}) => {
|
||||
const item = [...state.collection][index];
|
||||
/* Here we need the base props for scroll shadow, contains the className (scrollbar-hide and scrollshadow config based on the user inputs on select props) */
|
||||
const {getBaseProps: getBasePropsScrollShadow} = useScrollShadow({...scrollShadowProps});
|
||||
|
||||
const renderRow = (virtualItem: VirtualItem) => {
|
||||
const item = [...state.collection][virtualItem.index];
|
||||
|
||||
if (!item) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const itemProps = {
|
||||
color,
|
||||
@ -74,6 +125,15 @@ const VirtualizedListbox = (props: Props) => {
|
||||
...item.props,
|
||||
};
|
||||
|
||||
const virtualizerStyle = {
|
||||
position: "absolute" as const,
|
||||
top: 0,
|
||||
left: 0,
|
||||
width: "100%",
|
||||
height: `${virtualItem.size}px`,
|
||||
transform: `translateY(${virtualItem.start}px)`,
|
||||
};
|
||||
|
||||
if (item.type === "section") {
|
||||
return (
|
||||
<ListboxSection
|
||||
@ -102,6 +162,12 @@ const VirtualizedListbox = (props: Props) => {
|
||||
return listboxItem;
|
||||
};
|
||||
|
||||
const [scrollState, setScrollState] = useState({
|
||||
isTop: false,
|
||||
isBottom: true,
|
||||
isMiddle: false,
|
||||
});
|
||||
|
||||
const content = (
|
||||
<Component {...getListProps()}>
|
||||
{!state.collection.size && !hideEmptyContent && (
|
||||
@ -110,11 +176,18 @@ const VirtualizedListbox = (props: Props) => {
|
||||
</li>
|
||||
)}
|
||||
<div
|
||||
{...filterDOMProps(getBasePropsScrollShadow())}
|
||||
ref={parentRef}
|
||||
data-bottom-scroll={scrollState.isTop}
|
||||
data-top-bottom-scroll={scrollState.isMiddle}
|
||||
data-top-scroll={scrollState.isBottom}
|
||||
style={{
|
||||
height: maxListboxHeight,
|
||||
overflow: "auto",
|
||||
}}
|
||||
onScroll={(e) => {
|
||||
setScrollState(getScrollState(e.target as HTMLDivElement));
|
||||
}}
|
||||
>
|
||||
{listHeight > 0 && itemHeight > 0 && (
|
||||
<div
|
||||
@ -124,19 +197,7 @@ const VirtualizedListbox = (props: Props) => {
|
||||
position: "relative",
|
||||
}}
|
||||
>
|
||||
{virtualItems.map((virtualItem) =>
|
||||
renderRow({
|
||||
index: virtualItem.index,
|
||||
style: {
|
||||
position: "absolute",
|
||||
top: 0,
|
||||
left: 0,
|
||||
width: "100%",
|
||||
height: `${virtualItem.size}px`,
|
||||
transform: `translateY(${virtualItem.start}px)`,
|
||||
},
|
||||
}),
|
||||
)}
|
||||
{virtualItems.map((virtualItem) => renderRow(virtualItem))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@ -1,5 +1,14 @@
|
||||
# @nextui-org/menu
|
||||
|
||||
## 2.2.9
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`e7ff673`](https://github.com/nextui-org/nextui/commit/e7ff6730d7e891f1e9e3ca232b1faaebc5aedef2)]:
|
||||
- @nextui-org/react-utils@2.1.3
|
||||
- @nextui-org/divider@2.2.5
|
||||
- @nextui-org/aria-utils@2.2.7
|
||||
|
||||
## 2.2.8
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nextui-org/menu",
|
||||
"version": "2.2.8",
|
||||
"version": "2.2.9",
|
||||
"description": "A menu displays a list of options and allows a user to select one or more of them.",
|
||||
"keywords": [
|
||||
"menu"
|
||||
|
||||
@ -1,5 +1,13 @@
|
||||
# @nextui-org/modal
|
||||
|
||||
## 2.2.7
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`e7ff673`](https://github.com/nextui-org/nextui/commit/e7ff6730d7e891f1e9e3ca232b1faaebc5aedef2)]:
|
||||
- @nextui-org/react-utils@2.1.3
|
||||
- @nextui-org/framer-utils@2.1.6
|
||||
|
||||
## 2.2.6
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nextui-org/modal",
|
||||
"version": "2.2.6",
|
||||
"version": "2.2.7",
|
||||
"description": "Displays a dialog with a custom content that requires attention or provides additional information.",
|
||||
"keywords": [
|
||||
"modal"
|
||||
|
||||
@ -1,5 +1,15 @@
|
||||
# @nextui-org/navbar
|
||||
|
||||
## 2.2.8
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#4490](https://github.com/nextui-org/nextui/pull/4490) [`a43b156`](https://github.com/nextui-org/nextui/commit/a43b156801aef88b6eaa7bff0b670f7287499dde) Thanks [@Peterl561](https://github.com/Peterl561)! - fixed NavbarMenu applying Overlay while closed
|
||||
|
||||
- Updated dependencies [[`e7ff673`](https://github.com/nextui-org/nextui/commit/e7ff6730d7e891f1e9e3ca232b1faaebc5aedef2)]:
|
||||
- @nextui-org/react-utils@2.1.3
|
||||
- @nextui-org/framer-utils@2.1.6
|
||||
|
||||
## 2.2.7
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nextui-org/navbar",
|
||||
"version": "2.2.7",
|
||||
"version": "2.2.8",
|
||||
"description": "A responsive navigation header positioned on top side of your page that includes support for branding, links, navigation, collapse and more.",
|
||||
"keywords": [
|
||||
"navbar"
|
||||
|
||||
@ -4,6 +4,7 @@ import {clsx, dataAttr} from "@nextui-org/shared-utils";
|
||||
import {AnimatePresence, HTMLMotionProps, LazyMotion, m} from "framer-motion";
|
||||
import {mergeProps} from "@react-aria/utils";
|
||||
import {Overlay} from "@react-aria/overlays";
|
||||
import React from "react";
|
||||
|
||||
import {menuVariants} from "./navbar-menu-transitions";
|
||||
import {useNavbarContext} from "./navbar-context";
|
||||
@ -31,47 +32,54 @@ const NavbarMenu = forwardRef<"ul", NavbarMenuProps>((props, ref) => {
|
||||
|
||||
const styles = clsx(classNames?.menu, className);
|
||||
|
||||
// only apply overlay when menu is open
|
||||
const OverlayComponent = isMenuOpen ? Overlay : React.Fragment;
|
||||
|
||||
const contents = disableAnimation ? (
|
||||
<ul
|
||||
ref={domRef}
|
||||
className={slots.menu?.({class: styles})}
|
||||
data-open={dataAttr(isMenuOpen)}
|
||||
style={{
|
||||
// @ts-expect-error
|
||||
"--navbar-height": typeof height === "number" ? `${height}px` : height,
|
||||
}}
|
||||
{...otherProps}
|
||||
>
|
||||
{children}
|
||||
</ul>
|
||||
<OverlayComponent portalContainer={portalContainer}>
|
||||
<ul
|
||||
ref={domRef}
|
||||
className={slots.menu?.({class: styles})}
|
||||
data-open={dataAttr(isMenuOpen)}
|
||||
style={{
|
||||
// @ts-expect-error
|
||||
"--navbar-height": typeof height === "number" ? `${height}px` : height,
|
||||
}}
|
||||
{...otherProps}
|
||||
>
|
||||
{children}
|
||||
</ul>
|
||||
</OverlayComponent>
|
||||
) : (
|
||||
<AnimatePresence mode="wait">
|
||||
{isMenuOpen ? (
|
||||
<LazyMotion features={domAnimation}>
|
||||
<m.ul
|
||||
ref={domRef}
|
||||
layoutScroll
|
||||
animate="enter"
|
||||
className={slots.menu?.({class: styles})}
|
||||
data-open={dataAttr(isMenuOpen)}
|
||||
exit="exit"
|
||||
initial="exit"
|
||||
style={{
|
||||
// @ts-expect-error
|
||||
"--navbar-height": typeof height === "number" ? `${height}px` : height,
|
||||
...style,
|
||||
}}
|
||||
variants={menuVariants}
|
||||
{...mergeProps(motionProps, otherProps)}
|
||||
>
|
||||
{children}
|
||||
</m.ul>
|
||||
</LazyMotion>
|
||||
<Overlay portalContainer={portalContainer}>
|
||||
<LazyMotion features={domAnimation}>
|
||||
<m.ul
|
||||
ref={domRef}
|
||||
layoutScroll
|
||||
animate="enter"
|
||||
className={slots.menu?.({class: styles})}
|
||||
data-open={dataAttr(isMenuOpen)}
|
||||
exit="exit"
|
||||
initial="exit"
|
||||
style={{
|
||||
// @ts-expect-error
|
||||
"--navbar-height": typeof height === "number" ? `${height}px` : height,
|
||||
...style,
|
||||
}}
|
||||
variants={menuVariants}
|
||||
{...mergeProps(motionProps, otherProps)}
|
||||
>
|
||||
{children}
|
||||
</m.ul>
|
||||
</LazyMotion>
|
||||
</Overlay>
|
||||
) : null}
|
||||
</AnimatePresence>
|
||||
);
|
||||
|
||||
return <Overlay portalContainer={portalContainer}>{contents}</Overlay>;
|
||||
return contents;
|
||||
});
|
||||
|
||||
NavbarMenu.displayName = "NextUI.NavbarMenu";
|
||||
|
||||
@ -1,5 +1,12 @@
|
||||
# @nextui-org/pagination
|
||||
|
||||
## 2.2.8
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`e7ff673`](https://github.com/nextui-org/nextui/commit/e7ff6730d7e891f1e9e3ca232b1faaebc5aedef2)]:
|
||||
- @nextui-org/react-utils@2.1.3
|
||||
|
||||
## 2.2.7
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nextui-org/pagination",
|
||||
"version": "2.2.7",
|
||||
"version": "2.2.8",
|
||||
"description": "The Pagination component allows you to display active page and navigate between multiple pages.",
|
||||
"keywords": [
|
||||
"pagination"
|
||||
|
||||
@ -1,5 +1,19 @@
|
||||
# @nextui-org/popover
|
||||
|
||||
## 2.3.9
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#4498](https://github.com/nextui-org/nextui/pull/4498) [`33e0418`](https://github.com/nextui-org/nextui/commit/33e0418d08c29f829b00ee3bc41972dfce6a3370) Thanks [@ryo-manba](https://github.com/ryo-manba)! - Fix incorrect initial popover animation and arrow display (#4466)
|
||||
|
||||
- [#4460](https://github.com/nextui-org/nextui/pull/4460) [`fb46df2`](https://github.com/nextui-org/nextui/commit/fb46df2430f95cddef0c25fce4639c2078b34f62) Thanks [@ryo-manba](https://github.com/ryo-manba)! - Fix initial animation direction to match fallback placement (#4290)
|
||||
|
||||
- Updated dependencies [[`e7ff673`](https://github.com/nextui-org/nextui/commit/e7ff6730d7e891f1e9e3ca232b1faaebc5aedef2)]:
|
||||
- @nextui-org/react-utils@2.1.3
|
||||
- @nextui-org/button@2.2.9
|
||||
- @nextui-org/aria-utils@2.2.7
|
||||
- @nextui-org/framer-utils@2.1.6
|
||||
|
||||
## 2.3.8
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nextui-org/popover",
|
||||
"version": "2.3.8",
|
||||
"version": "2.3.9",
|
||||
"description": "A popover is an overlay element positioned relative to a trigger.",
|
||||
"keywords": [
|
||||
"popover"
|
||||
|
||||
@ -58,7 +58,7 @@ const FreeSoloPopoverWrapper = forwardRef<"div", FreeSoloPopoverWrapperProps>(
|
||||
// @ts-ignore
|
||||
transformOrigin,
|
||||
};
|
||||
} else {
|
||||
} else if (placement) {
|
||||
style = {
|
||||
...style,
|
||||
...getTransformOrigins(placement === "center" ? "top" : placement),
|
||||
|
||||
@ -80,6 +80,9 @@ const PopoverContent = (props: PopoverContentProps) => {
|
||||
);
|
||||
}, [backdrop, disableAnimation, getBackdropProps]);
|
||||
|
||||
const style = placement
|
||||
? getTransformOrigins(placement === "center" ? "top" : placement)
|
||||
: undefined;
|
||||
const contents = (
|
||||
<>
|
||||
{disableAnimation ? (
|
||||
@ -90,9 +93,7 @@ const PopoverContent = (props: PopoverContentProps) => {
|
||||
animate="enter"
|
||||
exit="exit"
|
||||
initial="initial"
|
||||
style={{
|
||||
...getTransformOrigins(placement === "center" ? "top" : placement),
|
||||
}}
|
||||
style={style}
|
||||
variants={TRANSITION_VARIANTS.scaleSpringOpacity}
|
||||
{...motionProps}
|
||||
>
|
||||
|
||||
@ -8,13 +8,14 @@ import {OverlayTriggerState, useOverlayTriggerState} from "@react-stately/overla
|
||||
import {useFocusRing} from "@react-aria/focus";
|
||||
import {ariaHideOutside, useOverlayTrigger, usePreventScroll} from "@react-aria/overlays";
|
||||
import {OverlayTriggerProps} from "@react-types/overlays";
|
||||
import {getShouldUseAxisPlacement} from "@nextui-org/aria-utils";
|
||||
import {
|
||||
HTMLNextUIProps,
|
||||
mapPropsVariants,
|
||||
PropGetter,
|
||||
useProviderContext,
|
||||
} from "@nextui-org/system";
|
||||
import {getArrowPlacement, getShouldUseAxisPlacement} from "@nextui-org/aria-utils";
|
||||
import {getArrowPlacement} from "@nextui-org/aria-utils";
|
||||
import {popover} from "@nextui-org/theme";
|
||||
import {mergeProps, mergeRefs} from "@react-aria/utils";
|
||||
import {clsx, dataAttr, objectToDeps} from "@nextui-org/shared-utils";
|
||||
@ -81,6 +82,8 @@ export interface Props extends HTMLNextUIProps<"div"> {
|
||||
onClose?: () => void;
|
||||
}
|
||||
|
||||
const DEFAULT_PLACEMENT = "top";
|
||||
|
||||
export type UsePopoverProps = Props &
|
||||
Omit<ReactAriaPopoverProps, "triggerRef" | "popoverRef"> &
|
||||
OverlayTriggerProps &
|
||||
@ -110,7 +113,7 @@ export function usePopover(originalProps: UsePopoverProps) {
|
||||
portalContainer,
|
||||
updatePositionDeps,
|
||||
dialogProps: dialogPropsProp,
|
||||
placement: placementProp = "top",
|
||||
placement: placementProp = DEFAULT_PLACEMENT,
|
||||
triggerType = "dialog",
|
||||
showArrow = false,
|
||||
offset = 7,
|
||||
@ -176,6 +179,16 @@ export function usePopover(originalProps: UsePopoverProps) {
|
||||
state,
|
||||
);
|
||||
|
||||
const placement = useMemo(() => {
|
||||
// If ariaPlacement is null, popoverProps.style isn't set,
|
||||
// so we return null to avoid an incorrect animation value.
|
||||
if (!ariaPlacement) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return getShouldUseAxisPlacement(ariaPlacement, placementProp) ? ariaPlacement : placementProp;
|
||||
}, [ariaPlacement, placementProp]);
|
||||
|
||||
const {triggerProps} = useOverlayTrigger({type: triggerType}, state, triggerRef);
|
||||
|
||||
const {isFocusVisible, isFocused, focusProps} = useFocusRing();
|
||||
@ -208,7 +221,7 @@ export function usePopover(originalProps: UsePopoverProps) {
|
||||
"data-focus": dataAttr(isFocused),
|
||||
"data-arrow": dataAttr(showArrow),
|
||||
"data-focus-visible": dataAttr(isFocusVisible),
|
||||
"data-placement": getArrowPlacement(ariaPlacement || "top", placementProp),
|
||||
"data-placement": ariaPlacement ? getArrowPlacement(ariaPlacement, placementProp) : undefined,
|
||||
...mergeProps(focusProps, dialogPropsProp, props),
|
||||
className: slots.base({class: clsx(baseStyles)}),
|
||||
style: {
|
||||
@ -222,18 +235,10 @@ export function usePopover(originalProps: UsePopoverProps) {
|
||||
"data-slot": "content",
|
||||
"data-open": dataAttr(state.isOpen),
|
||||
"data-arrow": dataAttr(showArrow),
|
||||
"data-placement": getArrowPlacement(ariaPlacement || "top", placementProp),
|
||||
"data-placement": ariaPlacement ? getArrowPlacement(ariaPlacement, placementProp) : undefined,
|
||||
className: slots.content({class: clsx(classNames?.content, props.className)}),
|
||||
}),
|
||||
[slots, state.isOpen, showArrow, ariaPlacement, placementProp, classNames],
|
||||
);
|
||||
|
||||
const placement = useMemo(
|
||||
() =>
|
||||
getShouldUseAxisPlacement(ariaPlacement || "top", placementProp)
|
||||
? ariaPlacement || placementProp
|
||||
: placementProp,
|
||||
[ariaPlacement, placementProp],
|
||||
[slots, state.isOpen, showArrow, placement, placementProp, classNames, ariaPlacement],
|
||||
);
|
||||
|
||||
const onPress = useCallback(
|
||||
|
||||
@ -127,11 +127,11 @@ const content = (
|
||||
</PopoverContent>
|
||||
);
|
||||
|
||||
const Template = (args: PopoverProps) => {
|
||||
const Template = ({label = "Open Popover", ...args}: PopoverProps & {label: string}) => {
|
||||
return (
|
||||
<Popover {...args}>
|
||||
<PopoverTrigger>
|
||||
<Button>Open Popover</Button>
|
||||
<Button>{label}</Button>
|
||||
</PopoverTrigger>
|
||||
{content}
|
||||
</Popover>
|
||||
@ -581,6 +581,32 @@ export const CustomMotion = {
|
||||
},
|
||||
};
|
||||
|
||||
export const WithFallbackPlacements = {
|
||||
args: {
|
||||
...defaultProps,
|
||||
},
|
||||
render: (args) => (
|
||||
<div className="relative h-screen w-screen">
|
||||
<div className="absolute top-0 left-0 p-8 flex gap-4">
|
||||
<Template {...args} label="placement: top" placement="top" />
|
||||
<Template {...args} label="placement: bottom" placement="bottom" />
|
||||
</div>
|
||||
<div className="absolute bottom-0 left-0 p-8 flex gap-4">
|
||||
<Template {...args} label="placement: bottom" placement="bottom" />
|
||||
<Template {...args} label="placement: top" placement="top" />
|
||||
</div>
|
||||
<div className="absolute left-0 top-1/2 -translate-y-1/2 p-8 flex flex-col gap-4">
|
||||
<Template {...args} label="placement: left" placement="left" />
|
||||
<Template {...args} label="placement: right" placement="right" />
|
||||
</div>
|
||||
<div className="absolute right-0 top-1/2 -translate-y-1/2 p-8 flex flex-col gap-4">
|
||||
<Template {...args} label="placement: right" placement="right" />
|
||||
<Template {...args} label="placement: left" placement="left" />
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
};
|
||||
|
||||
export const WithShouldBlockScroll = {
|
||||
render: (args) => {
|
||||
return (
|
||||
|
||||
@ -1,5 +1,12 @@
|
||||
# @nextui-org/progress
|
||||
|
||||
## 2.2.6
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`e7ff673`](https://github.com/nextui-org/nextui/commit/e7ff6730d7e891f1e9e3ca232b1faaebc5aedef2)]:
|
||||
- @nextui-org/react-utils@2.1.3
|
||||
|
||||
## 2.2.5
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nextui-org/progress",
|
||||
"version": "2.2.5",
|
||||
"version": "2.2.6",
|
||||
"description": "Progress bars show either determinate or indeterminate progress of an operation over time.",
|
||||
"keywords": [
|
||||
"progress"
|
||||
|
||||
@ -1,5 +1,13 @@
|
||||
# @nextui-org/radio
|
||||
|
||||
## 2.3.8
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`e7ff673`](https://github.com/nextui-org/nextui/commit/e7ff6730d7e891f1e9e3ca232b1faaebc5aedef2)]:
|
||||
- @nextui-org/react-utils@2.1.3
|
||||
- @nextui-org/form@2.1.8
|
||||
|
||||
## 2.3.7
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nextui-org/radio",
|
||||
"version": "2.3.7",
|
||||
"version": "2.3.8",
|
||||
"description": "Radios allow users to select a single option from a list of mutually exclusive options.",
|
||||
"keywords": [
|
||||
"radio"
|
||||
|
||||
@ -1,5 +1,12 @@
|
||||
# @nextui-org/ripple
|
||||
|
||||
## 2.2.7
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`e7ff673`](https://github.com/nextui-org/nextui/commit/e7ff6730d7e891f1e9e3ca232b1faaebc5aedef2)]:
|
||||
- @nextui-org/react-utils@2.1.3
|
||||
|
||||
## 2.2.6
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nextui-org/ripple",
|
||||
"version": "2.2.6",
|
||||
"version": "2.2.7",
|
||||
"description": "A simple implementation to display a ripple animation when the source component is clicked",
|
||||
"keywords": [
|
||||
"ripple"
|
||||
|
||||
@ -1,5 +1,12 @@
|
||||
# @nextui-org/scroll-shadow
|
||||
|
||||
## 2.3.5
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`e7ff673`](https://github.com/nextui-org/nextui/commit/e7ff6730d7e891f1e9e3ca232b1faaebc5aedef2)]:
|
||||
- @nextui-org/react-utils@2.1.3
|
||||
|
||||
## 2.3.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nextui-org/scroll-shadow",
|
||||
"version": "2.3.4",
|
||||
"version": "2.3.5",
|
||||
"description": "A component that applies top and bottom shadows when content overflows on scroll.",
|
||||
"keywords": [
|
||||
"scroll-shadow"
|
||||
|
||||
@ -1,5 +1,22 @@
|
||||
# @nextui-org/select
|
||||
|
||||
## 2.4.9
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#4463](https://github.com/nextui-org/nextui/pull/4463) [`d92468a`](https://github.com/nextui-org/nextui/commit/d92468aa1e35d5022c071b5d2674f5bfb6408001) Thanks [@wingkwong](https://github.com/wingkwong)! - bump `@tanstack/react-virtual` to support react 19 peer dep
|
||||
|
||||
- [#4462](https://github.com/nextui-org/nextui/pull/4462) [`16c57ec`](https://github.com/nextui-org/nextui/commit/16c57ece6467d755645f109b8de810c9063e5665) Thanks [@vinroger](https://github.com/vinroger)! - add support for dataset with section, add support for scrollshadow
|
||||
|
||||
- Updated dependencies [[`d92468a`](https://github.com/nextui-org/nextui/commit/d92468aa1e35d5022c071b5d2674f5bfb6408001), [`33e0418`](https://github.com/nextui-org/nextui/commit/33e0418d08c29f829b00ee3bc41972dfce6a3370), [`16c57ec`](https://github.com/nextui-org/nextui/commit/16c57ece6467d755645f109b8de810c9063e5665), [`e7ff673`](https://github.com/nextui-org/nextui/commit/e7ff6730d7e891f1e9e3ca232b1faaebc5aedef2), [`fb46df2`](https://github.com/nextui-org/nextui/commit/fb46df2430f95cddef0c25fce4639c2078b34f62)]:
|
||||
- @nextui-org/listbox@2.3.9
|
||||
- @nextui-org/popover@2.3.9
|
||||
- @nextui-org/react-utils@2.1.3
|
||||
- @nextui-org/form@2.1.8
|
||||
- @nextui-org/scroll-shadow@2.3.5
|
||||
- @nextui-org/spinner@2.2.6
|
||||
- @nextui-org/aria-utils@2.2.7
|
||||
|
||||
## 2.4.8
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nextui-org/select",
|
||||
"version": "2.4.8",
|
||||
"version": "2.4.9",
|
||||
"description": "A select displays a collapsible list of options and allows a user to select one of them.",
|
||||
"keywords": [
|
||||
"select"
|
||||
@ -59,7 +59,7 @@
|
||||
"@react-aria/utils": "3.26.0",
|
||||
"@react-aria/visually-hidden": "3.8.18",
|
||||
"@react-types/shared": "3.26.0",
|
||||
"@tanstack/react-virtual": "3.10.9"
|
||||
"@tanstack/react-virtual": "3.11.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@nextui-org/avatar": "workspace:*",
|
||||
|
||||
@ -161,7 +161,9 @@ export type UseSelectProps<T> = Omit<
|
||||
SelectVariantProps & {
|
||||
/**
|
||||
* The height of each item in the listbox.
|
||||
* For dataset with sections, the itemHeight must be the height of each item (including padding, border, margin).
|
||||
* This is required for virtualized listboxes to calculate the height of each item.
|
||||
* @default 36
|
||||
*/
|
||||
itemHeight?: number;
|
||||
/**
|
||||
@ -208,7 +210,7 @@ export function useSelect<T extends object>(originalProps: UseSelectProps<T>) {
|
||||
onSelectionChange,
|
||||
placeholder,
|
||||
isVirtualized,
|
||||
itemHeight = 32,
|
||||
itemHeight = 36,
|
||||
maxListboxHeight = 256,
|
||||
children,
|
||||
disallowEmptySelection = false,
|
||||
@ -564,6 +566,7 @@ export function useSelect<T extends object>(originalProps: UseSelectProps<T>) {
|
||||
className: slots.listbox({
|
||||
class: clsx(classNames?.listbox, props?.className),
|
||||
}),
|
||||
scrollShadowProps: slotsProps.scrollShadowProps,
|
||||
...mergeProps(slotsProps.listboxProps, props, menuProps),
|
||||
} as ListboxProps;
|
||||
};
|
||||
|
||||
@ -1391,9 +1391,127 @@ export const CustomItemHeight = {
|
||||
},
|
||||
};
|
||||
|
||||
const AVATAR_DECORATIONS: {[key: string]: string[]} = {
|
||||
arcane: ["jinx", "atlas-gauntlets", "flame-chompers", "fishbones", "hexcore", "shimmer"],
|
||||
anime: ["cat-ears", "heart-bloom", "in-love", "in-tears", "soul-leaving-body", "starry-eyed"],
|
||||
"lofi-vibes": ["chromawave", "cozy-cat", "cozy-headphones", "doodling", "rainy-mood"],
|
||||
valorant: [
|
||||
"a-hint-of-clove",
|
||||
"blade-storm",
|
||||
"cypher",
|
||||
"frag-out",
|
||||
"omen-cowl",
|
||||
"reyna-leer",
|
||||
"vct-supernova",
|
||||
"viper",
|
||||
"yoru",
|
||||
"carnalito2",
|
||||
"a-hint-of-clove2",
|
||||
"blade-storm2",
|
||||
"cypher2",
|
||||
"frag-out2",
|
||||
"omen-cowl2",
|
||||
"reyna-leer2",
|
||||
"vct-supernova2",
|
||||
"viper2",
|
||||
"yoru2",
|
||||
"carnalito3",
|
||||
"a-hint-of-clove3",
|
||||
"blade-storm3",
|
||||
"cypher3",
|
||||
"frag-out3",
|
||||
"omen-cowl3",
|
||||
"reyna-leer3",
|
||||
"vct-supernova3",
|
||||
"viper3",
|
||||
"yoru3",
|
||||
"carnalito4",
|
||||
"a-hint-of-clove4",
|
||||
"blade-storm4",
|
||||
"cypher4",
|
||||
"frag-out4",
|
||||
"omen-cowl4",
|
||||
"reyna-leer4",
|
||||
"vct-supernova4",
|
||||
"viper4",
|
||||
"yoru4",
|
||||
],
|
||||
spongebob: [
|
||||
"flower-clouds",
|
||||
"gary-the-snail",
|
||||
"imagination",
|
||||
"musclebob",
|
||||
"sandy-cheeks",
|
||||
"spongebob",
|
||||
],
|
||||
arcade: ["clyde-invaders", "hot-shot", "joystick", "mallow-jump", "pipedream", "snake"],
|
||||
"street-fighter": ["akuma", "cammy", "chun-li", "guile", "juri", "ken", "m.bison", "ryu"],
|
||||
};
|
||||
|
||||
export const NonVirtualizedVsVirtualizedWithSections = {
|
||||
render: () => {
|
||||
const SelectComponent = ({isVirtualized}: {isVirtualized: boolean}) => (
|
||||
<Select
|
||||
disallowEmptySelection
|
||||
className="max-w-xs"
|
||||
color="secondary"
|
||||
defaultSelectedKeys={["jinx"]}
|
||||
isVirtualized={isVirtualized}
|
||||
label={`Avatar Decoration ${isVirtualized ? "(Virtualized)" : "(Non-virtualized)"}`}
|
||||
selectedKeys={["jinx"]}
|
||||
selectionMode="single"
|
||||
variant="bordered"
|
||||
>
|
||||
{Object.keys(AVATAR_DECORATIONS).map((key) => (
|
||||
<SelectSection
|
||||
key={key}
|
||||
classNames={{
|
||||
heading: "uppercase text-secondary",
|
||||
}}
|
||||
title={key}
|
||||
>
|
||||
{AVATAR_DECORATIONS[key].map((item) => (
|
||||
<SelectItem key={item} className="capitalize" color="secondary" variant="bordered">
|
||||
{item.replace(/-/g, " ")}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectSection>
|
||||
))}
|
||||
</Select>
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="flex gap-4 w-full">
|
||||
<SelectComponent isVirtualized={false} />
|
||||
<SelectComponent isVirtualized={true} />
|
||||
</div>
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
export const ValidationBehaviorAria = {
|
||||
render: ValidationBehaviorAriaTemplate,
|
||||
args: {
|
||||
...defaultProps,
|
||||
},
|
||||
};
|
||||
|
||||
export const PopoverTopOrBottom = {
|
||||
args: {
|
||||
...defaultProps,
|
||||
},
|
||||
render: (args) => (
|
||||
<div className="relative h-screen w-screen">
|
||||
<div className="absolute top-0 p-8">
|
||||
<div className="w-48">
|
||||
<Template {...args} />
|
||||
</div>
|
||||
</div>
|
||||
<div className="absolute top-1/2 p-8">
|
||||
<div className="w-48">
|
||||
<Template {...args} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
};
|
||||
|
||||
@ -1,5 +1,12 @@
|
||||
# @nextui-org/skeleton
|
||||
|
||||
## 2.2.5
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`e7ff673`](https://github.com/nextui-org/nextui/commit/e7ff6730d7e891f1e9e3ca232b1faaebc5aedef2)]:
|
||||
- @nextui-org/react-utils@2.1.3
|
||||
|
||||
## 2.2.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nextui-org/skeleton",
|
||||
"version": "2.2.4",
|
||||
"version": "2.2.5",
|
||||
"description": "Skeleton is used to display the loading state of some component.",
|
||||
"keywords": [
|
||||
"skeleton"
|
||||
|
||||
@ -1,5 +1,13 @@
|
||||
# @nextui-org/slider
|
||||
|
||||
## 2.4.7
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`e7ff673`](https://github.com/nextui-org/nextui/commit/e7ff6730d7e891f1e9e3ca232b1faaebc5aedef2)]:
|
||||
- @nextui-org/react-utils@2.1.3
|
||||
- @nextui-org/tooltip@2.2.7
|
||||
|
||||
## 2.4.6
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nextui-org/slider",
|
||||
"version": "2.4.6",
|
||||
"version": "2.4.7",
|
||||
"description": "A slider allows a user to select one or more values within a range.",
|
||||
"keywords": [
|
||||
"slider"
|
||||
|
||||
@ -1,5 +1,15 @@
|
||||
# @nextui-org/snippet
|
||||
|
||||
## 2.2.10
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`4f0ef58`](https://github.com/nextui-org/nextui/commit/4f0ef5818be83071d6c2032080251b41039656f1), [`e7ff673`](https://github.com/nextui-org/nextui/commit/e7ff6730d7e891f1e9e3ca232b1faaebc5aedef2)]:
|
||||
- @nextui-org/use-clipboard@2.1.2
|
||||
- @nextui-org/react-utils@2.1.3
|
||||
- @nextui-org/button@2.2.9
|
||||
- @nextui-org/tooltip@2.2.7
|
||||
|
||||
## 2.2.9
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nextui-org/snippet",
|
||||
"version": "2.2.9",
|
||||
"version": "2.2.10",
|
||||
"description": "Display a snippet of copyable code for the command line.",
|
||||
"keywords": [
|
||||
"snippet"
|
||||
|
||||
@ -92,32 +92,9 @@ export const MultiLine = {
|
||||
args: {
|
||||
...defaultProps,
|
||||
children: [
|
||||
// "npm install @nextui-org/react",
|
||||
// "yarn add @nextui-org/react",
|
||||
// "pnpm add @nextui-org/react",
|
||||
`
|
||||
{
|
||||
"name": "Next.js PWA",
|
||||
"short_name": "NextPWA",
|
||||
"description": "A Progressive Web App built with Next.js and React",
|
||||
"start_url": "/",
|
||||
"display": "standalone",
|
||||
"background_color": "#ffffff",
|
||||
"theme_color": "#000000",
|
||||
"icons": [
|
||||
{
|
||||
"src": "/icon-192x192.png",
|
||||
"sizes": "192x192",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "/icon-512x512.png",
|
||||
"sizes": "512x512",
|
||||
"type": "image/png"
|
||||
}
|
||||
]
|
||||
}
|
||||
`,
|
||||
"npm install @nextui-org/react",
|
||||
"yarn add @nextui-org/react",
|
||||
"pnpm add @nextui-org/react",
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
@ -1,5 +1,13 @@
|
||||
# @nextui-org/spacer
|
||||
|
||||
## 2.2.6
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`e7ff673`](https://github.com/nextui-org/nextui/commit/e7ff6730d7e891f1e9e3ca232b1faaebc5aedef2)]:
|
||||
- @nextui-org/react-utils@2.1.3
|
||||
- @nextui-org/system-rsc@2.3.5
|
||||
|
||||
## 2.2.5
|
||||
|
||||
### Patch Changes
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user