From bff9f0231c05b332272105e085d37854ec32eeaf Mon Sep 17 00:00:00 2001 From: Vincentius Roger Kuswara Date: Mon, 2 Dec 2024 01:35:49 +0800 Subject: [PATCH 01/11] feat: baseline virtualization for table --- packages/components/table/package.json | 13 +- packages/components/table/src/table.tsx | 54 ++++- .../table/src/virtualized-table-body.tsx | 214 ++++++++++++++++++ .../table/stories/table.stories.tsx | 43 ++++ pnpm-lock.yaml | 5 +- 5 files changed, 310 insertions(+), 19 deletions(-) create mode 100644 packages/components/table/src/virtualized-table-body.tsx diff --git a/packages/components/table/package.json b/packages/components/table/package.json index 5633f8e251..4290d1a309 100644 --- a/packages/components/table/package.json +++ b/packages/components/table/package.json @@ -34,10 +34,10 @@ "postpack": "clean-package restore" }, "peerDependencies": { - "react": ">=18 || >=19.0.0-rc.0", - "react-dom": ">=18 || >=19.0.0-rc.0", + "@nextui-org/system": ">=2.3.0-beta.0", "@nextui-org/theme": ">=2.3.0-beta.0", - "@nextui-org/system": ">=2.3.0-beta.0" + "react": ">=18 || >=19.0.0-rc.0", + "react-dom": ">=18 || >=19.0.0-rc.0" }, "dependencies": { "@nextui-org/checkbox": "workspace:*", @@ -53,15 +53,16 @@ "@react-stately/table": "3.12.3", "@react-stately/virtualizer": "4.1.0", "@react-types/grid": "3.2.9", - "@react-types/table": "3.10.2" + "@react-types/table": "3.10.2", + "@tanstack/react-virtual": "^3.10.9" }, "devDependencies": { - "@nextui-org/theme": "workspace:*", - "@nextui-org/system": "workspace:*", "@nextui-org/button": "workspace:*", "@nextui-org/chip": "workspace:*", "@nextui-org/pagination": "workspace:*", "@nextui-org/spinner": "workspace:*", + "@nextui-org/system": "workspace:*", + "@nextui-org/theme": "workspace:*", "@nextui-org/tooltip": "workspace:*", "@nextui-org/use-infinite-scroll": "workspace:*", "@nextui-org/user": "workspace:*", diff --git a/packages/components/table/src/table.tsx b/packages/components/table/src/table.tsx index e2a70af996..4f1b4e37fb 100644 --- a/packages/components/table/src/table.tsx +++ b/packages/components/table/src/table.tsx @@ -8,8 +8,14 @@ import TableHeaderRow from "./table-header-row"; import TableColumnHeader from "./table-column-header"; import TableSelectAllCheckbox from "./table-select-all-checkbox"; import TableBody from "./table-body"; +import VirtualizedTableBody from "./virtualized-table-body"; // Import the virtualized table body component -export interface TableProps extends Omit {} +export interface TableProps + extends Omit, "isSelectable" | "isMultiSelectable"> { + isVirtualized?: boolean; + rowHeight?: number; + maxBodyHeight?: number; +} const Table = forwardRef<"table", TableProps>((props, ref) => { const { @@ -30,6 +36,12 @@ const Table = forwardRef<"table", TableProps>((props, ref) => { ref, }); + const { + isVirtualized, + rowHeight = 40, // Default row height + maxBodyHeight = 600, // Default max body height + } = props; + const Wrapper = useCallback( ({children}: {children: JSX.Element}) => { if (removeWrapper) { @@ -41,6 +53,8 @@ const Table = forwardRef<"table", TableProps>((props, ref) => { [removeWrapper, getWrapperProps], ); + const shouldVirtualize = isVirtualized ?? collection.size > 50; + return (
{topContentPlacement === "outside" && topContent} @@ -84,17 +98,33 @@ const Table = forwardRef<"table", TableProps>((props, ref) => { ))} - + {shouldVirtualize ? ( + + ) : ( + + )} {bottomContentPlacement === "inside" && bottomContent} diff --git a/packages/components/table/src/virtualized-table-body.tsx b/packages/components/table/src/virtualized-table-body.tsx new file mode 100644 index 0000000000..fb9bfce242 --- /dev/null +++ b/packages/components/table/src/virtualized-table-body.tsx @@ -0,0 +1,214 @@ +import {forwardRef, HTMLNextUIProps} from "@nextui-org/system"; +import {useDOMRef} from "@nextui-org/react-utils"; +import {clsx, dataAttr} from "@nextui-org/shared-utils"; +import {useTableRowGroup} from "@react-aria/table"; +import {filterDOMProps} from "@nextui-org/react-utils"; +import {mergeProps} from "@react-aria/utils"; +import {useRef} from "react"; +import {useVirtualizer} from "@tanstack/react-virtual"; + +import TableRow from "./table-row"; +import TableCell from "./table-cell"; +import TableCheckboxCell from "./table-checkbox-cell"; +import {ValuesType} from "./use-table"; + +// @internal +export interface VirtualizedTableBodyProps extends HTMLNextUIProps<"tbody"> { + slots: ValuesType["slots"]; + collection: ValuesType["collection"]; + state: ValuesType["state"]; + isSelectable: ValuesType["isSelectable"]; + color: ValuesType["color"]; + disableAnimation: ValuesType["disableAnimation"]; + checkboxesProps: ValuesType["checkboxesProps"]; + selectionMode: ValuesType["selectionMode"]; + classNames?: ValuesType["classNames"]; + rowHeight: number; + maxBodyHeight: number; +} + +const VirtualizedTableBody = forwardRef<"tbody", VirtualizedTableBodyProps>((props, ref) => { + const { + as, + className, + slots, + state, + collection, + isSelectable, + color, + disableAnimation, + checkboxesProps, + selectionMode, + classNames, + rowHeight, + maxBodyHeight, + ...otherProps + } = props; + + const Component = as || "tbody"; + const shouldFilterDOMProps = typeof Component === "string"; + + const domRef = useDOMRef(ref); + + const {rowGroupProps} = useTableRowGroup(); + + const tbodyStyles = clsx(classNames?.tbody, className); + const bodyProps = collection?.body.props; + + const isLoading = + bodyProps?.isLoading || + bodyProps?.loadingState === "loading" || + bodyProps?.loadingState === "loadingMore"; + + const parentRef = useRef(null); + + // Convert childNodes to an array + const items = [...collection.body.childNodes]; + + // Get the count + const count = items.length; + + const rowVirtualizer = useVirtualizer({ + count, + getScrollElement: () => parentRef.current, + estimateSize: () => rowHeight, + overscan: 5, // Adjust as needed + }); + + const virtualItems = rowVirtualizer.getVirtualItems(); + + let emptyContent; + let loadingContent; + + if (collection.size === 0 && bodyProps.emptyContent) { + emptyContent = ( + + + {!isLoading && bodyProps.emptyContent} + + + ); + } + + if (isLoading && bodyProps.loadingContent) { + loadingContent = ( + + + {bodyProps.loadingContent} + + {!emptyContent && collection.size === 0 ? ( + + ) : null} + + ); + } + + return ( + + + +
+
+ {virtualItems.map((virtualRow) => { + const row = items[virtualRow.index]; + + if (!row) { + return null; + } + + return ( +
+ + {[...row.childNodes].map((cell) => + cell.props.isSelectionCell ? ( + + ) : ( + + ), + )} + +
+ ); + })} +
+
+ + + {loadingContent} + {emptyContent} +
+ ); +}); + +VirtualizedTableBody.displayName = "NextUI.VirtualizedTableBody"; + +export default VirtualizedTableBody; diff --git a/packages/components/table/stories/table.stories.tsx b/packages/components/table/stories/table.stories.tsx index 18d86e1da2..7b70709ed7 100644 --- a/packages/components/table/stories/table.stories.tsx +++ b/packages/components/table/stories/table.stories.tsx @@ -1110,3 +1110,46 @@ export const TableWithSwitch = { selectionMode: "multiple", }, }; + +function generateRows(count) { + return Array.from({length: count}, (_, index) => ({ + key: index.toString(), + name: `Item ${index + 1}`, + value: `Value ${index + 1}`, + })); +} + +export const Virtualized = { + render: (args: TableProps) => { + const rows = generateRows(10000); + const columns = [ + {key: "name", label: "Name"}, + {key: "value", label: "Value"}, + ]; + + return ( + + + {(column) => {column.label}} + + + {(item) => ( + + {(columnKey) => {item[columnKey]}} + + )} + +
+ ); + }, + args: { + ...defaultProps, + className: "max-w-3xl", + }, +}; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c65136c311..25d00be1f9 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -2850,6 +2850,9 @@ importers: '@react-types/table': specifier: 3.10.2 version: 3.10.2(react@18.3.1) + '@tanstack/react-virtual': + specifier: ^3.10.9 + version: 3.10.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1) devDependencies: '@nextui-org/button': specifier: workspace:* @@ -22124,7 +22127,7 @@ snapshots: doctrine: 2.1.0 eslint: 7.32.0 eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.12.0(@typescript-eslint/parser@5.62.0(eslint@7.32.0)(typescript@4.9.5))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@2.7.1(eslint-plugin-import@2.31.0)(eslint@7.32.0))(eslint@7.32.0) + eslint-module-utils: 2.12.0(@typescript-eslint/parser@5.62.0(eslint@7.32.0)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@5.62.0(eslint@7.32.0)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0)(eslint@7.32.0))(eslint@7.32.0) hasown: 2.0.2 is-core-module: 2.15.1 is-glob: 4.0.3 From aaf9afb7a518f836635c4fff40073425e8c36dcc Mon Sep 17 00:00:00 2001 From: Vincentius Roger Kuswara Date: Sun, 8 Dec 2024 17:53:25 +0800 Subject: [PATCH 02/11] merge branch canary --- .changeset/silly-mugs-marry.md | 111 - apps/docs/app/docs/[[...slug]]/page.tsx | 2 +- apps/docs/app/docs/layout.tsx | 2 +- apps/docs/app/examples/perf/client-page.tsx | 561 +++ apps/docs/app/examples/perf/page.tsx | 562 +-- apps/docs/app/layout.tsx | 35 +- apps/docs/app/page.tsx | 24 +- apps/docs/app/providers.tsx | 4 +- .../components/ads/carbon-ad/carbon-ad.tsx | 6 +- apps/docs/components/blog-post.tsx | 1 + apps/docs/components/demos/music-player.tsx | 9 +- .../components/demos/user-twitter-card.tsx | 6 +- .../components/code-demo/react-live-demo.tsx | 25 +- .../components/docs/components/codeblock.tsx | 290 +- .../docs/components/package-managers.tsx | 7 +- apps/docs/components/docs/sidebar.tsx | 60 +- apps/docs/components/docs/toc.tsx | 6 +- .../featurebase/fb-changelog-button.tsx | 47 - .../featurebase/fb-feedback-button.tsx | 43 - .../components/marketing/features-grid.tsx | 2 +- .../marketing/hero/floating-components.tsx | 2 +- apps/docs/components/marketing/hero/hero.tsx | 17 +- .../components/marketing/install-banner.tsx | 2 +- apps/docs/components/marketing/marquee.tsx | 79 + .../marketing/nextui-pro-section.tsx | 182 + .../components/marketing/support-client.tsx | 211 + apps/docs/components/marketing/support.tsx | 220 +- apps/docs/components/mdx-components.tsx | 79 +- apps/docs/components/mdx-content.tsx | 2 +- apps/docs/components/navbar.tsx | 143 +- apps/docs/components/primitives.ts | 2 +- .../components/scripts/script-providers.tsx | 5 - apps/docs/components/theme-switch.tsx | 29 +- apps/docs/config/fonts.ts | 92 +- apps/docs/config/github-info.json | 8 +- apps/docs/config/routes.json | 33 +- apps/docs/config/search-meta.json | 3312 ++++++++----- apps/docs/content/blog/v2.6.0.mdx | 772 +++ ...olled.raw.jsx => controlled-alert.raw.jsx} | 0 .../content/components/alert/controlled.ts | 2 +- apps/docs/content/components/alert/index.ts | 2 + .../alert/without-icon-wrapper.raw.jsx | 15 + .../components/alert/without-icon-wrapper.ts | 9 + .../virtualization-custom-item-height.raw.jsx | 53 + .../virtualization-custom-item-height.ts | 58 +- .../virtualization-max-listbox-height.raw.jsx | 52 + .../virtualization-max-listbox-height.ts | 57 +- .../virtualization-ten-thousand.raw.jsx | 51 + .../virtualization-ten-thousand.ts | 56 +- .../autocomplete/virtualization.raw.jsx | 51 + .../components/autocomplete/virtualization.ts | 56 +- .../components/drawer/custom-styles.raw.jsx | 2 +- .../components/form/controlled.raw.jsx | 38 + .../content/components/form/controlled.ts | 9 + .../form/custom-error-messages.raw.jsx | 28 + .../components/form/custom-error-messages.ts | 9 + .../components/form/custom-validation.raw.jsx | 30 + .../components/form/custom-validation.ts | 9 + .../docs/content/components/form/demo.raw.jsx | 170 + apps/docs/content/components/form/demo.ts | 9 + .../content/components/form/events.raw.jsx | 52 + apps/docs/content/components/form/events.ts | 9 + .../components/form/form-usage.raw.jsx | 35 + apps/docs/content/components/form/index.ts | 21 + .../components/form/native-validation.raw.jsx | 24 + .../components/form/native-validation.ts | 9 + .../form/real-time-validation.raw.jsx | 36 + .../components/form/real-time-validation.ts | 9 + .../components/form/server-validation.raw.jsx | 49 + .../components/form/server-validation.ts | 9 + .../content/components/form/usage.raw.jsx | 35 + apps/docs/content/components/form/usage.ts | 9 + .../input-otp/input-otp-required.raw.jsx | 32 + .../components/input-otp/required.raw.jsx | 11 +- .../content/components/input-otp/required.ts | 2 +- .../components/input-otp/usage.raw.tsx | 15 - .../content/components/input-otp/usage.ts | 6 - apps/docs/content/components/listbox/index.ts | 4 + .../virtualization-ten-thousand.raw.jsx | 66 + .../listbox/virtualization-ten-thousand.ts | 9 + .../components/listbox/virtualization.raw.jsx | 65 + .../components/listbox/virtualization.ts | 9 + .../components/modal/draggable.raw.jsx | 2 +- apps/docs/content/components/select/index.ts | 8 + .../virtualization-custom-item-height.raw.jsx | 56 + .../virtualization-custom-item-height.ts | 9 + .../virtualization-max-listbox-height.raw.jsx | 55 + .../virtualization-max-listbox-height.ts | 9 + .../virtualization-ten-thousand.raw.jsx | 54 + .../select/virtualization-ten-thousand.ts | 9 + .../components/select/virtualization.raw.jsx | 54 + .../components/select/virtualization.ts | 9 + .../docs/api-references/nextui-provider.mdx | 14 +- apps/docs/content/docs/components/alert.mdx | 6 + .../content/docs/components/autocomplete.mdx | 6 +- apps/docs/content/docs/components/avatar.mdx | 4 +- apps/docs/content/docs/components/badge.mdx | 2 +- .../content/docs/components/breadcrumbs.mdx | 6 +- .../docs/content/docs/components/calendar.mdx | 2 +- apps/docs/content/docs/components/card.mdx | 2 +- .../docs/components/checkbox-group.mdx | 6 +- .../docs/content/docs/components/checkbox.mdx | 2 +- apps/docs/content/docs/components/chip.mdx | 2 +- .../docs/components/circular-progress.mdx | 2 +- .../content/docs/components/date-picker.mdx | 4 +- .../docs/components/date-range-picker.mdx | 6 +- apps/docs/content/docs/components/drawer.mdx | 2 +- .../docs/content/docs/components/dropdown.mdx | 10 +- apps/docs/content/docs/components/form.mdx | 183 + apps/docs/content/docs/components/image.mdx | 2 +- .../content/docs/components/input-otp.mdx | 12 +- apps/docs/content/docs/components/input.mdx | 6 +- apps/docs/content/docs/components/kbd.mdx | 2 +- apps/docs/content/docs/components/listbox.mdx | 38 +- apps/docs/content/docs/components/modal.mdx | 2 +- apps/docs/content/docs/components/navbar.mdx | 2 +- .../content/docs/components/pagination.mdx | 2 +- apps/docs/content/docs/components/popover.mdx | 2 +- .../docs/content/docs/components/progress.mdx | 2 +- .../content/docs/components/radio-group.mdx | 8 +- apps/docs/content/docs/components/select.mdx | 59 +- .../docs/content/docs/components/skeleton.mdx | 2 +- apps/docs/content/docs/components/snippet.mdx | 2 +- apps/docs/content/docs/components/spinner.mdx | 2 +- apps/docs/content/docs/components/switch.mdx | 8 +- apps/docs/content/docs/components/table.mdx | 2 +- apps/docs/content/docs/components/tabs.mdx | 2 +- .../docs/content/docs/components/textarea.mdx | 6 +- .../content/docs/components/time-input.mdx | 6 +- apps/docs/content/docs/components/tooltip.mdx | 2 +- apps/docs/content/docs/components/user.mdx | 2 +- apps/docs/content/docs/frameworks/astro.mdx | 4 +- apps/docs/content/docs/frameworks/nextjs.mdx | 6 +- apps/docs/content/docs/frameworks/remix.mdx | 4 +- apps/docs/content/docs/frameworks/vite.mdx | 4 +- apps/docs/content/docs/guide/form.mdx | 416 -- apps/docs/content/docs/guide/forms.mdx | 573 +++ apps/docs/content/docs/guide/installation.mdx | 6 +- apps/docs/content/docs/guide/introduction.mdx | 30 +- apps/docs/content/docs/guide/routing.mdx | 215 +- .../docs/content/docs/guide/upgrade-to-v2.mdx | 8 +- apps/docs/next.config.js | 28 +- apps/docs/package.json | 77 +- .../public/assets/fonts/FiraCode-Bold.woff2 | Bin 0 -> 107788 bytes .../public/assets/fonts/FiraCode-Medium.woff2 | Bin 0 -> 102384 bytes .../assets/fonts/FiraCode-Regular.woff2 | Bin 0 -> 103240 bytes .../assets/fonts/FiraCode-SemiBold.woff2 | Bin 0 -> 106992 bytes .../public/assets/fonts/Inter-Black.woff2 | Bin 0 -> 108748 bytes .../docs/public/assets/fonts/Inter-Bold.woff2 | Bin 0 -> 111040 bytes .../public/assets/fonts/Inter-ExtraBold.woff2 | Bin 0 -> 111360 bytes .../assets/fonts/Inter-ExtraLight.woff2 | Bin 0 -> 110176 bytes .../public/assets/fonts/Inter-Light.woff2 | Bin 0 -> 109992 bytes .../public/assets/fonts/Inter-Medium.woff2 | Bin 0 -> 111380 bytes .../public/assets/fonts/Inter-Regular.woff2 | Bin 0 -> 108488 bytes .../public/assets/fonts/Inter-SemiBold.woff2 | Bin 0 -> 111588 bytes apps/docs/public/blog/v2.6.0.jpg | Bin 0 -> 130035 bytes apps/docs/public/blog/v2.6.0_2x.jpg | Bin 0 -> 133403 bytes .../nextuipro-section-background-light.webp | Bin 0 -> 2602924 bytes ...uipro-section-background-light@mobile.webp | Bin 0 -> 2130322 bytes .../images/nextuipro-section-background.webp | Bin 0 -> 413334 bytes .../nextuipro-section-background@mobile.webp | Bin 0 -> 201662 bytes apps/docs/styles/globals.css | 10 +- apps/docs/tailwind.config.js | 30 +- apps/docs/utils/env.ts | 1 + apps/docs/utils/featurebase.ts | 6 - package.json | 4 +- packages/components/accordion/CHANGELOG.md | 80 + packages/components/accordion/package.json | 8 +- packages/components/alert/CHANGELOG.md | 68 + packages/components/alert/package.json | 8 +- packages/components/autocomplete/CHANGELOG.md | 104 + packages/components/autocomplete/package.json | 8 +- .../autocomplete/src/autocomplete.tsx | 20 +- .../autocomplete/src/use-autocomplete.ts | 2 +- packages/components/avatar/CHANGELOG.md | 60 + packages/components/avatar/package.json | 8 +- packages/components/badge/CHANGELOG.md | 56 + packages/components/badge/package.json | 6 +- packages/components/breadcrumbs/CHANGELOG.md | 60 + packages/components/breadcrumbs/package.json | 8 +- packages/components/button/CHANGELOG.md | 72 + packages/components/button/package.json | 8 +- packages/components/calendar/CHANGELOG.md | 78 + packages/components/calendar/package.json | 8 +- packages/components/calendar/src/calendar.tsx | 20 +- .../calendar/src/range-calendar.tsx | 22 +- packages/components/card/CHANGELOG.md | 68 + packages/components/card/package.json | 8 +- packages/components/checkbox/CHANGELOG.md | 74 + packages/components/checkbox/package.json | 8 +- .../checkbox/src/use-checkbox-group.ts | 2 +- .../components/checkbox/src/use-checkbox.ts | 97 +- .../checkbox/stories/checkbox.stories.tsx | 62 + packages/components/chip/CHANGELOG.md | 60 + packages/components/chip/package.json | 8 +- packages/components/code/CHANGELOG.md | 64 + packages/components/code/package.json | 4 +- packages/components/date-input/CHANGELOG.md | 70 + .../date-input/__tests__/date-input.test.tsx | 1 + .../date-input/__tests__/time-input.test.tsx | 34 +- packages/components/date-input/package.json | 8 +- .../components/date-input/src/date-input.tsx | 25 +- .../components/date-input/src/time-input.tsx | 20 +- .../date-input/src/use-date-input.ts | 2 +- .../date-input/src/use-time-input.ts | 2 +- packages/components/date-picker/CHANGELOG.md | 92 + packages/components/date-picker/package.json | 8 +- .../date-picker/src/date-picker.tsx | 20 +- .../src/date-range-picker-field.tsx | 21 +- .../date-picker/src/date-range-picker.tsx | 22 +- .../date-picker/src/use-date-picker.ts | 2 +- .../date-picker/src/use-date-range-picker.ts | 2 +- packages/components/divider/CHANGELOG.md | 64 + packages/components/divider/package.json | 4 +- packages/components/drawer/CHANGELOG.md | 68 + packages/components/drawer/package.json | 6 +- packages/components/dropdown/CHANGELOG.md | 80 + packages/components/dropdown/package.json | 8 +- .../components/dropdown/src/dropdown-menu.tsx | 20 +- .../dropdown/src/dropdown-trigger.tsx | 7 +- packages/components/form/CHANGELOG.md | 70 + packages/components/form/package.json | 8 +- packages/components/form/src/base-form.tsx | 12 +- packages/components/image/CHANGELOG.md | 58 + packages/components/image/package.json | 6 +- packages/components/input-otp/CHANGELOG.md | 66 + packages/components/input-otp/package.json | 7 +- .../components/input-otp/src/use-input-otp.ts | 10 +- .../input-otp/stories/input-otp.stories.tsx | 68 + packages/components/input/CHANGELOG.md | 72 + packages/components/input/package.json | 8 +- packages/components/input/src/use-input.ts | 2 +- packages/components/kbd/CHANGELOG.md | 66 + packages/components/kbd/package.json | 6 +- packages/components/link/CHANGELOG.md | 62 + packages/components/link/package.json | 8 +- packages/components/listbox/CHANGELOG.md | 80 + packages/components/listbox/package.json | 10 +- .../listbox/src/base/listbox-item-base.tsx | 2 +- .../components/listbox/src/listbox-item.tsx | 8 +- packages/components/listbox/src/listbox.tsx | 18 +- .../listbox/src/use-listbox-item.ts | 4 +- .../listbox/src/virtualized-listbox.tsx | 12 +- .../listbox/stories/listbox.stories.tsx | 105 + packages/components/menu/CHANGELOG.md | 84 + packages/components/menu/package.json | 8 +- .../menu/src/base/menu-item-base.tsx | 2 +- packages/components/menu/src/menu-item.tsx | 9 +- packages/components/menu/src/menu.tsx | 21 +- packages/components/menu/src/use-menu-item.ts | 4 +- packages/components/modal/CHANGELOG.md | 82 + packages/components/modal/package.json | 8 +- .../components/modal/src/modal-content.tsx | 5 +- packages/components/navbar/CHANGELOG.md | 72 + packages/components/navbar/package.json | 11 +- .../components/navbar/src/navbar-menu.tsx | 77 +- packages/components/navbar/src/use-navbar.ts | 11 + packages/components/pagination/CHANGELOG.md | 66 + .../pagination/__tests__/pagination.test.tsx | 74 + packages/components/pagination/package.json | 9 +- .../pagination/src/use-pagination.ts | 15 +- packages/components/popover/CHANGELOG.md | 84 + packages/components/popover/package.json | 11 +- .../popover/src/popover-content.tsx | 12 +- .../popover/src/popover-trigger.tsx | 7 +- .../components/popover/src/use-popover.ts | 6 +- packages/components/progress/CHANGELOG.md | 60 + packages/components/progress/package.json | 8 +- packages/components/radio/CHANGELOG.md | 70 + packages/components/radio/package.json | 8 +- .../components/radio/src/use-radio-group.ts | 2 +- packages/components/radio/src/use-radio.ts | 33 +- packages/components/ripple/CHANGELOG.md | 58 + packages/components/ripple/package.json | 6 +- .../components/scroll-shadow/CHANGELOG.md | 58 + .../components/scroll-shadow/package.json | 6 +- packages/components/select/CHANGELOG.md | 102 + .../select/__tests__/select.test.tsx | 383 +- packages/components/select/package.json | 12 +- .../components/select/src/hidden-select.tsx | 24 +- packages/components/select/src/select.tsx | 21 +- packages/components/select/src/use-select.ts | 69 +- .../select/stories/select.stories.tsx | 354 ++ packages/components/skeleton/CHANGELOG.md | 56 + packages/components/skeleton/package.json | 6 +- packages/components/slider/CHANGELOG.md | 66 + packages/components/slider/package.json | 8 +- packages/components/snippet/CHANGELOG.md | 80 + packages/components/snippet/package.json | 8 +- .../snippet/stories/snippet.stories.tsx | 29 +- packages/components/spacer/CHANGELOG.md | 64 + packages/components/spacer/package.json | 4 +- packages/components/spinner/CHANGELOG.md | 64 + packages/components/spinner/package.json | 4 +- packages/components/switch/CHANGELOG.md | 62 + packages/components/switch/package.json | 8 +- packages/components/switch/src/use-switch.ts | 32 +- packages/components/table/CHANGELOG.md | 72 + packages/components/table/package.json | 10 +- packages/components/tabs/CHANGELOG.md | 76 + packages/components/tabs/package.json | 8 +- packages/components/tabs/src/tabs.tsx | 18 +- packages/components/tooltip/CHANGELOG.md | 74 + packages/components/tooltip/package.json | 12 +- packages/components/user/CHANGELOG.md | 66 + packages/components/user/package.json | 8 +- packages/core/react/CHANGELOG.md | 247 + packages/core/react/package.json | 2 +- packages/core/react/tsup.config.ts | 1 - packages/core/system-rsc/CHANGELOG.md | 46 + packages/core/system-rsc/package.json | 4 +- packages/core/system/CHANGELOG.md | 62 + packages/core/system/package.json | 4 +- packages/core/system/src/provider-context.ts | 2 +- packages/core/system/src/provider.tsx | 2 +- packages/core/theme/CHANGELOG.md | 46 + packages/core/theme/package.json | 2 +- .../core/theme/src/components/accordion.ts | 2 +- packages/core/theme/src/components/form.ts | 23 + packages/core/theme/src/components/index.ts | 1 + packages/core/theme/src/components/select.ts | 2 +- .../use-aria-accordion-item/CHANGELOG.md | 34 + .../use-aria-accordion-item/package.json | 2 +- .../hooks/use-aria-accordion/CHANGELOG.md | 38 + .../hooks/use-aria-accordion/package.json | 4 +- packages/hooks/use-aria-button/CHANGELOG.md | 38 + packages/hooks/use-aria-button/package.json | 4 +- packages/hooks/use-aria-link/CHANGELOG.md | 38 + packages/hooks/use-aria-link/package.json | 4 +- packages/hooks/use-aria-menu/CHANGELOG.md | 38 + packages/hooks/use-aria-menu/package.json | 4 +- .../hooks/use-aria-modal-overlay/CHANGELOG.md | 38 + .../hooks/use-aria-modal-overlay/package.json | 4 +- .../hooks/use-aria-multiselect/CHANGELOG.md | 42 + .../hooks/use-aria-multiselect/package.json | 4 +- .../src/use-multiselect-state.ts | 54 +- .../hooks/use-aria-toggle-button/CHANGELOG.md | 44 + .../hooks/use-aria-toggle-button/package.json | 4 +- packages/hooks/use-callback-ref/CHANGELOG.md | 42 + packages/hooks/use-callback-ref/package.json | 2 +- packages/hooks/use-clipboard/CHANGELOG.md | 34 + packages/hooks/use-clipboard/package.json | 2 +- .../use-data-scroll-overflow/CHANGELOG.md | 42 + .../use-data-scroll-overflow/package.json | 2 +- packages/hooks/use-disclosure/CHANGELOG.md | 44 + packages/hooks/use-disclosure/package.json | 4 +- packages/hooks/use-draggable/CHANGELOG.md | 34 + packages/hooks/use-draggable/package.json | 2 +- packages/hooks/use-image/CHANGELOG.md | 42 + packages/hooks/use-image/package.json | 2 +- .../hooks/use-infinite-scroll/CHANGELOG.md | 42 + .../hooks/use-infinite-scroll/package.json | 2 +- .../use-intersection-observer/CHANGELOG.md | 38 + .../use-intersection-observer/package.json | 4 +- packages/hooks/use-is-mobile/CHANGELOG.md | 34 + packages/hooks/use-is-mobile/package.json | 2 +- packages/hooks/use-is-mounted/CHANGELOG.md | 34 + packages/hooks/use-is-mounted/package.json | 2 +- packages/hooks/use-measure/CHANGELOG.md | 34 + packages/hooks/use-measure/package.json | 2 +- packages/hooks/use-pagination/CHANGELOG.md | 42 + packages/hooks/use-pagination/package.json | 2 +- packages/hooks/use-real-shape/CHANGELOG.md | 42 + packages/hooks/use-real-shape/package.json | 2 +- packages/hooks/use-ref-state/CHANGELOG.md | 34 + packages/hooks/use-ref-state/package.json | 2 +- packages/hooks/use-resize/CHANGELOG.md | 34 + packages/hooks/use-resize/package.json | 2 +- .../hooks/use-safe-layout-effect/CHANGELOG.md | 34 + .../hooks/use-safe-layout-effect/package.json | 2 +- .../hooks/use-scroll-position/CHANGELOG.md | 34 + .../hooks/use-scroll-position/package.json | 2 +- packages/hooks/use-ssr/CHANGELOG.md | 34 + packages/hooks/use-ssr/package.json | 2 +- packages/hooks/use-theme/CHANGELOG.md | 34 + packages/hooks/use-theme/package.json | 2 +- packages/hooks/use-update-effect/CHANGELOG.md | 34 + packages/hooks/use-update-effect/package.json | 2 +- packages/utilities/aria-utils/CHANGELOG.md | 62 + packages/utilities/aria-utils/package.json | 4 +- packages/utilities/dom-animation/CHANGELOG.md | 34 + packages/utilities/dom-animation/package.json | 2 +- packages/utilities/framer-utils/CHANGELOG.md | 60 + packages/utilities/framer-utils/package.json | 2 +- .../utilities/react-rsc-utils/CHANGELOG.md | 34 + .../utilities/react-rsc-utils/package.json | 2 +- packages/utilities/react-utils/CHANGELOG.md | 44 + packages/utilities/react-utils/package.json | 2 +- packages/utilities/shared-icons/CHANGELOG.md | 34 + packages/utilities/shared-icons/package.json | 2 +- packages/utilities/shared-utils/CHANGELOG.md | 34 + packages/utilities/shared-utils/package.json | 2 +- packages/utilities/stories-utils/CHANGELOG.md | 34 + packages/utilities/stories-utils/package.json | 2 +- packages/utilities/test-utils/CHANGELOG.md | 34 + packages/utilities/test-utils/package.json | 2 +- plop/component/package.json.hbs | 4 +- pnpm-lock.yaml | 4403 +++++++++-------- 398 files changed, 15830 insertions(+), 6285 deletions(-) delete mode 100644 .changeset/silly-mugs-marry.md create mode 100644 apps/docs/app/examples/perf/client-page.tsx delete mode 100644 apps/docs/components/featurebase/fb-changelog-button.tsx delete mode 100644 apps/docs/components/featurebase/fb-feedback-button.tsx create mode 100644 apps/docs/components/marketing/marquee.tsx create mode 100644 apps/docs/components/marketing/nextui-pro-section.tsx create mode 100644 apps/docs/components/marketing/support-client.tsx create mode 100644 apps/docs/content/blog/v2.6.0.mdx rename apps/docs/content/components/alert/{controlled.raw.jsx => controlled-alert.raw.jsx} (100%) create mode 100644 apps/docs/content/components/alert/without-icon-wrapper.raw.jsx create mode 100644 apps/docs/content/components/alert/without-icon-wrapper.ts create mode 100644 apps/docs/content/components/autocomplete/virtualization-custom-item-height.raw.jsx create mode 100644 apps/docs/content/components/autocomplete/virtualization-max-listbox-height.raw.jsx create mode 100644 apps/docs/content/components/autocomplete/virtualization-ten-thousand.raw.jsx create mode 100644 apps/docs/content/components/autocomplete/virtualization.raw.jsx create mode 100644 apps/docs/content/components/form/controlled.raw.jsx create mode 100644 apps/docs/content/components/form/controlled.ts create mode 100644 apps/docs/content/components/form/custom-error-messages.raw.jsx create mode 100644 apps/docs/content/components/form/custom-error-messages.ts create mode 100644 apps/docs/content/components/form/custom-validation.raw.jsx create mode 100644 apps/docs/content/components/form/custom-validation.ts create mode 100644 apps/docs/content/components/form/demo.raw.jsx create mode 100644 apps/docs/content/components/form/demo.ts create mode 100644 apps/docs/content/components/form/events.raw.jsx create mode 100644 apps/docs/content/components/form/events.ts create mode 100644 apps/docs/content/components/form/form-usage.raw.jsx create mode 100644 apps/docs/content/components/form/index.ts create mode 100644 apps/docs/content/components/form/native-validation.raw.jsx create mode 100644 apps/docs/content/components/form/native-validation.ts create mode 100644 apps/docs/content/components/form/real-time-validation.raw.jsx create mode 100644 apps/docs/content/components/form/real-time-validation.ts create mode 100644 apps/docs/content/components/form/server-validation.raw.jsx create mode 100644 apps/docs/content/components/form/server-validation.ts create mode 100644 apps/docs/content/components/form/usage.raw.jsx create mode 100644 apps/docs/content/components/form/usage.ts create mode 100644 apps/docs/content/components/input-otp/input-otp-required.raw.jsx delete mode 100644 apps/docs/content/components/input-otp/usage.raw.tsx create mode 100644 apps/docs/content/components/listbox/virtualization-ten-thousand.raw.jsx create mode 100644 apps/docs/content/components/listbox/virtualization-ten-thousand.ts create mode 100644 apps/docs/content/components/listbox/virtualization.raw.jsx create mode 100644 apps/docs/content/components/listbox/virtualization.ts create mode 100644 apps/docs/content/components/select/virtualization-custom-item-height.raw.jsx create mode 100644 apps/docs/content/components/select/virtualization-custom-item-height.ts create mode 100644 apps/docs/content/components/select/virtualization-max-listbox-height.raw.jsx create mode 100644 apps/docs/content/components/select/virtualization-max-listbox-height.ts create mode 100644 apps/docs/content/components/select/virtualization-ten-thousand.raw.jsx create mode 100644 apps/docs/content/components/select/virtualization-ten-thousand.ts create mode 100644 apps/docs/content/components/select/virtualization.raw.jsx create mode 100644 apps/docs/content/components/select/virtualization.ts create mode 100644 apps/docs/content/docs/components/form.mdx delete mode 100644 apps/docs/content/docs/guide/form.mdx create mode 100644 apps/docs/content/docs/guide/forms.mdx create mode 100644 apps/docs/public/assets/fonts/FiraCode-Bold.woff2 create mode 100644 apps/docs/public/assets/fonts/FiraCode-Medium.woff2 create mode 100644 apps/docs/public/assets/fonts/FiraCode-Regular.woff2 create mode 100644 apps/docs/public/assets/fonts/FiraCode-SemiBold.woff2 create mode 100644 apps/docs/public/assets/fonts/Inter-Black.woff2 create mode 100644 apps/docs/public/assets/fonts/Inter-Bold.woff2 create mode 100644 apps/docs/public/assets/fonts/Inter-ExtraBold.woff2 create mode 100644 apps/docs/public/assets/fonts/Inter-ExtraLight.woff2 create mode 100644 apps/docs/public/assets/fonts/Inter-Light.woff2 create mode 100644 apps/docs/public/assets/fonts/Inter-Medium.woff2 create mode 100644 apps/docs/public/assets/fonts/Inter-Regular.woff2 create mode 100644 apps/docs/public/assets/fonts/Inter-SemiBold.woff2 create mode 100644 apps/docs/public/blog/v2.6.0.jpg create mode 100644 apps/docs/public/blog/v2.6.0_2x.jpg create mode 100644 apps/docs/public/images/nextuipro-section-background-light.webp create mode 100644 apps/docs/public/images/nextuipro-section-background-light@mobile.webp create mode 100644 apps/docs/public/images/nextuipro-section-background.webp create mode 100644 apps/docs/public/images/nextuipro-section-background@mobile.webp delete mode 100644 apps/docs/utils/featurebase.ts create mode 100644 packages/core/theme/src/components/form.ts diff --git a/.changeset/silly-mugs-marry.md b/.changeset/silly-mugs-marry.md deleted file mode 100644 index 277bdf3cee..0000000000 --- a/.changeset/silly-mugs-marry.md +++ /dev/null @@ -1,111 +0,0 @@ ---- -"@nextui-org/accordion": minor -"@nextui-org/alert": minor -"@nextui-org/autocomplete": minor -"@nextui-org/avatar": minor -"@nextui-org/badge": minor -"@nextui-org/breadcrumbs": minor -"@nextui-org/button": minor -"@nextui-org/calendar": minor -"@nextui-org/card": minor -"@nextui-org/checkbox": minor -"@nextui-org/chip": minor -"@nextui-org/code": minor -"@nextui-org/date-input": minor -"@nextui-org/date-picker": minor -"@nextui-org/divider": minor -"@nextui-org/drawer": minor -"@nextui-org/dropdown": minor -"@nextui-org/form": minor -"@nextui-org/image": minor -"@nextui-org/input": minor -"@nextui-org/input-otp": minor -"@nextui-org/kbd": minor -"@nextui-org/link": minor -"@nextui-org/listbox": minor -"@nextui-org/menu": minor -"@nextui-org/modal": minor -"@nextui-org/navbar": minor -"@nextui-org/pagination": minor -"@nextui-org/popover": minor -"@nextui-org/progress": minor -"@nextui-org/radio": minor -"@nextui-org/ripple": minor -"@nextui-org/scroll-shadow": minor -"@nextui-org/select": minor -"@nextui-org/skeleton": minor -"@nextui-org/slider": minor -"@nextui-org/snippet": minor -"@nextui-org/spacer": minor -"@nextui-org/spinner": minor -"@nextui-org/switch": minor -"@nextui-org/table": minor -"@nextui-org/tabs": minor -"@nextui-org/tooltip": minor -"@nextui-org/user": minor -"@nextui-org/react": minor -"@nextui-org/system": minor -"@nextui-org/system-rsc": minor -"@nextui-org/theme": minor -"@nextui-org/use-aria-accordion": minor -"@nextui-org/use-aria-accordion-item": minor -"@nextui-org/use-aria-button": minor -"@nextui-org/use-aria-link": minor -"@nextui-org/use-aria-menu": minor -"@nextui-org/use-aria-modal-overlay": minor -"@nextui-org/use-aria-multiselect": minor -"@nextui-org/use-aria-toggle-button": minor -"@nextui-org/use-callback-ref": minor -"@nextui-org/use-clipboard": minor -"@nextui-org/use-data-scroll-overflow": minor -"@nextui-org/use-disclosure": minor -"@nextui-org/use-draggable": minor -"@nextui-org/use-image": minor -"@nextui-org/use-infinite-scroll": minor -"@nextui-org/use-intersection-observer": minor -"@nextui-org/use-is-mobile": minor -"@nextui-org/use-is-mounted": minor -"@nextui-org/use-measure": minor -"@nextui-org/use-pagination": minor -"@nextui-org/use-real-shape": minor -"@nextui-org/use-ref-state": minor -"@nextui-org/use-resize": minor -"@nextui-org/use-safe-layout-effect": minor -"@nextui-org/use-scroll-position": minor -"@nextui-org/use-ssr": minor -"@nextui-org/use-theme": minor -"@nextui-org/use-update-effect": minor -"@nextui-org/aria-utils": minor -"@nextui-org/dom-animation": minor -"@nextui-org/framer-utils": minor -"@nextui-org/react-rsc-utils": minor -"@nextui-org/react-utils": minor -"@nextui-org/shared-icons": minor -"@nextui-org/shared-utils": minor -"@nextui-org/stories-utils": minor -"@nextui-org/test-utils": minor ---- - -This release includes several improvements and bug fixes: - -- Updated react-aria version across all components -- Improved Drawer styles and transitions -- Fixed missing peer dependencies for framer-motion -- Fixed menu item classNames functionality -- Added isClearable prop to Textarea component -- Fixed label placement issues in Input and Select components -- Improved table keyboard navigation with new isKeyboardNavigationDisabled prop -- Fixed UI sliding issues with helper wrapper in Input and Select -- Updated use-image hook to avoid Next.js hydration issues -- Replaced RTL-specific styles with logical properties -- Fixed textarea label squish issue -- Bumped tailwind-merge version -- Applied tw nested group fixes -- Fixed fullWidth variant in input and select components -- Moved circular-progress tv to progress -- Changed ListboxItem key to optional -- Fixed autocomplete clear button behavior -- Updated Select label placement logic -- Added missing framer-motion peer dependencies -- Removed layoutNode prop from Table due to react-aria update -- Virtualization added to Autocomplete \ No newline at end of file diff --git a/apps/docs/app/docs/[[...slug]]/page.tsx b/apps/docs/app/docs/[[...slug]]/page.tsx index dbb2acc24a..b346c67153 100644 --- a/apps/docs/app/docs/[[...slug]]/page.tsx +++ b/apps/docs/app/docs/[[...slug]]/page.tsx @@ -99,7 +99,7 @@ export default async function DocPage({params}: DocPageProps) {
{headings && headings.length > 0 && ( -
+
)} diff --git a/apps/docs/app/docs/layout.tsx b/apps/docs/app/docs/layout.tsx index 782bb7214e..9ed37fa8ab 100644 --- a/apps/docs/app/docs/layout.tsx +++ b/apps/docs/app/docs/layout.tsx @@ -11,7 +11,7 @@ interface DocsLayoutProps { export default function DocsLayout({children}: DocsLayoutProps) { return ( <> -
+
diff --git a/apps/docs/app/examples/perf/client-page.tsx b/apps/docs/app/examples/perf/client-page.tsx new file mode 100644 index 0000000000..79ab457b0a --- /dev/null +++ b/apps/docs/app/examples/perf/client-page.tsx @@ -0,0 +1,561 @@ +"use client"; + +import { + RadioGroup, + Radio, + Button, + Accordion, + Tabs, + Textarea, + Input, + Tab, + Avatar, + Select, + SelectItem, + AccordionItem, + Pagination, + extendVariants, + PaginationItem, +} from "@nextui-org/react"; +import {useFilter} from "@react-aria/i18n"; +import {useEffect, useMemo, useRef, useState} from "react"; +import {useSearchParams} from "next/navigation"; + +import {SearchLinearIcon} from "@/components/icons"; + +const MyRadioGroup = () => { + const [radio, setRadio] = useState("1"); + + return ( + + Radio 1 + Radio 2 + Radio 3 + Radio 4 + Radio 5 + Radio 6 + Radio 7 + Radio 8 + Radio 9 + Radio 10 + Radio 11 + Radio 12 + Radio 13 + Radio 14 + Radio 15 + Radio 16 + Radio 17 + Radio 18 + Radio 19 + Radio 20 + Radio 21 + Radio 22 + Radio 23 + Radio 24 + Radio 25 + Radio 26 + Radio 27 + Radio 28 + Radio 29 + Radio 30 + Radio 31 + Radio 32 + Radio 33 + Radio 34 + Radio 35 + Radio 36 + Radio 37 + Radio 38 + Radio 39 + Radio 40 + Radio 41 + Radio 42 + Radio 43 + Radio 44 + Radio 45 + Radio 46 + Radio 47 + Radio 48 + Radio 49 + Radio 50 + Radio 51 + Radio 52 + Radio 53 + Radio 54 + Radio 55 + Radio 56 + Radio 57 + Radio 58 + Radio 59 + Radio 60 + Radio 61 + Radio 62 + + ); +}; + +const MyInput = extendVariants(Input, { + variants: { + color: { + stone: { + inputWrapper: [ + "bg-zinc-100", + "border", + "shadow", + "transition-colors", + "focus-within:bg-zinc-100", + "data-[hover=true]:border-zinc-600", + "data-[hover=true]:bg-zinc-100", + "group-data-[focus=true]:border-zinc-600", + // dark theme + "dark:bg-zinc-900", + "dark:border-zinc-800", + "dark:data-[hover=true]:bg-zinc-900", + "dark:focus-within:bg-zinc-900", + ], + input: [ + "text-zinc-800", + "placeholder:text-zinc-600", + // dark theme + "dark:text-zinc-400", + "dark:placeholder:text-zinc-600", + ], + }, + }, + size: { + xs: { + inputWrapper: "h-6 min-h-6 px-1", + input: "text-tiny", + }, + md: { + inputWrapper: "h-10 min-h-10", + input: "text-small", + }, + xl: { + inputWrapper: "h-14 min-h-14", + input: "text-medium", + }, + }, + radius: { + xs: { + inputWrapper: "rounded", + }, + sm: { + inputWrapper: "rounded-[4px]", + }, + }, + textSize: { + base: { + input: "text-base", + }, + }, + removeLabel: { + true: { + label: "hidden", + }, + false: {}, + }, + }, + defaultVariants: { + color: "stone", + textSize: "base", + removeLabel: true, + }, +}); + +const MyButton2 = extendVariants(Button, { + variants: { + color: { + foreground: + "bg-foreground text-background data-[hover=true]:bg-foreground/90 data-[pressed=true]:bg-foreground/80", + }, + isScalable: { + true: "scale-125", + false: "", + }, + size: { + xl: "size--xl", + "2xl": "size--2xl", + }, + mySize: { + lg: "px-12 py-6 text-lg", + xl: "px-12 py-6 text-xl", + }, + }, + defaultVariants: { + color: "foreground", + }, +}); + +const usersData = [ + { + id: 1, + name: "Tony Reichert", + role: "CEO", + team: "Management", + status: "active", + age: "29", + avatar: "https://d2u8k2ocievbld.cloudfront.net/memojis/male/1.png", + email: "tony.reichert@example.com", + }, + { + id: 2, + name: "Zoey Lang", + role: "Tech Lead", + team: "Development", + status: "paused", + age: "25", + avatar: "https://d2u8k2ocievbld.cloudfront.net/memojis/female/1.png", + email: "zoey.lang@example.com", + }, + { + id: 3, + name: "Jane Fisher", + role: "Sr. Dev", + team: "Development", + status: "active", + age: "22", + avatar: "https://d2u8k2ocievbld.cloudfront.net/memojis/female/2.png", + email: "jane.fisher@example.com", + }, + { + id: 4, + name: "William Howard", + role: "C.M.", + team: "Marketing", + status: "vacation", + age: "28", + avatar: "https://d2u8k2ocievbld.cloudfront.net/memojis/male/2.png", + email: "william.howard@example.com", + }, + { + id: 5, + name: "Kristen Copper", + role: "S. Manager", + team: "Sales", + status: "active", + age: "24", + avatar: "https://d2u8k2ocievbld.cloudfront.net/memojis/female/3.png", + email: "kristen.cooper@example.com", + }, + { + id: 6, + name: "Brian Kim", + role: "P. Manager", + team: "Management", + age: "29", + avatar: "https://d2u8k2ocievbld.cloudfront.net/memojis/male/3.png", + email: "brian.kim@example.com", + status: "active", + }, + { + id: 7, + name: "Michael Hunt", + role: "Designer", + team: "Design", + status: "paused", + age: "27", + avatar: "https://d2u8k2ocievbld.cloudfront.net/memojis/male/4.png", + email: "michael.hunt@example.com", + }, + { + id: 8, + name: "Samantha Brooks", + role: "HR Manager", + team: "HR", + status: "active", + age: "31", + avatar: "https://d2u8k2ocievbld.cloudfront.net/memojis/female/4.png", + email: "samantha.brooks@example.com", + }, + { + id: 9, + name: "Frank Harrison", + role: "F. Manager", + team: "Finance", + status: "vacation", + age: "33", + avatar: "https://d2u8k2ocievbld.cloudfront.net/memojis/male/5.png", + email: "frank.harrison@example.com", + }, + { + id: 10, + name: "Emma Adams", + role: "Ops Manager", + team: "Operations", + status: "active", + age: "35", + avatar: "https://d2u8k2ocievbld.cloudfront.net/memojis/female/5.png", + email: "emma.adams@example.com", + }, + { + id: 11, + name: "Brandon Stevens", + role: "Jr. Dev", + team: "Development", + status: "active", + age: "22", + avatar: "https://d2u8k2ocievbld.cloudfront.net/memojis/male/7.png", + email: "brandon.stevens@example.com", + }, + { + id: 12, + name: "Megan Richards", + role: "P. Manager", + team: "Product", + status: "paused", + age: "28", + avatar: "https://d2u8k2ocievbld.cloudfront.net/memojis/female/7.png", + email: "megan.richards@example.com", + }, + { + id: 13, + name: "Oliver Scott", + role: "S. Manager", + team: "Security", + status: "active", + age: "37", + avatar: "https://d2u8k2ocievbld.cloudfront.net/memojis/male/8.png", + email: "oliver.scott@example.com", + }, + { + id: 14, + name: "Grace Allen", + role: "M. Specialist", + team: "Marketing", + status: "active", + age: "30", + avatar: "https://d2u8k2ocievbld.cloudfront.net/memojis/female/8.png", + email: "grace.allen@example.com", + }, + { + id: 15, + name: "Noah Carter", + role: "IT Specialist", + team: "I. Technology", + status: "paused", + age: "31", + avatar: "https://d2u8k2ocievbld.cloudfront.net/memojis/male/9.png", + email: "noah.carter@example.com", + }, + { + id: 16, + name: "Ava Perez", + role: "Manager", + team: "Sales", + status: "active", + age: "29", + avatar: "https://d2u8k2ocievbld.cloudfront.net/memojis/female/9.png", + email: "ava.perez@example.com", + }, + { + id: 17, + name: "Liam Johnson", + role: "Data Analyst", + team: "Analysis", + status: "active", + age: "28", + avatar: "https://d2u8k2ocievbld.cloudfront.net/memojis/male/11.png", + email: "liam.johnson@example.com", + }, + { + id: 18, + name: "Sophia Taylor", + role: "QA Analyst", + team: "Testing", + status: "active", + age: "27", + avatar: "https://d2u8k2ocievbld.cloudfront.net/memojis/female/11.png", + email: "sophia.taylor@example.com", + }, + { + id: 19, + name: "Lucas Harris", + role: "Administrator", + team: "Information Technology", + status: "paused", + age: "32", + avatar: "https://d2u8k2ocievbld.cloudfront.net/memojis/male/12.png", + email: "lucas.harris@example.com", + }, + { + id: 20, + name: "Mia Robinson", + role: "Coordinator", + team: "Operations", + status: "active", + age: "26", + avatar: "https://d2u8k2ocievbld.cloudfront.net/memojis/female/12.png", + email: "mia.robinson@example.com", + }, +]; + +export default function NextUIPerf() { + const [textA, setTextA] = useState(""); + const [textB, setTextB] = useState(""); + const [textC, setTextC] = useState(""); + const [isOpen, setIsOpen] = useState(false); + const [inputValue, setInputValue] = useState(); + const [selectedKey, setSelectedKey] = useState(""); + + const searchParams = useSearchParams(); + + const page = Number(searchParams.get("page")); + + let {startsWith} = useFilter({sensitivity: "base"}); + + const filteredItems = inputValue + ? usersData.filter((item) => startsWith(item.name, inputValue)) + : usersData; + + const inputRef = useRef(null); + + useEffect(() => { + isOpen && inputRef?.current?.focus(); + }, [isOpen]); + + const handleSelectionChange = (e: React.ChangeEvent) => { + setSelectedKey(e.target.value); + }; + + const topContent = useMemo(() => { + return ( + } + type="text" + onValueChange={setInputValue} + /> + ); + }, [inputRef, selectedKey, isOpen]); + + return ( +
+ + + + + Non est aliqua tempor occaecat laborum. Lorem culpa minim irure mollit. Est qui + reprehenderit commodo magna proident anim ipsum ex. Mollit id amet officia nisi excepteur + eu. Commodo elit commodo nisi nisi aute eu aliquip aliquip voluptate exercitation ullamco + ipsum eiusmod veniam. Magna in laborum anim amet anim ex elit aliqua nostrud mollit. + Pariatur ullamco cillum proident aliqua nostrud. Labore ea veniam cillum duis veniam in + cupidatat voluptate eu officia. Ut laborum sunt nostrud magna. Ex magna esse cillum enim + incididunt pariatur qui veniam dolor. Exercitation id culpa et enim mollit duis duis + aliquip. Magna ullamco est cupidatat laboris irure pariatur aliquip duis aute cillum. + Officia irure do laboris ea nisi sunt reprehenderit laboris irure. Ex eiusmod in duis + veniam excepteur. Sunt et et laboris culpa. Mollit excepteur occaecat elit anim officia. + Laborum commodo proident cupidatat pariatur eu veniam id qui do culpa. Quis consectetur + adipisicing anim ex ea velit excepteur. Deserunt laboris ex aute sunt laborum tempor ea + enim dolore ut in. Id aliqua Lorem exercitation qui velit nostrud anim reprehenderit enim. + Nisi elit fugiat deserunt elit. Sit excepteur ipsum enim excepteur irure irure sint veniam + elit consequat ea id. Lorem ea qui sunt enim occaecat excepteur officia ex consequat + nostrud. Tempor sint Lorem est culpa do. + + + Non est aliqua tempor occaecat laborum. Lorem culpa minim irure mollit. Est qui + reprehenderit commodo magna proident anim ipsum ex. Mollit id amet officia nisi excepteur + eu. Commodo elit commodo nisi nisi aute eu aliquip aliquip voluptate exercitation ullamco + ipsum eiusmod veniam. Magna in laborum anim amet anim ex elit aliqua nostrud mollit. + Pariatur ullamco cillum proident aliqua nostrud. Labore ea veniam cillum duis veniam in + cupidatat voluptate eu officia. Ut laborum sunt nostrud magna. Ex magna esse cillum enim + + + Non est aliqua tempor occaecat laborum. Lorem culpa minim irure mollit. Est qui + reprehenderit commodo magna proident anim ipsum ex. Mollit id amet officia nisi excepteur + eu. Commodo elit commodo nisi nisi aute eu aliquip aliquip voluptate exercitation ullamco + ipsum eiusmod veniam. Magna in laborum anim amet anim ex elit aliqua nostrud mollit. + Pariatur ullamco cillum proident aliqua nostrud. Labore ea veniam cillum duis veniam in + + + + +