diff --git a/.changeset/witty-socks-bathe.md b/.changeset/witty-socks-bathe.md deleted file mode 100644 index ff37b1abd8..0000000000 --- a/.changeset/witty-socks-bathe.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@nextui-org/theme": patch ---- - -add missing `data-[hover=true]:` for ghost button with danger color diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index 2de89b8dd1..e8f6cc03d3 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -6,6 +6,6 @@ contact_links: - name: 💬 Discord Community Chat url: https://discord.gg/9b6yyZKmH4 about: Ask quick questions or simply chat on the `NextUI` community Discord server. - - name: 💬 New Updates (Twitter) - url: https://twitter.com/getnextui - about: Link to our twitter account if you want to follow us and stay up to date with NextUI news + - name: 💬 New Updates (X) + url: https://x.com/getnextui + about: Link to our X account if you want to follow us and stay up to date with NextUI news diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 2c16ffb5d9..9c4ff17f0c 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -11,15 +11,15 @@ Closes # ## 📝 Description -> Add a brief description + ## ⛳️ Current behavior (updates) -> Please describe the current behavior that you are modifying + ## 🚀 New behavior -> Please describe the behavior or changes this PR adds + ## 💣 Is this a breaking change (Yes/No): diff --git a/.github/workflows/enter-pre-release-mode.yaml b/.github/workflows/enter-pre-release-mode.yaml new file mode 100644 index 0000000000..77e8ef273c --- /dev/null +++ b/.github/workflows/enter-pre-release-mode.yaml @@ -0,0 +1,35 @@ +name: Enter pre-release mode + +on: workflow_dispatch +jobs: + enter-pre-release-mode: + if: ${{ github.ref == 'refs/heads/beta/release-next' || github.ref == 'refs/heads/canary' }} + runs-on: ubuntu-latest + permissions: + contents: write + pull-requests: write + id-token: write + steps: + - name: Checkout branch + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Install + uses: ./.github/common-actions/install + + - name: Enter pre-release mode + id: enter-pre-release-mode + env: + GITHUB_TOKEN: ${{ secrets.GA_ACCESS_TOKEN }} + run: | + git config user.email "41898282+github-actions[bot]@users.noreply.github.com" + git config user.name "github-actions[bot]" + if [ ${{ github.ref }} == 'refs/heads/canary' ]; then + pnpm changeset:canary + else + pnpm changeset:beta + fi + git add -A + git commit -m 'chore(pre-release): enter pre-release mode' + git push \ No newline at end of file diff --git a/.github/workflows/exit-pre-release-mode.yaml b/.github/workflows/exit-pre-release-mode.yaml new file mode 100644 index 0000000000..d8cf71a470 --- /dev/null +++ b/.github/workflows/exit-pre-release-mode.yaml @@ -0,0 +1,39 @@ +name: Exit pre-release mode + +on: workflow_dispatch +jobs: + exit-pre-release-mode: + if: ${{ github.ref == 'refs/heads/beta/release-next' || github.ref == 'refs/heads/canary' }} + name: exit pre-release mode + runs-on: ubuntu-latest + permissions: + contents: write + pull-requests: write + id-token: write + + steps: + - name: Checkout branch + uses: actions/checkout@v4 + with: + ref: ${{ github.event.inputs.branch }} + fetch-depth: 0 + + - name: Install + uses: ./.github/common-actions/install + + - name: remove pre.json + # we only remove .changeset/pre.json here + # since we want to keep the changeset files introduced in beta/release-next or canary branch + # once we merge it to canary / main, those files will be removed in version PR in canary + # and converted to corresponding changelogs + run: npx rimraf .changeset/pre.json + + - name: Commit and push changes + env: + GITHUB_TOKEN: ${{ secrets.GA_ACCESS_TOKEN }} + run: | + git config user.email "41898282+github-actions[bot]@users.noreply.github.com" + git config user.name "github-actions[bot]" + git add -A + git commit -m "ci(changesets): exit pre-release mode" + git push \ No newline at end of file diff --git a/.github/workflows/pre-release.yaml b/.github/workflows/pre-release.yaml new file mode 100644 index 0000000000..729f055cd5 --- /dev/null +++ b/.github/workflows/pre-release.yaml @@ -0,0 +1,81 @@ +name: Pre-release + +on: + push: + paths: + - ".changeset/**" + - "packages/**" + branches: + - "beta/release-next" + +concurrency: ${{ github.workflow }}-${{ github.ref }} + +jobs: + prerelease: + name: changesets pre-release + runs-on: ubuntu-latest + timeout-minutes: 30 + permissions: + contents: write + pull-requests: write + id-token: write + steps: + - name: Checkout branch + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Install + uses: ./.github/common-actions/install + + - name: Debug condition values + run: | + echo "pre.json exists: ${{ steps.check_if_pre_json_exists.outputs.files_exists }}" + echo "Commit message: ${{ github.event.head_commit.message }}" + echo "Contains version packages: ${{ contains(github.event.head_commit.message, 'ci(changesets): version packages') }}" + echo "Full condition would be: ${{ steps.check_if_pre_json_exists.outputs.files_exists == 'true' && contains(github.event.head_commit.message, 'ci(changesets): version packages') }}" + + - name: Check if pre.json exists + id: check_if_pre_json_exists + uses: andstor/file-existence-action@v3.0.0 + with: + files: ".changeset/pre.json" + + - name: Get pre-release changesets + id: get-pre-release-changesets + uses: notiz-dev/github-action-json-property@release + with: + path: ".changeset/pre.json" + prop_path: "changesets" + + - name: Create pre-release PR + id: create-pre-release-pr + if: "${{ steps.check_if_pre_json_exists.outputs.files_exists == 'true' && !startsWith(github.event.head_commit.message, 'ci(changesets): version packages') }}" + uses: changesets/action@v1 + with: + version: pnpm run version + title: "ci(changesets): :package: version packages" + commit: "ci(changesets): version packages" + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Tests + if: "${{ steps.check_if_pre_json_exists.outputs.files_exists == 'true' && contains(github.event.head_commit.message, 'ci(changesets): version packages') }}" + run: pnpm test + + - name: Build + if: "${{ steps.check_if_pre_json_exists.outputs.files_exists == 'true' && contains(github.event.head_commit.message, 'ci(changesets): version packages') }}" + run: pnpm build + env: + NODE_OPTIONS: "--max-old-space-size=4096" + + - name: Publish to NPM + id: publish-to-npm + if: "${{ steps.check_if_pre_json_exists.outputs.files_exists == 'true' && contains(github.event.head_commit.message, 'ci(changesets): version packages') }}" + uses: changesets/action@v1 + with: + publish: pnpm run release + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 9d364c0602..9da665a574 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -15,6 +15,7 @@ jobs: release: name: Release runs-on: ubuntu-latest + timeout-minutes: 30 steps: - name: Checkout branch uses: actions/checkout@v4 @@ -22,12 +23,12 @@ jobs: - name: Install uses: ./.github/common-actions/install - - name: Build - run: pnpm build - - name: Tests run: pnpm test + - name: Build + run: pnpm build + - name: Create Release Pull Request or Publish to NPM id: changesets uses: changesets/action@v1 @@ -41,17 +42,9 @@ jobs: NPM_TOKEN: ${{ secrets.NPM_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - name: Sync files from canary to main branch if a publish happens - if: steps.changesets.outputs.published == 'true' - run: | - curl -X POST \ - -H "Accept: application/vnd.github.v3+json" \ - -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \ - https://api.github.com/repos/owner/repo/dispatches \ - -d '{"event_type":"sync-canary-to-main"}' - - name: Create canary release if: steps.changesets.outputs.published != 'true' + timeout-minutes: 15 run: | git checkout canary pnpm version:canary diff --git a/.github/workflows/sync-canary-to-main.yaml b/.github/workflows/sync-canary-to-main.yaml deleted file mode 100644 index c03f5cfde7..0000000000 --- a/.github/workflows/sync-canary-to-main.yaml +++ /dev/null @@ -1,43 +0,0 @@ -name: Sync Canary to Main - -on: - # triggered manually in Github - workflow_dispatch: - # triggered by the type "sync-canary-to-main" (e.g. from release action after publishing) - repository_dispatch: - types: [sync-canary-to-main] - -jobs: - create_pull_request: - runs-on: ubuntu-latest - steps: - - name: Checkout code - uses: actions/checkout@v4 - with: - fetch-depth: 0 # Ensure all history is fetched - - - name: Create Pull Request - uses: repo-sync/pull-request@v2 - with: - github_token: ${{ secrets.GITHUB_TOKEN }} - source_branch: "canary" - destination_branch: "main" - pr_title: "Auto-sync Canary to Main" - pr_body: | - ## Automated: Sync from Canary to Main - - This Pull Request is automatically generated to sync the changes from the Canary branch to the Main branch. Below are the included updates: - - ### Triggered by a Direct Push to Canary: - - Please check the recent commits on the Canary branch directly as this sync may include multiple changes. - - ### Triggered by a Pull Request Merge: - - Merged Pull Request: [PR#${{ github.event.pull_request.number }}](${{ github.event.pull_request.html_url }}) - ${{ github.event.pull_request.title }} - - PR Description: ${{ github.event.pull_request.body }} - - Merged by: ${{ github.event.pull_request.merged_by.login }} - - ### Action Required: - - Please review the changes carefully. - - Approve and merge the Pull Request if everything is in order. - - Thank you for maintaining the Main branch updated and clean. diff --git a/.github/workflows/update-stats.yml b/.github/workflows/update-stats.yml new file mode 100644 index 0000000000..3ea0fd4819 --- /dev/null +++ b/.github/workflows/update-stats.yml @@ -0,0 +1,42 @@ +name: Update Stats + +on: + schedule: + # Runs every Monday at 00:00 UTC + - cron: '0 0 * * 1' + # Allow manual trigger + workflow_dispatch: + +jobs: + update-stats: + name: Update Stats + runs-on: ubuntu-latest + steps: + - name: Checkout branch + uses: actions/checkout@v4 + + - name: Install + uses: ./.github/common-actions/install + + - name: Update search metadata + run: pnpm update:search-meta + + - name: Update GitHub info + run: pnpm update:github-info + + - name: Create Pull Request + uses: peter-evans/create-pull-request@v5 + with: + commit-message: "chore(stats): update project statistics" + title: "chore(stats): 📊 Update project statistics" + body: | + This PR updates the project statistics including: + - Search metadata + - GitHub repository information + + This is an automated PR generated weekly. + branch: chore/update-stats + base: main + delete-branch: true + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.gitignore b/.gitignore index 9fca9efca5..69a0d91f51 100644 --- a/.gitignore +++ b/.gitignore @@ -56,6 +56,7 @@ packages/**/*.backup.ts # ignore sitemap apps/**/sitemap.xml +apps/**/sitemap-0.xml # turbo .turbo diff --git a/.husky/post-merge b/.husky/post-merge new file mode 100755 index 0000000000..e20e0849a6 --- /dev/null +++ b/.husky/post-merge @@ -0,0 +1,5 @@ +#!/usr/bin/env sh +huskyDir=$(dirname -- "$0") +. "$huskyDir/_/husky.sh" + +. "$huskyDir/scripts/update-dep" diff --git a/.husky/post-rebase b/.husky/post-rebase new file mode 100755 index 0000000000..e20e0849a6 --- /dev/null +++ b/.husky/post-rebase @@ -0,0 +1,5 @@ +#!/usr/bin/env sh +huskyDir=$(dirname -- "$0") +. "$huskyDir/_/husky.sh" + +. "$huskyDir/scripts/update-dep" diff --git a/.husky/scripts/update-dep b/.husky/scripts/update-dep new file mode 100644 index 0000000000..1e569b495b --- /dev/null +++ b/.husky/scripts/update-dep @@ -0,0 +1,11 @@ +#!/usr/bin/env sh +changed_files="$(git diff-tree -r --name-only --no-commit-id ORIG_HEAD HEAD)" + +check_run() { + if (echo "$changed_files" | grep --quiet "$1"); then + printf "\033[36mDetected changes in pnpm-lock.yaml, starting dependency update\033[0m\n" + eval "$2" + fi +} + +check_run pnpm-lock.yaml "pnpm install --color" diff --git a/.vscode/settings.json b/.vscode/settings.json index c531e733d0..6b36bf07d3 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -10,5 +10,5 @@ }, "tailwindCSS.experimental.classRegex": [ ["([\"'`][^\"'`]*.*?[\"'`])", "[\"'`]([^\"'`]*).*?[\"'`]"] - ] + ], } diff --git a/apps/docs/.eslintrc.json b/apps/docs/.eslintrc.json index 23dda4847f..bf12dab1cd 100644 --- a/apps/docs/.eslintrc.json +++ b/apps/docs/.eslintrc.json @@ -3,7 +3,7 @@ "ignorePatterns": ["!**/*"], "overrides": [ { - "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], + "files": ["*.ts", "*.tsx"], "parserOptions": { "project": ["apps/docs/tsconfig(.*)?.json"], "ecmaFeatures": { @@ -22,10 +22,6 @@ { "files": ["*.ts", "*.tsx"], "rules": {} - }, - { - "files": ["*.js", "*.jsx"], - "rules": {} } ] } diff --git a/apps/docs/app/blog/[slug]/page.tsx b/apps/docs/app/blog/[slug]/page.tsx index f62a849e0d..e3dab232d4 100644 --- a/apps/docs/app/blog/[slug]/page.tsx +++ b/apps/docs/app/blog/[slug]/page.tsx @@ -1,7 +1,7 @@ import type {Metadata} from "next"; import {notFound} from "next/navigation"; -import {allBlogPosts} from "contentlayer/generated"; +import {allBlogPosts} from "contentlayer2/generated"; import {Link, User} from "@nextui-org/react"; import {format, parseISO} from "date-fns"; import NextLink from "next/link"; diff --git a/apps/docs/app/blog/page.tsx b/apps/docs/app/blog/page.tsx index 4662e294a1..b19c5eb92b 100644 --- a/apps/docs/app/blog/page.tsx +++ b/apps/docs/app/blog/page.tsx @@ -1,4 +1,4 @@ -import {allBlogPosts} from "contentlayer/generated"; +import {allBlogPosts} from "contentlayer2/generated"; import {compareDesc} from "date-fns"; import {BlogPostList} from "@/components/blog-post"; diff --git a/apps/docs/app/docs/[[...slug]]/page.tsx b/apps/docs/app/docs/[[...slug]]/page.tsx index 858865c0bd..dbb2acc24a 100644 --- a/apps/docs/app/docs/[[...slug]]/page.tsx +++ b/apps/docs/app/docs/[[...slug]]/page.tsx @@ -1,7 +1,7 @@ import type {Metadata} from "next"; import {notFound} from "next/navigation"; -import {allDocs} from "contentlayer/generated"; +import {allDocs} from "contentlayer2/generated"; import {Link} from "@nextui-org/react"; import {MDXContent} from "@/components/mdx-content"; 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 + + + + +