Full Code of satnaing/shadcn-admin for AI

main 8747b9a2b8f3 cached
238 files
525.1 KB
141.8k tokens
435 symbols
1 requests
Download .txt
Showing preview only (580K chars total). Download the full file or copy to clipboard to get everything.
Repository: satnaing/shadcn-admin
Branch: main
Commit: 8747b9a2b8f3
Files: 238
Total size: 525.1 KB

Directory structure:
gitextract_5m319v_v/

├── .github/
│   ├── CODE_OF_CONDUCT.md
│   ├── CONTRIBUTING.md
│   ├── FUNDING.yml
│   ├── ISSUE_TEMPLATE/
│   │   ├── config.yml
│   │   ├── ✨-feature-request.md
│   │   └── 🐞-bug-report.md
│   ├── PULL_REQUEST_TEMPLATE.md
│   └── workflows/
│       ├── ci.yml
│       └── stale.yml
├── .gitignore
├── .prettierignore
├── .prettierrc
├── CHANGELOG.md
├── LICENSE
├── README.md
├── components.json
├── cz.yaml
├── eslint.config.js
├── index.html
├── knip.config.ts
├── netlify.toml
├── package.json
├── src/
│   ├── assets/
│   │   ├── brand-icons/
│   │   │   ├── icon-discord.tsx
│   │   │   ├── icon-docker.tsx
│   │   │   ├── icon-facebook.tsx
│   │   │   ├── icon-figma.tsx
│   │   │   ├── icon-github.tsx
│   │   │   ├── icon-gitlab.tsx
│   │   │   ├── icon-gmail.tsx
│   │   │   ├── icon-medium.tsx
│   │   │   ├── icon-notion.tsx
│   │   │   ├── icon-skype.tsx
│   │   │   ├── icon-slack.tsx
│   │   │   ├── icon-stripe.tsx
│   │   │   ├── icon-telegram.tsx
│   │   │   ├── icon-trello.tsx
│   │   │   ├── icon-whatsapp.tsx
│   │   │   ├── icon-zoom.tsx
│   │   │   └── index.ts
│   │   ├── clerk-full-logo.tsx
│   │   ├── clerk-logo.tsx
│   │   ├── custom/
│   │   │   ├── icon-dir.tsx
│   │   │   ├── icon-layout-compact.tsx
│   │   │   ├── icon-layout-default.tsx
│   │   │   ├── icon-layout-full.tsx
│   │   │   ├── icon-sidebar-floating.tsx
│   │   │   ├── icon-sidebar-inset.tsx
│   │   │   ├── icon-sidebar-sidebar.tsx
│   │   │   ├── icon-theme-dark.tsx
│   │   │   ├── icon-theme-light.tsx
│   │   │   └── icon-theme-system.tsx
│   │   └── logo.tsx
│   ├── components/
│   │   ├── coming-soon.tsx
│   │   ├── command-menu.tsx
│   │   ├── config-drawer.tsx
│   │   ├── confirm-dialog.tsx
│   │   ├── data-table/
│   │   │   ├── bulk-actions.tsx
│   │   │   ├── column-header.tsx
│   │   │   ├── faceted-filter.tsx
│   │   │   ├── index.ts
│   │   │   ├── pagination.tsx
│   │   │   ├── toolbar.tsx
│   │   │   └── view-options.tsx
│   │   ├── date-picker.tsx
│   │   ├── layout/
│   │   │   ├── app-sidebar.tsx
│   │   │   ├── app-title.tsx
│   │   │   ├── authenticated-layout.tsx
│   │   │   ├── data/
│   │   │   │   └── sidebar-data.ts
│   │   │   ├── header.tsx
│   │   │   ├── main.tsx
│   │   │   ├── nav-group.tsx
│   │   │   ├── nav-user.tsx
│   │   │   ├── team-switcher.tsx
│   │   │   ├── top-nav.tsx
│   │   │   └── types.ts
│   │   ├── learn-more.tsx
│   │   ├── long-text.tsx
│   │   ├── navigation-progress.tsx
│   │   ├── password-input.tsx
│   │   ├── profile-dropdown.tsx
│   │   ├── search.tsx
│   │   ├── select-dropdown.tsx
│   │   ├── sign-out-dialog.tsx
│   │   ├── skip-to-main.tsx
│   │   ├── theme-switch.tsx
│   │   └── ui/
│   │       ├── alert-dialog.tsx
│   │       ├── alert.tsx
│   │       ├── avatar.tsx
│   │       ├── badge.tsx
│   │       ├── button.tsx
│   │       ├── calendar.tsx
│   │       ├── card.tsx
│   │       ├── checkbox.tsx
│   │       ├── collapsible.tsx
│   │       ├── command.tsx
│   │       ├── dialog.tsx
│   │       ├── dropdown-menu.tsx
│   │       ├── form.tsx
│   │       ├── input-otp.tsx
│   │       ├── input.tsx
│   │       ├── label.tsx
│   │       ├── popover.tsx
│   │       ├── radio-group.tsx
│   │       ├── scroll-area.tsx
│   │       ├── select.tsx
│   │       ├── separator.tsx
│   │       ├── sheet.tsx
│   │       ├── sidebar.tsx
│   │       ├── skeleton.tsx
│   │       ├── sonner.tsx
│   │       ├── switch.tsx
│   │       ├── table.tsx
│   │       ├── tabs.tsx
│   │       ├── textarea.tsx
│   │       └── tooltip.tsx
│   ├── config/
│   │   └── fonts.ts
│   ├── context/
│   │   ├── direction-provider.tsx
│   │   ├── font-provider.tsx
│   │   ├── layout-provider.tsx
│   │   ├── search-provider.tsx
│   │   └── theme-provider.tsx
│   ├── features/
│   │   ├── apps/
│   │   │   ├── data/
│   │   │   │   └── apps.tsx
│   │   │   └── index.tsx
│   │   ├── auth/
│   │   │   ├── auth-layout.tsx
│   │   │   ├── forgot-password/
│   │   │   │   ├── components/
│   │   │   │   │   └── forgot-password-form.tsx
│   │   │   │   └── index.tsx
│   │   │   ├── otp/
│   │   │   │   ├── components/
│   │   │   │   │   └── otp-form.tsx
│   │   │   │   └── index.tsx
│   │   │   ├── sign-in/
│   │   │   │   ├── components/
│   │   │   │   │   └── user-auth-form.tsx
│   │   │   │   ├── index.tsx
│   │   │   │   └── sign-in-2.tsx
│   │   │   └── sign-up/
│   │   │       ├── components/
│   │   │       │   └── sign-up-form.tsx
│   │   │       └── index.tsx
│   │   ├── chats/
│   │   │   ├── components/
│   │   │   │   └── new-chat.tsx
│   │   │   ├── data/
│   │   │   │   ├── chat-types.ts
│   │   │   │   └── convo.json
│   │   │   └── index.tsx
│   │   ├── dashboard/
│   │   │   ├── components/
│   │   │   │   ├── analytics-chart.tsx
│   │   │   │   ├── analytics.tsx
│   │   │   │   ├── overview.tsx
│   │   │   │   └── recent-sales.tsx
│   │   │   └── index.tsx
│   │   ├── errors/
│   │   │   ├── forbidden.tsx
│   │   │   ├── general-error.tsx
│   │   │   ├── maintenance-error.tsx
│   │   │   ├── not-found-error.tsx
│   │   │   └── unauthorized-error.tsx
│   │   ├── settings/
│   │   │   ├── account/
│   │   │   │   ├── account-form.tsx
│   │   │   │   └── index.tsx
│   │   │   ├── appearance/
│   │   │   │   ├── appearance-form.tsx
│   │   │   │   └── index.tsx
│   │   │   ├── components/
│   │   │   │   ├── content-section.tsx
│   │   │   │   └── sidebar-nav.tsx
│   │   │   ├── display/
│   │   │   │   ├── display-form.tsx
│   │   │   │   └── index.tsx
│   │   │   ├── index.tsx
│   │   │   ├── notifications/
│   │   │   │   ├── index.tsx
│   │   │   │   └── notifications-form.tsx
│   │   │   └── profile/
│   │   │       ├── index.tsx
│   │   │       └── profile-form.tsx
│   │   ├── tasks/
│   │   │   ├── components/
│   │   │   │   ├── data-table-bulk-actions.tsx
│   │   │   │   ├── data-table-row-actions.tsx
│   │   │   │   ├── tasks-columns.tsx
│   │   │   │   ├── tasks-dialogs.tsx
│   │   │   │   ├── tasks-import-dialog.tsx
│   │   │   │   ├── tasks-multi-delete-dialog.tsx
│   │   │   │   ├── tasks-mutate-drawer.tsx
│   │   │   │   ├── tasks-primary-buttons.tsx
│   │   │   │   ├── tasks-provider.tsx
│   │   │   │   └── tasks-table.tsx
│   │   │   ├── data/
│   │   │   │   ├── data.tsx
│   │   │   │   ├── schema.ts
│   │   │   │   └── tasks.ts
│   │   │   └── index.tsx
│   │   └── users/
│   │       ├── components/
│   │       │   ├── data-table-bulk-actions.tsx
│   │       │   ├── data-table-row-actions.tsx
│   │       │   ├── users-action-dialog.tsx
│   │       │   ├── users-columns.tsx
│   │       │   ├── users-delete-dialog.tsx
│   │       │   ├── users-dialogs.tsx
│   │       │   ├── users-invite-dialog.tsx
│   │       │   ├── users-multi-delete-dialog.tsx
│   │       │   ├── users-primary-buttons.tsx
│   │       │   ├── users-provider.tsx
│   │       │   └── users-table.tsx
│   │       ├── data/
│   │       │   ├── data.ts
│   │       │   ├── schema.ts
│   │       │   └── users.ts
│   │       └── index.tsx
│   ├── hooks/
│   │   ├── use-dialog-state.tsx
│   │   ├── use-mobile.tsx
│   │   └── use-table-url-state.ts
│   ├── lib/
│   │   ├── cookies.ts
│   │   ├── handle-server-error.ts
│   │   ├── show-submitted-data.tsx
│   │   └── utils.ts
│   ├── main.tsx
│   ├── routeTree.gen.ts
│   ├── routes/
│   │   ├── (auth)/
│   │   │   ├── forgot-password.tsx
│   │   │   ├── otp.tsx
│   │   │   ├── sign-in-2.tsx
│   │   │   ├── sign-in.tsx
│   │   │   └── sign-up.tsx
│   │   ├── (errors)/
│   │   │   ├── 401.tsx
│   │   │   ├── 403.tsx
│   │   │   ├── 404.tsx
│   │   │   ├── 500.tsx
│   │   │   └── 503.tsx
│   │   ├── __root.tsx
│   │   ├── _authenticated/
│   │   │   ├── apps/
│   │   │   │   └── index.tsx
│   │   │   ├── chats/
│   │   │   │   └── index.tsx
│   │   │   ├── errors/
│   │   │   │   └── $error.tsx
│   │   │   ├── help-center/
│   │   │   │   └── index.tsx
│   │   │   ├── index.tsx
│   │   │   ├── route.tsx
│   │   │   ├── settings/
│   │   │   │   ├── account.tsx
│   │   │   │   ├── appearance.tsx
│   │   │   │   ├── display.tsx
│   │   │   │   ├── index.tsx
│   │   │   │   ├── notifications.tsx
│   │   │   │   └── route.tsx
│   │   │   ├── tasks/
│   │   │   │   └── index.tsx
│   │   │   └── users/
│   │   │       └── index.tsx
│   │   └── clerk/
│   │       ├── (auth)/
│   │       │   ├── route.tsx
│   │       │   ├── sign-in.tsx
│   │       │   └── sign-up.tsx
│   │       ├── _authenticated/
│   │       │   ├── route.tsx
│   │       │   └── user-management.tsx
│   │       └── route.tsx
│   ├── stores/
│   │   └── auth-store.ts
│   ├── styles/
│   │   ├── index.css
│   │   └── theme.css
│   ├── tanstack-table.d.ts
│   └── vite-env.d.ts
├── tsconfig.app.json
├── tsconfig.json
├── tsconfig.node.json
└── vite.config.ts

================================================
FILE CONTENTS
================================================

================================================
FILE: .github/CODE_OF_CONDUCT.md
================================================
# Contributor Covenant Code of Conduct

## Our Pledge

We as members, contributors, and leaders pledge to make participation in our
community a harassment-free experience for everyone, regardless of age, body
size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socio-economic status,
nationality, personal appearance, race, religion, or sexual identity
and orientation.

We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community.

## Our Standards

Examples of behavior that contributes to a positive environment for our
community include:

* Demonstrating empathy and kindness toward other people
* Being respectful of differing opinions, viewpoints, and experiences
* Giving and gracefully accepting constructive feedback
* Accepting responsibility and apologizing to those affected by our mistakes,
  and learning from the experience
* Focusing on what is best not just for us as individuals, but for the
  overall community

Examples of unacceptable behavior include:

* The use of sexualized language or imagery, and sexual attention or
  advances of any kind
* Trolling, insulting or derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or email
  address, without their explicit permission
* Other conduct which could reasonably be considered inappropriate in a
  professional setting

## Enforcement Responsibilities

Community leaders are responsible for clarifying and enforcing our standards of
acceptable behavior and will take appropriate and fair corrective action in
response to any behavior that they deem inappropriate, threatening, offensive,
or harmful.

Community leaders have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct, and will communicate reasons for moderation
decisions when appropriate.

## Scope

This Code of Conduct applies within all community spaces, and also applies when
an individual is officially representing the community in public spaces.
Examples of representing our community include using an official e-mail address,
posting via an official social media account, or acting as an appointed
representative at an online or offline event.

## Enforcement

Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at
.
All complaints will be reviewed and investigated promptly and fairly.

All community leaders are obligated to respect the privacy and security of the
reporter of any incident.

## Enforcement Guidelines

Community leaders will follow these Community Impact Guidelines in determining
the consequences for any action they deem in violation of this Code of Conduct:

### 1. Correction

**Community Impact**: Use of inappropriate language or other behavior deemed
unprofessional or unwelcome in the community.

**Consequence**: A private, written warning from community leaders, providing
clarity around the nature of the violation and an explanation of why the
behavior was inappropriate. A public apology may be requested.

### 2. Warning

**Community Impact**: A violation through a single incident or series
of actions.

**Consequence**: A warning with consequences for continued behavior. No
interaction with the people involved, including unsolicited interaction with
those enforcing the Code of Conduct, for a specified period of time. This
includes avoiding interactions in community spaces as well as external channels
like social media. Violating these terms may lead to a temporary or
permanent ban.

### 3. Temporary Ban

**Community Impact**: A serious violation of community standards, including
sustained inappropriate behavior.

**Consequence**: A temporary ban from any sort of interaction or public
communication with the community for a specified period of time. No public or
private interaction with the people involved, including unsolicited interaction
with those enforcing the Code of Conduct, is allowed during this period.
Violating these terms may lead to a permanent ban.

### 4. Permanent Ban

**Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior,  harassment of an
individual, or aggression toward or disparagement of classes of individuals.

**Consequence**: A permanent ban from any sort of public interaction within
the community.

## Attribution

This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 2.0, available at
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.

Community Impact Guidelines were inspired by [Mozilla's code of conduct
enforcement ladder](https://github.com/mozilla/diversity).

[homepage]: https://www.contributor-covenant.org

For answers to common questions about this code of conduct, see the FAQ at
https://www.contributor-covenant.org/faq. Translations are available at
https://www.contributor-covenant.org/translations.


================================================
FILE: .github/CONTRIBUTING.md
================================================
# Contributing to Shadcn-Admin

Thank you for considering contributing to **shadcn-admin**! Every contribution is valuable, whether it's reporting bugs, suggesting improvements, adding features, or refining README.

## Table of Contents

1. [Getting Started](#getting-started)
2. [How to Contribute](#how-to-contribute)
3. [Code Standards](#code-standards)
4. [Pull Request Guidelines](#pull-request-guidelines)
5. [Reporting Issues](#reporting-issues)
6. [Community Guidelines](#community-guidelines)

---

## Getting Started

1. **Fork** the repository.
2. **Clone** your fork:

   ```bash
   git clone https://github.com/your-username/shadcn-admin.git
   ```

3. **Install dependencies:**

   ```bash
   pnpm install
   ```

4. **Run the project locally:**

   ```bash
   pnpm dev
   ```

5. Create a new branch for your contribution:

   ```bash
   git checkout -b feature/your-feature
   ```

---

## How to Contribute

- **Feature Requests:** Open an issue or start a discussion to discuss the feature before implementation.
- **Bug Fixes:** Provide clear reproduction steps in your issue.
- **Documentation:** Improvements to the documentation (README) are always appreciated.

> **Note:** Pull Requests adding new features without a prior issue or discussion will **not be accepted**.

---

## Code Standards

- Follow the existing **ESLint** and **Prettier** configurations.
- Ensure your code is **type-safe** with **TypeScript**.
- Maintain consistency with the existing code structure.

> **Tips!** Before submitting your changes, run the following commands:

```bash
pnpm lint && pnpm format && pnpm knip && pnpm build
```

---

## Pull Request Guidelines

- **Follow the [PR Template](./PULL_REQUEST_TEMPLATE.md):**
  - Description
  - Types of changes
  - Checklist
  - Further comments
  - Related Issue
- Ensure your changes pass **CI checks**.
- Keep PRs **focused** and **concise**.
- Reference related issues in your PR description.

---

## Reporting Issues

- Clearly describe the issue.
- Provide reproduction steps if applicable.
- Include screenshots or code examples if relevant.

---

## Community Guidelines

- Be respectful and constructive.
- Follow the [Code of Conduct](./CODE_OF_CONDUCT.md).
- Stay on topic in discussions.

---

Thank you for helping make **shadcn-admin** better! 🚀

If you have any questions, feel free to reach out via [Discussions](https://github.com/satnaing/shadcn-admin/discussions).


================================================
FILE: .github/FUNDING.yml
================================================
github: [satnaing]
buy_me_a_coffee: satnaing

# patreon: # Replace with a single Patreon username
# open_collective: # Replace with a single Open Collective username
# ko_fi: # Replace with a single Ko-fi username
# tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
# community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
# liberapay: # Replace with a single Liberapay username
# issuehunt: # Replace with a single IssueHunt username
# lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
# polar: # Replace with a single Polar username
# thanks_dev: # Replace with a single thanks.dev username
# custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']


================================================
FILE: .github/ISSUE_TEMPLATE/config.yml
================================================
blank_issues_enabled: false
contact_links:
  - name: Shadcn-Admin Discussions
    url: https://github.com/satnaing/shadcn-admin/discussions
    about: Please ask and answer questions here.

================================================
FILE: .github/ISSUE_TEMPLATE/✨-feature-request.md
================================================
---
name: "✨ Feature Request"
about: Suggest an idea for improving Shadcn-Admin
title: "[Feature Request]: "
labels: enhancement
assignees: ""
---

**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]

**Describe the solution you'd like**
A clear and concise description of what you want to happen.

**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.

**Additional context**
Add any other context or screenshots about the feature request here.


================================================
FILE: .github/ISSUE_TEMPLATE/🐞-bug-report.md
================================================
---
name: "\U0001F41E Bug report"
about: Report a bug or unexpected behavior in Shadcn-Admin
title: "[BUG]: "
labels: bug
assignees: ""
---

**Describe the bug**
A clear and concise description of what the bug is.

**To Reproduce**
Steps to reproduce the behavior:

1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error

**Expected behavior**
A clear and concise description of what you expected to happen.

**Screenshots**
If applicable, add screenshots to help explain your problem.

**Additional context**
Add any other context about the problem here.


================================================
FILE: .github/PULL_REQUEST_TEMPLATE.md
================================================
## Description

<!-- A clear and concise description of what the pull request does. Include any relevant motivation and background. -->

## Types of changes

<!-- What types of changes does your code introduce to AstroPaper? Put an `x` in the boxes that apply -->

- [ ] Bug Fix (non-breaking change which fixes an issue)
- [ ] New Feature (non-breaking change which adds functionality)
- [ ] Others (any other types not listed above)

## Checklist

<!-- Please follow this checklist and put an x in each of the boxes, like this: [x]. You can also fill these out after creating the PR. This is simply a reminder of what we are going to look for before merging your code. -->

- [ ] I have read the [Contributing Guide](https://github.com/satnaing/shadcn-admin/blob/main/.github/CONTRIBUTING.md)

## Further comments

<!-- If this is a relatively large or complex change, kick off the discussion by explaining why you chose the solution you did and what alternatives you considered, etc... -->

## Related Issue

<!-- If this PR is related to an existing issue, link to it here. -->

Closes: #<!-- Issue number, if applicable -->

================================================
FILE: .github/workflows/ci.yml
================================================
name: Continuous Integration

on:
  push:
    branches:
      - main

  pull_request:
    branches:
      - main

jobs:
  install-lint-build:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: 20

      - name: Install pnpm
        run: npm install -g pnpm

      - name: Install dependencies
        run: pnpm install --frozen-lockfile

      - name: Lint the code
        run: pnpm lint

      # - name: Analyze unused files and dependencies
      #   run: pnpm knip

      - name: Run Prettier check
        run: pnpm format:check

      - name: Build the project
        run: pnpm build


================================================
FILE: .github/workflows/stale.yml
================================================
name: Close inactive issues/PR

on:
  schedule:
  - cron: '38 18 * * *'

jobs:
  stale:

    runs-on: ubuntu-latest
    permissions:
      issues: write
      pull-requests: write

    steps:
    - uses: actions/stale@v5
      with:
        repo-token: ${{ secrets.GITHUB_TOKEN }}
        days-before-issue-stale: 120
        days-before-issue-close: 120
        stale-issue-label: "stale"
        stale-issue-message: "This issue is stale because it has been open for 120 days with no activity."
        close-issue-message: "This issue was closed because it has been inactive for 120 days since being marked as stale."
        days-before-pr-stale: 120
        days-before-pr-close: 120
        stale-pr-label: "stale"
        stale-pr-message: "This PR is stale because it has been open for 120 days with no activity."
        close-pr-message: "This PR was closed because it has been inactive for 120 days since being marked as stale."
        operations-per-run: 0


================================================
FILE: .gitignore
================================================
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*

node_modules
dist
dist-ssr
*.local

.env

# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?


================================================
FILE: .prettierignore
================================================
# Ignore everything
/*

# Except these files & folders
!/src
!index.html
!package.json
!tailwind.config.js
!tsconfig.json
!tsconfig.node.json
!vite.config.ts
!.prettierrc
!README.md
!eslint.config.js
!postcss.config.js

# Ignore auto generated routeTree.gen.ts
/src/routeTree.gen.ts

================================================
FILE: .prettierrc
================================================
{
  "arrowParens": "always",
  "semi": false,
  "tabWidth": 2,
  "printWidth": 80,
  "singleQuote": true,
  "jsxSingleQuote": true,
  "trailingComma": "es5",
  "bracketSpacing": true,
  "endOfLine": "lf",
  "plugins": [
    "@trivago/prettier-plugin-sort-imports",
    "prettier-plugin-tailwindcss"
  ],
  "tailwindStylesheet": "./src/styles/index.css",
  "importOrder": [
    "^path$",
    "^vite$",
    "^@vitejs/(.*)$",
    "^react$",
    "^react-dom/client$",
    "^react/(.*)$",
    "^globals$",
    "^zod$",
    "^axios$",
    "^date-fns$",
    "^react-hook-form$",
    "^use-intl$",
    "^@radix-ui/(.*)$",
    "^@hookform/resolvers/zod$",
    "^@tanstack/react-query$",
    "^@tanstack/react-router$",
    "^@tanstack/react-table$",
    "<THIRD_PARTY_MODULES>",
    "^@/assets/(.*)",
    "^@/api/(.*)$",
    "^@/stores/(.*)$",
    "^@/lib/(.*)$",
    "^@/utils/(.*)$",
    "^@/constants/(.*)$",
    "^@/context/(.*)$",
    "^@/hooks/(.*)$",
    "^@/components/layouts/(.*)$",
    "^@/components/ui/(.*)$",
    "^@/components/errors/(.*)$",
    "^@/components/(.*)$",
    "^@/features/(.*)$",
    "^[./]"
  ]
}


================================================
FILE: CHANGELOG.md
================================================
## v2.2.1 (2025-11-06)

### Fix

- **style**: update data attribute class in authenticated layout (#249)
- prevent navigation to 500 page during development (#240)
- **style**: apply variant 'destructive' to sign-out buttons (#236)
- add missing space in profile form (#235)

### Refactor

- enhance tables and update table layout (#234)

## v2.2.0 (2025-10-09)

### Feat

- add analytics tab in dashboard page (#220)
- add extra AppTitle component for sidebar header (#216)
- update 2-column sign in page (#213)

### Fix

- update sidebar menu chevron direction in RTL mode (#229)
- pagination button spacing (#215)
- upgrade lucide-react to solve antivirus warning (#211)

### Refactor

- move sidebar related components into app-sidebar
- change SidebarInset component from 'main' to 'div'
- replace extra main container query with content container query
- replace inline svg logo with logo component (#214)

## v2.1.0 (2025-08-23)

### Feat

- enhance data table pagination with page numbers (#207)
- enhance auth flow with sign-out dialogs and redirect functionality (#206)

### Refactor

- reorganize utility files into `lib/` folder (#209)
- extract data-table components and reorganize structure (#208)

## v2.0.0 (2025-08-16)

### BREAKING CHANGE

- CSS file structure has been reorganized

### Feat

- add search param sync in apps route (#200)
- improve tables and sync table states with search param (#199)
- add data table bulk action toolbar (#196)
- add config drawer and update overall layout (#186)
- RTL support (#179)

### Fix

- adjust layout styles in search and top nav in dashboard page
- update spacing and layout styles
- update faceted icon color
- improve user table hover & selected styles (#195)
- add max-width for large screens to improve responsiveness (#194)
- adjust chat border radius for better responsiveness (#193)
- update hard-coded or inconsistent colors (#191)
- use variable for inset layout height calculation
- faded-bottom overflow issue in inset layout
- hide unnecessary configs on mobile (#189)
- adjust file input text vertical alignment (#188)

### Refactor

- enforce consistency and code quality (#198)
- improve code quality and consistency (#197)
- update error routes (#192)
- remove DirSwitch component and its usage in Tasks (#190)
- standardize using cookie as persist state (#187)
- separate CSS into modular theme and base styles (#185)
- replace tabler icons with lucide icons (#183)

## v1.4.2 (2025-07-23)

### Fix

- remove unnecessary transitions in table (#176)
- overflow background in tables (#175)

## v1.4.1 (2025-06-25)

### Fix

- user list overflow in chat (#160)
- prevent showing collapsed menu on mobile (#155)
- white background select dropdown in dark mode (#149)

### Refactor

- update font config guide in fonts.ts (#164)

## v1.4.0 (2025-05-25)

### Feat

- **clerk**: add Clerk for auth and protected route (#146)

### Fix

- add an indicator for nested pages in search (#147)
- update faded-bottom color with css variable (#139)

## v1.3.0 (2025-04-16)

### Fix

- replace custom otp with input-otp component (#131)
- disable layout animation on mobile (#130)
- upgrade react-day-picker and update calendar component (#129)

### Others

- upgrade Tailwind CSS to v4 (#125)
- upgrade dependencies (#128)
- configure automatic code-splitting (#127)

## v1.2.0 (2025-04-12)

### Feat

- add loading indicator during page transitions (#119)
- add light favicons and theme-based switching (#112)
- add new chat dialog in chats page (#90)

### Fix

- add fallback font for fontFamily (#110)
- broken focus behavior in add user dialog (#113)

## v1.1.0 (2025-01-30)

### Feat

- allow changing font family in setting

### Fix

- update sidebar color in dark mode for consistent look (#87)
- use overflow-clip in table paginations (#86)
- **style**: update global scrollbar style (#82)
- toolbar filter placeholder typo in user table (#76)

## v1.0.3 (2024-12-28)

### Fix

- add gap between buttons in import task dialog (#70)
- hide button sort if column cannot be hidden & update filterFn (#69)
- nav links added in profile dropdown (#68)

### Refactor

- optimize states in users/tasks context (#71)

## v1.0.2 (2024-12-25)

### Fix

- update overall layout due to scroll-lock bug (#66)

### Refactor

- analyze and remove unused files/exports with knip (#67)

## v1.0.1 (2024-12-14)

### Fix

- merge two button components into one (#60)
- loading all tabler-icon chunks in dev mode (#59)
- display menu dropdown when sidebar collapsed (#58)
- update spacing & alignment in dialogs/drawers
- update border & transition of sticky columns in user table
- update heading alignment to left in user dialogs
- add height and scroll area in user mutation dialogs
- update `/dashboard` route to just `/`
- **build**: replace require with import in tailwind.config.js

### Refactor

- remove unnecessary layout-backup file

## v1.0.0 (2024-12-09)

### BREAKING CHANGE

- Restructured the entire folder
hierarchy to adopt a feature-based structure. This
change improves code modularity and maintainability
but introduces breaking changes.

### Feat

- implement task dialogs
- implement user invite dialog
- implement users CRUD
- implement global command/search
- implement custom sidebar trigger
- implement coming-soon page

### Fix

- uncontrolled issue in account setting
- card layout issue in app integrations page
- remove form reset logic from useEffect in task import
- update JSX types due to react 19
- prevent card stretch in filtered app layout
- layout wrap issue in tasks page on mobile
- update user column hover and selected colors
- add setTimeout in user dialog closing
- layout shift issue in dropdown modal
- z-axis overflow issue in header
- stretch search bar only in mobile
- language dropdown issue in account setting
- update overflow contents with scroll area

### Refactor

- update layouts and extract common layout
- reorganize project to feature-based structure

## v1.0.0-beta.5 (2024-11-11)

### Feat

- add multiple language support (#37)

### Fix

- ensure site syncs with system theme changes (#49)
- recent sales responsive on ipad view (#40)

## v1.0.0-beta.4 (2024-09-22)

### Feat

- upgrade theme button to theme dropdown (#33)
- **a11y**: add "Skip to Main" button to improve keyboard navigation (#27)

### Fix

- optimize onComplete/onIncomplete invocation (#32)
- solve asChild attribute issue in custom button (#31)
- improve custom Button component (#28)

## v1.0.0-beta.3 (2024-08-25)

### Feat

- implement chat page (#21)
- add 401 error page (#12)
- implement apps page
- add otp page

### Fix

- prevent focus zoom on mobile devices (#20)
- resolve eslint script issue (#18)
- **a11y**: update default aria-label of each pin-input
- resolve OTP paste issue in multi-digit pin-input
- update layouts and solve overflow issues (#11)
- sync pin inputs programmatically

## v1.0.0-beta.2 (2024-03-18)

### Feat

- implement custom pin-input component (#2)

## v1.0.0-beta.1 (2024-02-08)

### Feat

- update theme-color meta tag when theme is updated
- add coming soon page in broken pages
- implement tasks table and page
- add remaining settings pages
- add example error page for settings
- update general error page to be more flexible
- implement settings layout and settings profile page
- add error pages
- add password-input custom component
- add sign-up page
- add forgot-password page
- add box sign in page
- add email + password sign in page
- make sidebar responsive and accessible
- add tailwind prettier plugin
- make sidebar collapsed state in local storage
- add check current active nav hook
- add loader component ui
- update dropdown nav by default if child is active
- add main-panel in dashboard
- **ui**: add dark mode
- **ui**: implement side nav ui

### Fix

- update incorrect overflow side nav height
- exclude shadcn components from linting and remove unused props
- solve text overflow issue when nav text is long
- replace nav with dropdown in mobile topnav
- make sidebar scrollable when overflow
- update nav link keys
- **ui**: update label style

### Refactor

- move password-input component into custom component dir
- add custom button component
- extract redundant codes into layout component
- update react-router to use new api for routing
- update main panel layout
- update major layouts and styling
- update main panel to be responsive
- update sidebar collapsed state to false in mobile
- update sidebar logo and title
- **ui**: remove unnecessary spacing
- remove unused files


================================================
FILE: LICENSE
================================================
MIT License

Copyright (c) 2024 Sat Naing

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


================================================
FILE: README.md
================================================
# Shadcn Admin Dashboard

Admin Dashboard UI crafted with Shadcn and Vite. Built with responsiveness and accessibility in mind.

![alt text](public/images/shadcn-admin.png)

[![Sponsored by Clerk](https://img.shields.io/badge/Sponsored%20by-Clerk-5b6ee1?logo=clerk)](https://go.clerk.com/GttUAaK)

I've been creating dashboard UIs at work and for my personal projects. I always wanted to make a reusable collection of dashboard UI for future projects; and here it is now. While I've created a few custom components, some of the code is directly adapted from ShadcnUI examples.

> This is not a starter project (template) though. I'll probably make one in the future.

## Features

- Light/dark mode
- Responsive
- Accessible
- With built-in Sidebar component
- Global search command
- 10+ pages
- Extra custom components
- RTL support

<details>
<summary>Customized Components (click to expand)</summary>

This project uses Shadcn UI components, but some have been slightly modified for better RTL (Right-to-Left) support and other improvements. These customized components differ from the original Shadcn UI versions.

If you want to update components using the Shadcn CLI (e.g., `npx shadcn@latest add <component>`), it's generally safe for non-customized components. For the listed customized ones, you may need to manually merge changes to preserve the project's modifications and avoid overwriting RTL support or other updates.

> If you don't require RTL support, you can safely update the 'RTL Updated Components' via the Shadcn CLI, as these changes are primarily for RTL compatibility. The 'Modified Components' may have other customizations to consider.

### Modified Components

- scroll-area
- sonner
- separator

### RTL Updated Components

- alert-dialog
- calendar
- command
- dialog
- dropdown-menu
- select
- table
- sheet
- sidebar
- switch

**Notes:**

- **Modified Components**: These have general updates, potentially including RTL adjustments.
- **RTL Updated Components**: These have specific changes for RTL language support (e.g., layout, positioning).
- For implementation details, check the source files in `src/components/ui/`.
- All other Shadcn UI components in the project are standard and can be safely updated via the CLI.

</details>

## Tech Stack

**UI:** [ShadcnUI](https://ui.shadcn.com) (TailwindCSS + RadixUI)

**Build Tool:** [Vite](https://vitejs.dev/)

**Routing:** [TanStack Router](https://tanstack.com/router/latest)

**Type Checking:** [TypeScript](https://www.typescriptlang.org/)

**Linting/Formatting:** [ESLint](https://eslint.org/) & [Prettier](https://prettier.io/)

**Icons:** [Lucide Icons](https://lucide.dev/icons/), [Tabler Icons](https://tabler.io/icons) (Brand icons only)

**Auth (partial):** [Clerk](https://go.clerk.com/GttUAaK)

## Run Locally

Clone the project

```bash
  git clone https://github.com/satnaing/shadcn-admin.git
```

Go to the project directory

```bash
  cd shadcn-admin
```

Install dependencies

```bash
  pnpm install
```

Start the server

```bash
  pnpm run dev
```

## Sponsoring this project ❤️

If you find this project helpful or use this in your own work, consider [sponsoring me](https://github.com/sponsors/satnaing) to support development and maintenance. You can [buy me a coffee](https://buymeacoffee.com/satnaing) as well. Don’t worry, every penny helps. Thank you! 🙏

For questions or sponsorship inquiries, feel free to reach out at [satnaingdev@gmail.com](mailto:satnaingdev@gmail.com).

### Current Sponsor

- [Clerk](https://go.clerk.com/GttUAaK) - authentication and user management for the modern web

## Author

Crafted with 🤍 by [@satnaing](https://github.com/satnaing)

## License

Licensed under the [MIT License](https://choosealicense.com/licenses/mit/)


================================================
FILE: components.json
================================================
{
  "$schema": "https://ui.shadcn.com/schema.json",
  "style": "new-york",
  "rsc": false,
  "tsx": true,
  "tailwind": {
    "config": "",
    "css": "src/styles/index.css",
    "baseColor": "slate",
    "cssVariables": true,
    "prefix": ""
  },
  "aliases": {
    "components": "@/components",
    "utils": "@/lib/utils",
    "ui": "@/components/ui",
    "lib": "@/lib",
    "hooks": "@/hooks"
  },
  "iconLibrary": "lucide"
}


================================================
FILE: cz.yaml
================================================
---
commitizen:
  name: cz_conventional_commits
  tag_format: v$version
  update_changelog_on_bump: true
  version_provider: npm
  version_scheme: semver


================================================
FILE: eslint.config.js
================================================
import globals from 'globals'
import js from '@eslint/js'
import pluginQuery from '@tanstack/eslint-plugin-query'
import reactHooks from 'eslint-plugin-react-hooks'
import reactRefresh from 'eslint-plugin-react-refresh'
import { defineConfig } from 'eslint/config'
import tseslint from 'typescript-eslint'

export default defineConfig(
  { ignores: ['dist', 'src/components/ui'] },
  {
    extends: [
      js.configs.recommended,
      ...tseslint.configs.recommended,
      ...pluginQuery.configs['flat/recommended'],
    ],
    files: ['**/*.{ts,tsx}'],
    languageOptions: {
      ecmaVersion: 2020,
      globals: globals.browser,
    },
    plugins: {
      'react-hooks': reactHooks,
      'react-refresh': reactRefresh,
    },
    rules: {
      ...reactHooks.configs.recommended.rules,
      'react-refresh/only-export-components': [
        'warn',
        { allowConstantExport: true },
      ],
      'no-console': 'error',
      'no-unused-vars': 'off',
      '@typescript-eslint/no-unused-vars': [
        'error',
        {
          args: 'all',
          argsIgnorePattern: '^_',
          caughtErrors: 'all',
          caughtErrorsIgnorePattern: '^_',
          destructuredArrayIgnorePattern: '^_',
          varsIgnorePattern: '^_',
          ignoreRestSiblings: true,
        },
      ],
      // Enforce type-only imports for TypeScript types
      '@typescript-eslint/consistent-type-imports': [
        'error',
        {
          prefer: 'type-imports',
          fixStyle: 'inline-type-imports',
          disallowTypeAnnotations: false,
        },
      ],
      // Prevent duplicate imports from the same module
      'no-duplicate-imports': 'error',
    },
  }
)


================================================
FILE: index.html
================================================
<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <link
      rel="icon"
      type="image/svg+xml"
      href="/images/favicon.svg"
      media="(prefers-color-scheme: light)"
    />
    <link
      rel="icon"
      type="image/svg+xml"
      href="/images/favicon_light.svg"
      media="(prefers-color-scheme: dark)"
    />
    <link
      rel="icon"
      type="image/png"
      href="/images/favicon.png"
      media="(prefers-color-scheme: light)"
    />
    <link
      rel="icon"
      type="image/png"
      href="/images/favicon_light.png"
      media="(prefers-color-scheme: dark)"
    />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />

    <!-- Primary Meta Tags -->
    <title>Shadcn Admin</title>
    <meta name="title" content="Shadcn Admin" />
    <meta
      name="description"
      content="Admin Dashboard UI built with Shadcn and Vite."
    />

    <!-- Open Graph / Facebook -->
    <meta property="og:type" content="website" />
    <meta property="og:url" content="https://shadcn-admin.netlify.app" />
    <meta property="og:title" content="Shadcn Admin" />
    <meta
      property="og:description"
      content="Admin Dashboard UI built with Shadcn and Vite."
    />
    <meta
      property="og:image"
      content="https://shadcn-admin.netlify.app/images/shadcn-admin.png"
    />

    <!-- Twitter -->
    <meta property="twitter:card" content="summary_large_image" />
    <meta property="twitter:url" content="https://shadcn-admin.netlify.app" />
    <meta property="twitter:title" content="Shadcn Admin" />
    <meta
      property="twitter:description"
      content="Admin Dashboard UI built with Shadcn and Vite."
    />
    <meta
      property="twitter:image"
      content="https://shadcn-admin.netlify.app/images/shadcn-admin.png"
    />

    <!-- font family -->
    <link rel="preconnect" href="https://fonts.googleapis.com" />
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
    <link
      href="https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&family=Manrope:wght@200..800&display=swap"
      rel="stylesheet"
    />

    <meta name="theme-color" content="#fff" />
  </head>

  <body>
    <div id="root"></div>
    <script type="module" src="/src/main.tsx"></script>
  </body>
</html>


================================================
FILE: knip.config.ts
================================================
import type { KnipConfig } from 'knip';

const config: KnipConfig = {
  ignore: ['src/components/ui/**', 'src/routeTree.gen.ts'],
  ignoreDependencies: ["tailwindcss", "tw-animate-css"]
};

export default config;

================================================
FILE: netlify.toml
================================================
[[redirects]]
  from = "/*"
  to = "/index.html"
  status = 200

================================================
FILE: package.json
================================================
{
  "name": "shadcn-admin",
  "private": false,
  "version": "2.2.1",
  "type": "module",
  "scripts": {
    "dev": "vite",
    "build": "tsc -b && vite build",
    "lint": "eslint .",
    "preview": "vite preview",
    "format:check": "prettier --check .",
    "format": "prettier --write .",
    "knip": "knip"
  },
  "dependencies": {
    "@clerk/clerk-react": "^5.58.1",
    "@hookform/resolvers": "^5.2.2",
    "@radix-ui/react-alert-dialog": "^1.1.15",
    "@radix-ui/react-avatar": "^1.1.11",
    "@radix-ui/react-checkbox": "^1.3.3",
    "@radix-ui/react-collapsible": "^1.1.12",
    "@radix-ui/react-dialog": "^1.1.15",
    "@radix-ui/react-direction": "^1.1.1",
    "@radix-ui/react-dropdown-menu": "^2.1.16",
    "@radix-ui/react-icons": "^1.3.2",
    "@radix-ui/react-label": "^2.1.8",
    "@radix-ui/react-popover": "^1.1.15",
    "@radix-ui/react-radio-group": "^1.3.8",
    "@radix-ui/react-scroll-area": "^1.2.10",
    "@radix-ui/react-select": "^2.2.6",
    "@radix-ui/react-separator": "^1.1.8",
    "@radix-ui/react-slot": "^1.2.4",
    "@radix-ui/react-switch": "^1.2.6",
    "@radix-ui/react-tabs": "^1.1.13",
    "@radix-ui/react-tooltip": "^1.2.8",
    "@tailwindcss/vite": "^4.1.18",
    "@tanstack/react-query": "^5.90.12",
    "@tanstack/react-router": "^1.141.2",
    "@tanstack/react-table": "^8.21.3",
    "axios": "^1.13.5",
    "class-variance-authority": "^0.7.1",
    "clsx": "^2.1.1",
    "cmdk": "1.1.1",
    "date-fns": "^4.1.0",
    "input-otp": "^1.4.2",
    "lucide-react": "^0.561.0",
    "react": "^19.2.3",
    "react-day-picker": "9.12.0",
    "react-dom": "^19.2.3",
    "react-hook-form": "^7.68.0",
    "react-top-loading-bar": "^3.0.2",
    "recharts": "^3.6.0",
    "sonner": "^2.0.7",
    "tailwind-merge": "^3.4.0",
    "tailwindcss": "^4.1.18",
    "tw-animate-css": "^1.4.0",
    "zod": "^4.2.0",
    "zustand": "^5.0.9"
  },
  "devDependencies": {
    "@eslint/js": "^9.39.2",
    "@faker-js/faker": "^10.1.0",
    "@tanstack/eslint-plugin-query": "^5.91.2",
    "@tanstack/react-query-devtools": "^5.91.1",
    "@tanstack/react-router-devtools": "^1.141.2",
    "@tanstack/router-plugin": "^1.141.2",
    "@trivago/prettier-plugin-sort-imports": "^6.0.0",
    "@types/node": "^25.0.2",
    "@types/react": "^19.2.7",
    "@types/react-dom": "^19.2.3",
    "@vitejs/plugin-react-swc": "^4.2.2",
    "eslint": "^9.39.2",
    "eslint-plugin-react-hooks": "^7.0.1",
    "eslint-plugin-react-refresh": "^0.4.25",
    "globals": "^16.5.0",
    "knip": "^5.73.4",
    "prettier": "^3.7.4",
    "prettier-plugin-tailwindcss": "^0.7.2",
    "typescript": "~5.9.3",
    "typescript-eslint": "^8.49.0",
    "vite": "^7.3.0"
  }
}


================================================
FILE: src/assets/brand-icons/icon-discord.tsx
================================================
import { type SVGProps } from 'react'
import { cn } from '@/lib/utils'

export function IconDiscord({ className, ...props }: SVGProps<SVGSVGElement>) {
  return (
    <svg
      role='img'
      viewBox='0 0 24 24'
      xmlns='http://www.w3.org/2000/svg'
      width='24'
      height='24'
      className={cn('[&>path]:stroke-current', className)}
      fill='none'
      stroke='currentColor'
      strokeWidth='2'
      strokeLinecap='round'
      strokeLinejoin='round'
      {...props}
    >
      <title>Discord</title>
      <path strokeWidth='0' d='M0 0h24v24H0z' fill='none' />
      <path d='M8 12a1 1 0 1 0 2 0a1 1 0 0 0 -2 0' />
      <path d='M14 12a1 1 0 1 0 2 0a1 1 0 0 0 -2 0' />
      <path d='M15.5 17c0 1 1.5 3 2 3c1.5 0 2.833 -1.667 3.5 -3c.667 -1.667 .5 -5.833 -1.5 -11.5c-1.457 -1.015 -3 -1.34 -4.5 -1.5l-.972 1.923a11.913 11.913 0 0 0 -4.053 0l-.975 -1.923c-1.5 .16 -3.043 .485 -4.5 1.5c-2 5.667 -2.167 9.833 -1.5 11.5c.667 1.333 2 3 3.5 3c.5 0 2 -2 2 -3' />
      <path d='M7 16.5c3.5 1 6.5 1 10 0' />
    </svg>
  )
}


================================================
FILE: src/assets/brand-icons/icon-docker.tsx
================================================
import { type SVGProps } from 'react'
import { cn } from '@/lib/utils'

export function IconDocker({ className, ...props }: SVGProps<SVGSVGElement>) {
  return (
    <svg
      role='img'
      viewBox='0 0 24 24'
      xmlns='http://www.w3.org/2000/svg'
      width='24'
      height='24'
      className={cn('[&>path]:stroke-current', className)}
      fill='none'
      stroke='currentColor'
      strokeWidth='2'
      strokeLinecap='round'
      strokeLinejoin='round'
      {...props}
    >
      <title>Docker</title>
      <path strokeWidth='0' d='M0 0h24v24H0z' fill='none' />
      <path d='M22 12.54c-1.804 -.345 -2.701 -1.08 -3.523 -2.94c-.487 .696 -1.102 1.568 -.92 2.4c.028 .238 -.32 1 -.557 1h-14c0 5.208 3.164 7 6.196 7c4.124 .022 7.828 -1.376 9.854 -5c1.146 -.101 2.296 -1.505 2.95 -2.46z' />
      <path d='M5 10h3v3h-3z' />
      <path d='M8 10h3v3h-3z' />
      <path d='M11 10h3v3h-3z' />
      <path d='M8 7h3v3h-3z' />
      <path d='M11 7h3v3h-3z' />
      <path d='M11 4h3v3h-3z' />
      <path d='M4.571 18c1.5 0 2.047 -.074 2.958 -.78' />
      <path d='M10 16l0 .01' />
    </svg>
  )
}


================================================
FILE: src/assets/brand-icons/icon-facebook.tsx
================================================
import { type SVGProps } from 'react'
import { cn } from '@/lib/utils'

export function IconFacebook({ className, ...props }: SVGProps<SVGSVGElement>) {
  return (
    <svg
      role='img'
      viewBox='0 0 24 24'
      xmlns='http://www.w3.org/2000/svg'
      width='24'
      height='24'
      className={cn('[&>path]:stroke-current', className)}
      fill='none'
      stroke='currentColor'
      strokeWidth='2'
      strokeLinecap='round'
      strokeLinejoin='round'
      {...props}
    >
      <title>Facebook</title>
      <path strokeWidth='0' d='M0 0h24v24H0z' fill='none' />
      <path d='M7 10v4h3v7h4v-7h3l1 -4h-4v-2a1 1 0 0 1 1 -1h3v-4h-3a5 5 0 0 0 -5 5v2h-3' />
    </svg>
  )
}


================================================
FILE: src/assets/brand-icons/icon-figma.tsx
================================================
import { type SVGProps } from 'react'
import { cn } from '@/lib/utils'

export function IconFigma({ className, ...props }: SVGProps<SVGSVGElement>) {
  return (
    <svg
      role='img'
      viewBox='0 0 24 24'
      xmlns='http://www.w3.org/2000/svg'
      width='24'
      height='24'
      className={cn('[&>path]:stroke-current', className)}
      fill='none'
      stroke='currentColor'
      strokeWidth='2'
      strokeLinecap='round'
      strokeLinejoin='round'
      {...props}
    >
      <title>Figma</title>
      <path strokeWidth='0' d='M0 0h24v24H0z' fill='none' />
      <path d='M15 12m-3 0a3 3 0 1 0 6 0a3 3 0 1 0 -6 0' />
      <path d='M6 3m0 3a3 3 0 0 1 3 -3h6a3 3 0 0 1 3 3v0a3 3 0 0 1 -3 3h-6a3 3 0 0 1 -3 -3z' />
      <path d='M9 9a3 3 0 0 0 0 6h3m-3 0a3 3 0 1 0 3 3v-15' />
    </svg>
  )
}


================================================
FILE: src/assets/brand-icons/icon-github.tsx
================================================
import { type SVGProps } from 'react'
import { cn } from '@/lib/utils'

export function IconGithub({ className, ...props }: SVGProps<SVGSVGElement>) {
  return (
    <svg
      role='img'
      viewBox='0 0 24 24'
      xmlns='http://www.w3.org/2000/svg'
      width='24'
      height='24'
      className={cn('[&>path]:stroke-current', className)}
      fill='none'
      stroke='currentColor'
      strokeWidth='2'
      strokeLinecap='round'
      strokeLinejoin='round'
      {...props}
    >
      <title>GitHub</title>
      <path strokeWidth='0' d='M0 0h24v24H0z' fill='none' />
      <path d='M9 19c-4.3 1.4 -4.3 -2.5 -6 -3m12 5v-3.5c0 -1 .1 -1.4 -.5 -2c2.8 -.3 5.5 -1.4 5.5 -6a4.6 4.6 0 0 0 -1.3 -3.2a4.2 4.2 0 0 0 -.1 -3.2s-1.1 -.3 -3.5 1.3a12.3 12.3 0 0 0 -6.2 0c-2.4 -1.6 -3.5 -1.3 -3.5 -1.3a4.2 4.2 0 0 0 -.1 3.2a4.6 4.6 0 0 0 -1.3 3.2c0 4.6 2.7 5.7 5.5 6c-.6 .6 -.6 1.2 -.5 2v3.5' />
    </svg>
  )
}


================================================
FILE: src/assets/brand-icons/icon-gitlab.tsx
================================================
import { type SVGProps } from 'react'
import { cn } from '@/lib/utils'

export function IconGitlab({ className, ...props }: SVGProps<SVGSVGElement>) {
  return (
    <svg
      role='img'
      viewBox='0 0 24 24'
      xmlns='http://www.w3.org/2000/svg'
      width='24'
      height='24'
      className={cn('[&>path]:stroke-current', className)}
      fill='none'
      stroke='currentColor'
      strokeWidth='2'
      strokeLinecap='round'
      strokeLinejoin='round'
      {...props}
    >
      <title>GitLab</title>
      <path strokeWidth='0' d='M0 0h24v24H0z' fill='none' />
      <path d='M21 14l-9 7l-9 -7l3 -11l3 7h6l3 -7z' />
    </svg>
  )
}


================================================
FILE: src/assets/brand-icons/icon-gmail.tsx
================================================
import { type SVGProps } from 'react'
import { cn } from '@/lib/utils'

export function IconGmail({ className, ...props }: SVGProps<SVGSVGElement>) {
  return (
    <svg
      role='img'
      viewBox='0 0 24 24'
      xmlns='http://www.w3.org/2000/svg'
      width='24'
      height='24'
      className={cn('[&>path]:stroke-current', className)}
      fill='none'
      stroke='currentColor'
      strokeWidth='2'
      strokeLinecap='round'
      strokeLinejoin='round'
      {...props}
    >
      <title>Gmail</title>
      <path strokeWidth='0' d='M0 0h24v24H0z' fill='none' />
      <path d='M16 20h3a1 1 0 0 0 1 -1v-14a1 1 0 0 0 -1 -1h-3v16z' />
      <path d='M5 20h3v-16h-3a1 1 0 0 0 -1 1v14a1 1 0 0 0 1 1z' />
      <path d='M16 4l-4 4l-4 -4' />
      <path d='M4 6.5l8 7.5l8 -7.5' />
    </svg>
  )
}


================================================
FILE: src/assets/brand-icons/icon-medium.tsx
================================================
import { type SVGProps } from 'react'
import { cn } from '@/lib/utils'

export function IconMedium({ className, ...props }: SVGProps<SVGSVGElement>) {
  return (
    <svg
      role='img'
      viewBox='0 0 24 24'
      xmlns='http://www.w3.org/2000/svg'
      width='24'
      height='24'
      className={cn('[&>path]:stroke-current', className)}
      fill='none'
      stroke='currentColor'
      strokeWidth='2'
      strokeLinecap='round'
      strokeLinejoin='round'
      {...props}
    >
      <title>Medium</title>
      <path strokeWidth='0' d='M0 0h24v24H0z' fill='none' />
      <path d='M4 4m0 2a2 2 0 0 1 2 -2h12a2 2 0 0 1 2 2v12a2 2 0 0 1 -2 2h-12a2 2 0 0 1 -2 -2z' />
      <path d='M8 9h1l3 3l3 -3h1' />
      <path d='M8 15l2 0' />
      <path d='M14 15l2 0' />
      <path d='M9 9l0 6' />
      <path d='M15 9l0 6' />
    </svg>
  )
}


================================================
FILE: src/assets/brand-icons/icon-notion.tsx
================================================
import { type SVGProps } from 'react'
import { cn } from '@/lib/utils'

export function IconNotion({ className, ...props }: SVGProps<SVGSVGElement>) {
  return (
    <svg
      role='img'
      viewBox='0 0 24 24'
      xmlns='http://www.w3.org/2000/svg'
      width='24'
      height='24'
      className={cn('[&>path]:stroke-current', className)}
      fill='none'
      stroke='currentColor'
      strokeWidth='2'
      strokeLinecap='round'
      strokeLinejoin='round'
      {...props}
    >
      <title>Notion</title>
      <path strokeWidth='0' d='M0 0h24v24H0z' fill='none' />
      <path d='M11 17.5v-6.5h.5l4 6h.5v-6.5' />
      <path d='M19.077 20.071l-11.53 .887a1 1 0 0 1 -.876 -.397l-2.471 -3.294a1 1 0 0 1 -.2 -.6v-10.741a1 1 0 0 1 .923 -.997l11.389 -.876a2 2 0 0 1 1.262 .33l1.535 1.023a2 2 0 0 1 .891 1.664v12.004a1 1 0 0 1 -.923 .997z' />
      <path d='M4.5 5.5l2.5 2.5' />
      <path d='M20 7l-13 1v12.5' />
    </svg>
  )
}


================================================
FILE: src/assets/brand-icons/icon-skype.tsx
================================================
import { type SVGProps } from 'react'
import { cn } from '@/lib/utils'

export function IconSkype({ className, ...props }: SVGProps<SVGSVGElement>) {
  return (
    <svg
      role='img'
      viewBox='0 0 24 24'
      xmlns='http://www.w3.org/2000/svg'
      width='24'
      height='24'
      className={cn('[&>path]:stroke-current', className)}
      fill='none'
      stroke='currentColor'
      strokeWidth='2'
      strokeLinecap='round'
      strokeLinejoin='round'
      {...props}
    >
      <title>Skype</title>
      <path strokeWidth='0' d='M0 0h24v24H0z' fill='none' />
      <path d='M12 3a9 9 0 0 1 8.603 11.65a4.5 4.5 0 0 1 -5.953 5.953a9 9 0 0 1 -11.253 -11.253a4.5 4.5 0 0 1 5.953 -5.954a8.987 8.987 0 0 1 2.65 -.396z' />
      <path d='M8 14.5c.5 2 2.358 2.5 4 2.5c2.905 0 4 -1.187 4 -2.5c0 -1.503 -1.927 -2.5 -4 -2.5s-4 -1 -4 -2.5c0 -1.313 1.095 -2.5 4 -2.5c1.642 0 3.5 .5 4 2.5' />
    </svg>
  )
}


================================================
FILE: src/assets/brand-icons/icon-slack.tsx
================================================
import { type SVGProps } from 'react'
import { cn } from '@/lib/utils'

export function IconSlack({ className, ...props }: SVGProps<SVGSVGElement>) {
  return (
    <svg
      role='img'
      viewBox='0 0 24 24'
      xmlns='http://www.w3.org/2000/svg'
      width='24'
      height='24'
      className={cn('[&>path]:stroke-current', className)}
      fill='none'
      stroke='currentColor'
      strokeWidth='2'
      strokeLinecap='round'
      strokeLinejoin='round'
      {...props}
    >
      <title>Slack</title>
      <path strokeWidth='0' d='M0 0h24v24H0z' fill='none' />
      <path d='M12 12v-6a2 2 0 0 1 4 0v6m0 -2a2 2 0 1 1 2 2h-6' />
      <path d='M12 12h6a2 2 0 0 1 0 4h-6m2 0a2 2 0 1 1 -2 2v-6' />
      <path d='M12 12v6a2 2 0 0 1 -4 0v-6m0 2a2 2 0 1 1 -2 -2h6' />
      <path d='M12 12h-6a2 2 0 0 1 0 -4h6m-2 0a2 2 0 1 1 2 -2v6' />
    </svg>
  )
}


================================================
FILE: src/assets/brand-icons/icon-stripe.tsx
================================================
import { type SVGProps } from 'react'
import { cn } from '@/lib/utils'

export function IconStripe({ className, ...props }: SVGProps<SVGSVGElement>) {
  return (
    <svg
      role='img'
      viewBox='0 0 24 24'
      xmlns='http://www.w3.org/2000/svg'
      width='24'
      height='24'
      className={cn('[&>path]:stroke-current', className)}
      fill='none'
      stroke='currentColor'
      strokeWidth='2'
      strokeLinecap='round'
      strokeLinejoin='round'
      {...props}
    >
      <title>Stripe</title>
      <path strokeWidth='0' d='M0 0h24v24H0z' fill='none' />
      <path d='M11.453 8.056c0 -.623 .518 -.979 1.442 -.979c1.69 0 3.41 .343 4.605 .923l.5 -4c-.948 -.449 -2.82 -1 -5.5 -1c-1.895 0 -3.373 .087 -4.5 1c-1.172 .956 -2 2.33 -2 4c0 3.03 1.958 4.906 5 6c1.961 .69 3 .743 3 1.5c0 .735 -.851 1.5 -2 1.5c-1.423 0 -3.963 -.609 -5.5 -1.5l-.5 4c1.321 .734 3.474 1.5 6 1.5c2 0 3.957 -.468 5.084 -1.36c1.263 -.979 1.916 -2.268 1.916 -4.14c0 -3.096 -1.915 -4.547 -5 -5.637c-1.646 -.605 -2.544 -1.07 -2.544 -1.807z' />
    </svg>
  )
}


================================================
FILE: src/assets/brand-icons/icon-telegram.tsx
================================================
import { type SVGProps } from 'react'
import { cn } from '@/lib/utils'

export function IconTelegram({ className, ...props }: SVGProps<SVGSVGElement>) {
  return (
    <svg
      role='img'
      viewBox='0 0 24 24'
      xmlns='http://www.w3.org/2000/svg'
      width='24'
      height='24'
      className={cn('[&>path]:stroke-current', className)}
      fill='none'
      stroke='currentColor'
      strokeWidth='2'
      strokeLinecap='round'
      strokeLinejoin='round'
      {...props}
    >
      <title>Telegram</title>
      <path strokeWidth='0' d='M0 0h24v24H0z' fill='none' />
      <path d='M15 10l-4 4l6 6l4 -16l-18 7l4 2l2 6l3 -4' />
    </svg>
  )
}


================================================
FILE: src/assets/brand-icons/icon-trello.tsx
================================================
import { type SVGProps } from 'react'
import { cn } from '@/lib/utils'

export function IconTrello({ className, ...props }: SVGProps<SVGSVGElement>) {
  return (
    <svg
      role='img'
      viewBox='0 0 24 24'
      xmlns='http://www.w3.org/2000/svg'
      width='24'
      height='24'
      className={cn('[&>path]:stroke-current', className)}
      fill='none'
      stroke='currentColor'
      strokeWidth='2'
      strokeLinecap='round'
      strokeLinejoin='round'
      {...props}
    >
      <title>Trello</title>
      <path strokeWidth='0' d='M0 0h24v24H0z' fill='none' />
      <path d='M4 4m0 2a2 2 0 0 1 2 -2h12a2 2 0 0 1 2 2v12a2 2 0 0 1 -2 2h-12a2 2 0 0 1 -2 -2z' />
      <path d='M7 7h3v10h-3z' />
      <path d='M14 7h3v6h-3z' />
    </svg>
  )
}


================================================
FILE: src/assets/brand-icons/icon-whatsapp.tsx
================================================
import { type SVGProps } from 'react'
import { cn } from '@/lib/utils'

export function IconWhatsapp({ className, ...props }: SVGProps<SVGSVGElement>) {
  return (
    <svg
      role='img'
      viewBox='0 0 24 24'
      xmlns='http://www.w3.org/2000/svg'
      width='24'
      height='24'
      className={cn('[&>path]:stroke-current', className)}
      fill='none'
      stroke='currentColor'
      strokeWidth='2'
      strokeLinecap='round'
      strokeLinejoin='round'
      {...props}
    >
      <title>WhatsApp</title>
      <path strokeWidth='0' d='M0 0h24v24H0z' fill='none' />
      <path d='M3 21l1.65 -3.8a9 9 0 1 1 3.4 2.9l-5.05 .9' />
      <path d='M9 10a.5 .5 0 0 0 1 0v-1a.5 .5 0 0 0 -1 0v1a5 5 0 0 0 5 5h1a.5 .5 0 0 0 0 -1h-1a.5 .5 0 0 0 0 1' />
    </svg>
  )
}


================================================
FILE: src/assets/brand-icons/icon-zoom.tsx
================================================
import { type SVGProps } from 'react'
import { cn } from '@/lib/utils'

export function IconZoom({ className, ...props }: SVGProps<SVGSVGElement>) {
  return (
    <svg
      role='img'
      viewBox='0 0 24 24'
      xmlns='http://www.w3.org/2000/svg'
      width='24'
      height='24'
      className={cn('[&>path]:stroke-current', className)}
      fill='none'
      stroke='currentColor'
      strokeWidth='2'
      strokeLinecap='round'
      strokeLinejoin='round'
      {...props}
    >
      <title>Zoom</title>
      <path strokeWidth='0' d='M0 0h24v24H0z' fill='none' />
      <path d='M17.011 9.385v5.128l3.989 3.487v-12z' />
      <path d='M3.887 6h10.08c1.468 0 3.033 1.203 3.033 2.803v8.196a.991 .991 0 0 1 -.975 1h-10.373c-1.667 0 -2.652 -1.5 -2.652 -3l.01 -8a.882 .882 0 0 1 .208 -.71a.841 .841 0 0 1 .67 -.287z' />
    </svg>
  )
}


================================================
FILE: src/assets/brand-icons/index.ts
================================================
export { IconDiscord } from './icon-discord'
export { IconDocker } from './icon-docker'
export { IconFacebook } from './icon-facebook'
export { IconFigma } from './icon-figma'
export { IconGithub } from './icon-github'
export { IconGitlab } from './icon-gitlab'
export { IconGmail } from './icon-gmail'
export { IconMedium } from './icon-medium'
export { IconNotion } from './icon-notion'
export { IconSkype } from './icon-skype'
export { IconSlack } from './icon-slack'
export { IconStripe } from './icon-stripe'
export { IconTelegram } from './icon-telegram'
export { IconTrello } from './icon-trello'
export { IconWhatsapp } from './icon-whatsapp'
export { IconZoom } from './icon-zoom'


================================================
FILE: src/assets/clerk-full-logo.tsx
================================================
import { type SVGProps } from 'react'

export function ClerkFullLogo(props: SVGProps<SVGSVGElement>) {
  return (
    <svg
      width={77}
      height={24}
      viewBox='0 0 77 24'
      fill='none'
      xmlns='http://www.w3.org/2000/svg'
      {...props}
    >
      <path
        d='M35.148 16.738a4.198 4.198 0 01-3.06 1.283 3.53 3.53 0 01-2.604-1.034c-.619-.645-.975-1.566-.975-2.665 0-2.199 1.432-3.703 3.58-3.703a3.914 3.914 0 013.034 1.377l1.859-1.644c-1.211-1.47-3.176-2.229-5.042-2.229-3.652 0-6.24 2.517-6.24 6.22 0 1.831.643 3.374 1.728 4.463s2.631 1.728 4.415 1.728c2.317 0 4.166-.94 5.203-2.122l-1.898-1.674zM38.727 3.428h2.766V20.34h-2.766V3.428zM54.818 15.283c.046-.368.07-.74.076-1.11 0-3.507-2.296-6.047-5.847-6.047a5.738 5.738 0 00-4.215 1.725c-1.038 1.089-1.66 2.631-1.66 4.47 0 3.749 2.642 6.216 6.146 6.216 2.35 0 4.043-.951 5.058-2.242l-1.812-1.605-.09-.076a3.749 3.749 0 01-3.008 1.406c-1.778 0-3.061-1.037-3.427-2.737h8.779zm-8.733-2.22a3.365 3.365 0 01.737-1.449 3.082 3.082 0 012.368-.996c1.58 0 2.57.988 2.911 2.445h-6.016zM63.445 8.09v3.084a13.36 13.36 0 00-.838-.05c-2.094 0-3.282 1.505-3.282 3.479v5.736h-2.763V8.261h2.763v1.83h.025c.938-1.283 2.284-1.997 3.75-1.997l.345-.004zM69.887 15.281l-1.998 2.222v2.837h-2.764V3.428h2.764v10.374L72.822 8.3h3.283l-4.341 4.86 4.417 7.18h-3.11l-3.133-5.059h-.051z'
        fill='#1F0256'
      />
      <path
        d='M19.116 3.16l-2.88 2.881a.571.571 0 01-.701.084 6.854 6.854 0 00-10.39 5.647 6.867 6.867 0 00.979 3.764.571.571 0 01-.084.699l-2.88 2.88a.57.57 0 01-.865-.063A11.994 11.994 0 0119.051 2.295a.57.57 0 01.065.866z'
        fill='url(#paint0_linear_26568_214324)'
      />
      <path
        d='M19.113 20.829l-2.88-2.88a.571.571 0 00-.7-.085 6.854 6.854 0 01-7.081 0 .571.571 0 00-.7.084l-2.881 2.88a.57.57 0 00.062.877 11.994 11.994 0 0014.114 0 .571.571 0 00.066-.876zM11.997 15.422a3.427 3.427 0 100-6.854 3.427 3.427 0 000 6.854z'
        fill='#1F0256'
      />
      <defs>
        <linearGradient
          id='paint0_linear_26568_214324'
          x1={16.4087}
          y1={-1.75881}
          x2={-7.88473}
          y2={22.5365}
          gradientUnits='userSpaceOnUse'
        >
          <stop stopColor='#17CCFC' />
          <stop offset={0.5} stopColor='#5D31FF' />
          <stop offset={1} stopColor='#F35AFF' />
        </linearGradient>
      </defs>
    </svg>
  )
}


================================================
FILE: src/assets/clerk-logo.tsx
================================================
import { type SVGProps } from 'react'
import { cn } from '@/lib/utils'

export function ClerkLogo({ className, ...props }: SVGProps<SVGSVGElement>) {
  return (
    <svg
      role='img'
      viewBox='0 0 24 24'
      xmlns='http://www.w3.org/2000/svg'
      id='clerk'
      height='24'
      width='24'
      className={cn('[&>path]:fill-foreground', className)}
      {...props}
    >
      <title>Clerk</title>
      <path
        d='m21.47 20.829 -2.881 -2.881a0.572 0.572 0 0 0 -0.7 -0.084 6.854 6.854 0 0 1 -7.081 0 0.576 0.576 0 0 0 -0.7 0.084l-2.881 2.881a0.576 0.576 0 0 0 -0.103 0.69 0.57 0.57 0 0 0 0.166 0.186 12 12 0 0 0 14.113 0 0.58 0.58 0 0 0 0.239 -0.423 0.576 0.576 0 0 0 -0.172 -0.453Zm0.002 -17.668 -2.88 2.88a0.569 0.569 0 0 1 -0.701 0.084A6.857 6.857 0 0 0 8.724 8.08a6.862 6.862 0 0 0 -1.222 3.692 6.86 6.86 0 0 0 0.978 3.764 0.573 0.573 0 0 1 -0.083 0.699l-2.881 2.88a0.567 0.567 0 0 1 -0.864 -0.063A11.993 11.993 0 0 1 6.771 2.7a11.99 11.99 0 0 1 14.637 -0.405 0.566 0.566 0 0 1 0.232 0.418 0.57 0.57 0 0 1 -0.168 0.448Zm-7.118 12.261a3.427 3.427 0 1 0 0 -6.854 3.427 3.427 0 0 0 0 6.854Z'
        strokeWidth='1'
      ></path>
    </svg>
  )
}


================================================
FILE: src/assets/custom/icon-dir.tsx
================================================
import { type SVGProps } from 'react'
import { cn } from '@/lib/utils'
import { type Direction } from '@/context/direction-provider'

type IconDirProps = SVGProps<SVGSVGElement> & {
  dir: Direction
}

export function IconDir({ dir, className, ...props }: IconDirProps) {
  return (
    <svg
      data-name={`icon-dir-${dir}`}
      xmlns='http://www.w3.org/2000/svg'
      viewBox='0 0 79.86 51.14'
      className={cn(dir === 'rtl' && 'rotate-y-180', className)}
      {...props}
    >
      <path
        d='M23.42.51h51.92c2.21 0 4 1.79 4 4v42.18c0 2.21-1.79 4-4 4H23.42s-.04-.02-.04-.04V.55s.02-.04.04-.04z'
        opacity={0.15}
      />
      <path
        fill='none'
        opacity={0.72}
        strokeLinecap='round'
        strokeMiterlimit={10}
        strokeWidth='2px'
        d='M5.56 14.88L17.78 14.88'
      />
      <path
        fill='none'
        opacity={0.48}
        strokeLinecap='round'
        strokeMiterlimit={10}
        strokeWidth='2px'
        d='M5.56 22.09L16.08 22.09'
      />
      <path
        fill='none'
        opacity={0.55}
        strokeLinecap='round'
        strokeMiterlimit={10}
        strokeWidth='2px'
        d='M5.56 18.38L14.93 18.38'
      />
      <g strokeLinecap='round' strokeMiterlimit={10}>
        <circle cx={7.51} cy={7.4} r={2.54} opacity={0.8} />
        <path
          fill='none'
          opacity={0.8}
          strokeWidth='2px'
          d='M12.06 6.14L17.78 6.14'
        />
        <path fill='none' opacity={0.6} d='M11.85 8.79L16.91 8.79' />
      </g>
      <path
        fill='none'
        opacity={0.62}
        strokeLinecap='round'
        strokeMiterlimit={10}
        strokeWidth='3px'
        d='M29.41 7.4L34.67 7.4'
      />
      <rect
        x={28.76}
        y={11.21}
        width={26.03}
        height={2.73}
        rx={0.64}
        ry={0.64}
        opacity={0.44}
        strokeLinecap='round'
        strokeMiterlimit={10}
      />
      <rect
        x={28.76}
        y={17.01}
        width={44.25}
        height={13.48}
        rx={0.64}
        ry={0.64}
        opacity={0.3}
        strokeLinecap='round'
        strokeMiterlimit={10}
      />
      <rect
        x={28.76}
        y={33.57}
        width={44.25}
        height={4.67}
        rx={0.64}
        ry={0.64}
        opacity={0.21}
        strokeLinecap='round'
        strokeMiterlimit={10}
      />
      <rect
        x={28.76}
        y={41.32}
        width={36.21}
        height={4.67}
        rx={0.64}
        ry={0.64}
        opacity={0.3}
        strokeLinecap='round'
        strokeMiterlimit={10}
      />
    </svg>
  )
}


================================================
FILE: src/assets/custom/icon-layout-compact.tsx
================================================
import { type SVGProps } from 'react'

export function IconLayoutCompact(props: SVGProps<SVGSVGElement>) {
  return (
    <svg
      data-name='icon-layout-compact'
      xmlns='http://www.w3.org/2000/svg'
      viewBox='0 0 79.86 51.14'
      {...props}
    >
      <rect
        x={5.84}
        y={5.2}
        width={4}
        height={40}
        rx={2}
        ry={2}
        strokeLinecap='round'
        strokeMiterlimit={10}
      />
      <g stroke='#fff' strokeLinecap='round' strokeMiterlimit={10}>
        <path
          fill='none'
          opacity={0.66}
          strokeWidth='2px'
          d='M7.26 11.56L8.37 11.56'
        />
        <path
          fill='none'
          opacity={0.51}
          strokeWidth='2px'
          d='M7.26 14.49L8.37 14.49'
        />
        <path
          fill='none'
          opacity={0.52}
          strokeWidth='2px'
          d='M7.26 17.39L8.37 17.39'
        />
        <circle cx={7.81} cy={7.25} r={1.16} fill='#fff' opacity={0.8} />
      </g>
      <path
        fill='none'
        opacity={0.75}
        strokeLinecap='round'
        strokeMiterlimit={10}
        strokeWidth='3px'
        d='M15.81 14.49L22.89 14.49'
      />
      <rect
        x={14.93}
        y={18.39}
        width={22.19}
        height={2.73}
        rx={0.64}
        ry={0.64}
        opacity={0.5}
        strokeLinecap='round'
        strokeMiterlimit={10}
      />
      <rect
        x={14.93}
        y={5.89}
        width={59.16}
        height={2.73}
        rx={0.64}
        ry={0.64}
        opacity={0.9}
        strokeLinecap='round'
        strokeMiterlimit={10}
      />
      <rect
        x={14.93}
        y={24.22}
        width={32.68}
        height={19.95}
        rx={2.11}
        ry={2.11}
        opacity={0.4}
        strokeLinecap='round'
        strokeMiterlimit={10}
      />
      <g strokeLinecap='round' strokeMiterlimit={10}>
        <rect
          x={59.05}
          y={38.15}
          width={2.01}
          height={3.42}
          rx={0.33}
          ry={0.33}
          opacity={0.32}
        />
        <rect
          x={54.78}
          y={34.99}
          width={2.01}
          height={6.58}
          rx={0.33}
          ry={0.33}
          opacity={0.44}
        />
        <rect
          x={63.17}
          y={32.86}
          width={2.01}
          height={8.7}
          rx={0.33}
          ry={0.33}
          opacity={0.53}
        />
        <rect
          x={67.54}
          y={29.17}
          width={2.01}
          height={12.4}
          rx={0.33}
          ry={0.33}
          opacity={0.66}
        />
      </g>
      <g opacity={0.5}>
        <circle cx={62.16} cy={18.63} r={7.5} />
        <path d='M62.16 11.63c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.14-7-7 3.14-7 7-7m0-1c-4.42 0-8 3.58-8 8s3.58 8 8 8 8-3.58 8-8-3.58-8-8-8z' />
      </g>
      <g opacity={0.74}>
        <path d='M63.04 18.13l3.38-5.67c.93.64 1.7 1.48 2.26 2.47.56.98.89 2.08.96 3.21h-6.6z' />
        <path d='M66.57 13.19a6.977 6.977 0 012.52 4.44h-5.17l2.65-4.44m-.31-1.43l-4.1 6.87h8c0-1.39-.36-2.75-1.04-3.95a8.007 8.007 0 00-2.86-2.92z' />
      </g>
    </svg>
  )
}


================================================
FILE: src/assets/custom/icon-layout-default.tsx
================================================
import { type SVGProps } from 'react'

export function IconLayoutDefault(props: SVGProps<SVGSVGElement>) {
  return (
    <svg
      data-name='con-layout-default'
      xmlns='http://www.w3.org/2000/svg'
      viewBox='0 0 79.86 51.14'
      {...props}
    >
      <path
        d='M39.22 15.99h-8.16c-.79 0-1.43-.67-1.43-1.5s.64-1.5 1.43-1.5h8.16c.79 0 1.43.67 1.43 1.5s-.64 1.5-1.43 1.5z'
        opacity={0.75}
      />
      <rect
        x={29.63}
        y={18.39}
        width={16.72}
        height={2.73}
        rx={1.36}
        ry={1.36}
        opacity={0.5}
      />
      <path
        d='M75.1 6.68v1.45c0 .63-.49 1.14-1.09 1.14H30.72c-.6 0-1.09-.51-1.09-1.14V6.68c0-.62.49-1.14 1.09-1.14h43.29c.6 0 1.09.52 1.09 1.14z'
        opacity={0.9}
      />
      <rect
        x={29.63}
        y={24.22}
        width={21.8}
        height={19.95}
        rx={2.11}
        ry={2.11}
        opacity={0.4}
      />
      <g strokeLinecap='round' strokeMiterlimit={10}>
        <rect
          x={61.06}
          y={38.15}
          width={2.01}
          height={3.42}
          rx={0.33}
          ry={0.33}
          opacity={0.32}
        />
        <rect
          x={56.78}
          y={34.99}
          width={2.01}
          height={6.58}
          rx={0.33}
          ry={0.33}
          opacity={0.44}
        />
        <rect
          x={65.17}
          y={32.86}
          width={2.01}
          height={8.7}
          rx={0.33}
          ry={0.33}
          opacity={0.53}
        />
        <rect
          x={69.55}
          y={29.17}
          width={2.01}
          height={12.4}
          rx={0.33}
          ry={0.33}
          opacity={0.66}
        />
      </g>
      <g opacity={0.5}>
        <circle cx={63.17} cy={18.63} r={7.5} />
        <path d='M63.17 11.63c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.14-7-7 3.14-7 7-7m0-1c-4.42 0-8 3.58-8 8s3.58 8 8 8 8-3.58 8-8-3.58-8-8-8z' />
      </g>
      <g opacity={0.74}>
        <path d='M64.05 18.13l3.38-5.67c.93.64 1.7 1.48 2.26 2.47.56.98.89 2.08.96 3.21h-6.6z' />
        <path d='M67.57 13.19a6.977 6.977 0 012.52 4.44h-5.17l2.65-4.44m-.31-1.43l-4.1 6.87h8c0-1.39-.36-2.75-1.04-3.95a8.007 8.007 0 00-2.86-2.92z' />
      </g>
      <g strokeLinecap='round' strokeMiterlimit={10}>
        <rect
          x={5.84}
          y={5.02}
          width={19.14}
          height={40}
          rx={2}
          ry={2}
          opacity={0.8}
        />
        <g stroke='#fff'>
          <path
            fill='none'
            opacity={0.72}
            strokeWidth='2px'
            d='M9.02 17.39L21.25 17.39'
          />
          <path
            fill='none'
            opacity={0.48}
            strokeWidth='2px'
            d='M9.02 24.6L19.54 24.6'
          />
          <path
            fill='none'
            opacity={0.55}
            strokeWidth='2px'
            d='M9.02 20.88L18.4 20.88'
          />
          <circle cx={10.98} cy={9.91} r={2.54} fill='#fff' opacity={0.8} />
          <path
            fill='none'
            opacity={0.8}
            strokeWidth='2px'
            d='M15.53 8.65L21.25 8.65'
          />
          <path fill='none' opacity={0.6} d='M15.32 11.3L20.38 11.3' />
        </g>
      </g>
    </svg>
  )
}


================================================
FILE: src/assets/custom/icon-layout-full.tsx
================================================
import { type SVGProps } from 'react'

export function IconLayoutFull(props: SVGProps<SVGSVGElement>) {
  return (
    <svg
      data-name='icon-layout-full'
      xmlns='http://www.w3.org/2000/svg'
      viewBox='0 0 79.86 51.14'
      {...props}
    >
      <path
        fill='none'
        opacity={0.75}
        strokeLinecap='round'
        strokeMiterlimit={10}
        strokeWidth='3px'
        d='M6.85 14.49L15.02 14.49'
      />
      <rect
        x={5.84}
        y={18.39}
        width={25.6}
        height={2.73}
        rx={0.64}
        ry={0.64}
        opacity={0.5}
        strokeLinecap='round'
        strokeMiterlimit={10}
      />
      <rect
        x={5.84}
        y={5.89}
        width={68.26}
        height={2.73}
        rx={0.64}
        ry={0.64}
        opacity={0.9}
        strokeLinecap='round'
        strokeMiterlimit={10}
      />
      <rect
        x={5.84}
        y={24.22}
        width={37.71}
        height={19.95}
        rx={2.11}
        ry={2.11}
        opacity={0.4}
        strokeLinecap='round'
        strokeMiterlimit={10}
      />
      <g strokeLinecap='round' strokeMiterlimit={10}>
        <rect
          x={59.05}
          y={38.15}
          width={2.01}
          height={3.42}
          rx={0.33}
          ry={0.33}
          opacity={0.32}
        />
        <rect
          x={54.78}
          y={34.99}
          width={2.01}
          height={6.58}
          rx={0.33}
          ry={0.33}
          opacity={0.44}
        />
        <rect
          x={63.17}
          y={32.86}
          width={2.01}
          height={8.7}
          rx={0.33}
          ry={0.33}
          opacity={0.53}
        />
        <rect
          x={67.54}
          y={29.17}
          width={2.01}
          height={12.4}
          rx={0.33}
          ry={0.33}
          opacity={0.66}
        />
      </g>
      <g opacity={0.5}>
        <circle cx={62.16} cy={18.63} r={7.5} />
        <path d='M62.16 11.63c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.14-7-7 3.14-7 7-7m0-1c-4.42 0-8 3.58-8 8s3.58 8 8 8 8-3.58 8-8-3.58-8-8-8z' />
      </g>
      <g opacity={0.74}>
        <path d='M63.04 18.13l3.38-5.67c.93.64 1.7 1.48 2.26 2.47.56.98.89 2.08.96 3.21h-6.6z' />
        <path d='M66.57 13.19a6.977 6.977 0 012.52 4.44h-5.17l2.65-4.44m-.31-1.43l-4.1 6.87h8c0-1.39-.36-2.75-1.04-3.95a8.007 8.007 0 00-2.86-2.92z' />
      </g>
    </svg>
  )
}


================================================
FILE: src/assets/custom/icon-sidebar-floating.tsx
================================================
import { type SVGProps } from 'react'

export function IconSidebarFloating(props: SVGProps<SVGSVGElement>) {
  return (
    <svg
      data-name='icon-sidebar-floating'
      xmlns='http://www.w3.org/2000/svg'
      viewBox='0 0 79.86 51.14'
      {...props}
    >
      <rect
        x={5.89}
        y={5.15}
        width={19.74}
        height={40}
        rx={2}
        ry={2}
        opacity={0.8}
        strokeLinecap='round'
        strokeMiterlimit={10}
      />
      <g stroke='#fff' strokeLinecap='round' strokeMiterlimit={10}>
        <path
          fill='none'
          opacity={0.72}
          strokeWidth='2px'
          d='M9.81 18.36L22.04 18.36'
        />
        <path
          fill='none'
          opacity={0.48}
          strokeWidth='2px'
          d='M9.81 25.57L20.33 25.57'
        />
        <path
          fill='none'
          opacity={0.55}
          strokeWidth='2px'
          d='M9.81 21.85L19.18 21.85'
        />
        <circle cx={11.76} cy={10.88} r={2.54} fill='#fff' opacity={0.8} />
        <path
          fill='none'
          opacity={0.8}
          strokeWidth='2px'
          d='M16.31 9.62L22.04 9.62'
        />
        <path fill='none' opacity={0.6} d='M16.1 12.27L21.16 12.27' />
      </g>
      <path
        fill='none'
        opacity={0.62}
        strokeLinecap='round'
        strokeMiterlimit={10}
        strokeWidth='3px'
        d='M30.59 9.62L35.85 9.62'
      />
      <rect
        x={29.94}
        y={13.42}
        width={26.03}
        height={2.73}
        rx={0.64}
        ry={0.64}
        opacity={0.44}
        strokeLinecap='round'
        strokeMiterlimit={10}
      />
      <rect
        x={29.94}
        y={19.28}
        width={43.11}
        height={25.87}
        rx={2}
        ry={2}
        opacity={0.3}
        strokeLinecap='round'
        strokeMiterlimit={10}
      />
    </svg>
  )
}


================================================
FILE: src/assets/custom/icon-sidebar-inset.tsx
================================================
import { type SVGProps } from 'react'

export function IconSidebarInset(props: SVGProps<SVGSVGElement>) {
  return (
    <svg
      data-name='icon-sidebar-inset'
      xmlns='http://www.w3.org/2000/svg'
      viewBox='0 0 79.86 51.14'
      {...props}
    >
      <rect
        x={23.39}
        y={5.57}
        width={50.22}
        height={40}
        rx={2}
        ry={2}
        opacity={0.2}
        strokeLinecap='round'
        strokeMiterlimit={10}
      />
      <path
        fill='none'
        opacity={0.72}
        strokeLinecap='round'
        strokeMiterlimit={10}
        strokeWidth='2px'
        d='M5.08 17.05L17.31 17.05'
      />
      <path
        fill='none'
        opacity={0.48}
        strokeLinecap='round'
        strokeMiterlimit={10}
        strokeWidth='2px'
        d='M5.08 24.25L15.6 24.25'
      />
      <path
        fill='none'
        opacity={0.55}
        strokeLinecap='round'
        strokeMiterlimit={10}
        strokeWidth='2px'
        d='M5.08 20.54L14.46 20.54'
      />
      <g strokeLinecap='round' strokeMiterlimit={10}>
        <circle cx={7.04} cy={9.57} r={2.54} opacity={0.8} />
        <path
          fill='none'
          opacity={0.8}
          strokeWidth='2px'
          d='M11.59 8.3L17.31 8.3'
        />
        <path fill='none' opacity={0.6} d='M11.38 10.95L16.44 10.95' />
      </g>
    </svg>
  )
}


================================================
FILE: src/assets/custom/icon-sidebar-sidebar.tsx
================================================
import { type SVGProps } from 'react'

export function IconSidebarSidebar(props: SVGProps<SVGSVGElement>) {
  return (
    <svg
      data-name='icon-sidebar-sidebar'
      xmlns='http://www.w3.org/2000/svg'
      viewBox='0 0 79.86 51.14'
      {...props}
    >
      <path
        d='M23.42.51h51.99c2.21 0 4 1.79 4 4v42.18c0 2.21-1.79 4-4 4H23.42s-.04-.02-.04-.04V.55s.02-.04.04-.04z'
        opacity={0.2}
        strokeLinecap='round'
        strokeMiterlimit={10}
      />
      <path
        fill='none'
        opacity={0.72}
        strokeLinecap='round'
        strokeMiterlimit={10}
        strokeWidth='2px'
        d='M5.56 14.88L17.78 14.88'
      />
      <path
        fill='none'
        opacity={0.48}
        strokeLinecap='round'
        strokeMiterlimit={10}
        strokeWidth='2px'
        d='M5.56 22.09L16.08 22.09'
      />
      <path
        fill='none'
        opacity={0.55}
        strokeLinecap='round'
        strokeMiterlimit={10}
        strokeWidth='2px'
        d='M5.56 18.38L14.93 18.38'
      />
      <g strokeLinecap='round' strokeMiterlimit={10}>
        <circle cx={7.51} cy={7.4} r={2.54} opacity={0.8} />
        <path
          fill='none'
          opacity={0.8}
          strokeWidth='2px'
          d='M12.06 6.14L17.78 6.14'
        />
        <path fill='none' opacity={0.6} d='M11.85 8.79L16.91 8.79' />
      </g>
    </svg>
  )
}


================================================
FILE: src/assets/custom/icon-theme-dark.tsx
================================================
import { type SVGProps } from 'react'

export function IconThemeDark(props: SVGProps<SVGSVGElement>) {
  return (
    <svg
      data-name='icon-theme-dark'
      xmlns='http://www.w3.org/2000/svg'
      viewBox='0 0 79.86 51.14'
      {...props}
    >
      <g fill='#1d2b3f'>
        <rect x={0.53} y={0.5} width={78.83} height={50.14} rx={3.5} ry={3.5} />
        <path d='M75.86 1c1.65 0 3 1.35 3 3v43.14c0 1.65-1.35 3-3 3H4.03c-1.65 0-3-1.35-3-3V4c0-1.65 1.35-3 3-3h71.83m0-1H4.03c-2.21 0-4 1.79-4 4v43.14c0 2.21 1.79 4 4 4h71.83c2.21 0 4-1.79 4-4V4c0-2.21-1.79-4-4-4z' />
      </g>
      <path
        d='M22.88 0h52.97c2.21 0 4 1.79 4 4v43.14c0 2.21-1.79 4-4 4H22.88V0z'
        fill='#0d1628'
      />
      <circle cx={6.7} cy={7.04} r={3.54} fill='#426187' />
      <path
        d='M18.12 6.39h-5.87c-.6 0-1.09-.45-1.09-1s.49-1 1.09-1h5.87c.6 0 1.09.45 1.09 1s-.49 1-1.09 1zM16.55 9.77h-4.24c-.55 0-1-.45-1-1s.45-1 1-1h4.24c.55 0 1 .45 1 1s-.45 1-1 1zM18.32 17.37H4.59c-.69 0-1.25-.47-1.25-1.05s.56-1.05 1.25-1.05h13.73c.69 0 1.25.47 1.25 1.05s-.56 1.05-1.25 1.05zM15.34 21.26h-11c-.55 0-1-.41-1-.91s.45-.91 1-.91h11c.55 0 1 .41 1 .91s-.45.91-1 .91zM16.46 25.57H4.43c-.6 0-1.09-.44-1.09-.98s.49-.98 1.09-.98h12.03c.6 0 1.09.44 1.09.98s-.49.98-1.09.98z'
        fill='#426187'
      />
      <g fill='#2a62bc'>
        <rect
          x={33.36}
          y={19.73}
          width={2.75}
          height={3.42}
          rx={0.33}
          ry={0.33}
          opacity={0.32}
        />
        <rect
          x={29.64}
          y={16.57}
          width={2.75}
          height={6.58}
          rx={0.33}
          ry={0.33}
          opacity={0.44}
        />
        <rect
          x={37.16}
          y={14.44}
          width={2.75}
          height={8.7}
          rx={0.33}
          ry={0.33}
          opacity={0.53}
        />
        <rect
          x={41.19}
          y={10.75}
          width={2.75}
          height={12.4}
          rx={0.33}
          ry={0.33}
          opacity={0.53}
        />
      </g>
      <circle cx={62.74} cy={16.32} r={8} fill='#2f5491' opacity={0.5} />
      <path
        d='M62.74 16.32l4.1-6.87c1.19.71 2.18 1.72 2.86 2.92s1.04 2.57 1.04 3.95h-8z'
        fill='#2f5491'
        opacity={0.74}
      />
      <rect
        x={29.64}
        y={27.75}
        width={41.62}
        height={18.62}
        rx={1.69}
        ry={1.69}
        fill='#17273f'
      />
    </svg>
  )
}


================================================
FILE: src/assets/custom/icon-theme-light.tsx
================================================
import { type SVGProps } from 'react'

export function IconThemeLight(props: SVGProps<SVGSVGElement>) {
  return (
    <svg
      data-name='icon-theme-light'
      xmlns='http://www.w3.org/2000/svg'
      viewBox='0 0 79.86 51.14'
      {...props}
    >
      <g fill='#d9d9d9'>
        <rect x={0.53} y={0.5} width={78.83} height={50.14} rx={3.5} ry={3.5} />
        <path d='M75.86 1c1.65 0 3 1.35 3 3v43.14c0 1.65-1.35 3-3 3H4.03c-1.65 0-3-1.35-3-3V4c0-1.65 1.35-3 3-3h71.83m0-1H4.03c-2.21 0-4 1.79-4 4v43.14c0 2.21 1.79 4 4 4h71.83c2.21 0 4-1.79 4-4V4c0-2.21-1.79-4-4-4z' />
      </g>
      <path
        d='M22.88 0h52.97c2.21 0 4 1.79 4 4v43.14c0 2.21-1.79 4-4 4H22.88V0z'
        fill='#ecedef'
      />
      <circle cx={6.7} cy={7.04} r={3.54} fill='#fff' />
      <path
        d='M18.12 6.39h-5.87c-.6 0-1.09-.45-1.09-1s.49-1 1.09-1h5.87c.6 0 1.09.45 1.09 1s-.49 1-1.09 1zM16.55 9.77h-4.24c-.55 0-1-.45-1-1s.45-1 1-1h4.24c.55 0 1 .45 1 1s-.45 1-1 1zM18.32 17.37H4.59c-.69 0-1.25-.47-1.25-1.05s.56-1.05 1.25-1.05h13.73c.69 0 1.25.47 1.25 1.05s-.56 1.05-1.25 1.05zM15.34 21.26h-11c-.55 0-1-.41-1-.91s.45-.91 1-.91h11c.55 0 1 .41 1 .91s-.45.91-1 .91zM16.46 25.57H4.43c-.6 0-1.09-.44-1.09-.98s.49-.98 1.09-.98h12.03c.6 0 1.09.44 1.09.98s-.49.98-1.09.98z'
        fill='#fff'
      />
      <g fill='#c0c4c4'>
        <rect
          x={33.36}
          y={19.73}
          width={2.75}
          height={3.42}
          rx={0.33}
          ry={0.33}
          opacity={0.32}
        />
        <rect
          x={29.64}
          y={16.57}
          width={2.75}
          height={6.58}
          rx={0.33}
          ry={0.33}
          opacity={0.44}
        />
        <rect
          x={37.16}
          y={14.44}
          width={2.75}
          height={8.7}
          rx={0.33}
          ry={0.33}
          opacity={0.53}
        />
        <rect
          x={41.19}
          y={10.75}
          width={2.75}
          height={12.4}
          rx={0.33}
          ry={0.33}
          opacity={0.53}
        />
      </g>
      <circle cx={62.74} cy={16.32} r={8} fill='#fff' />
      <g fill='#d9d9d9'>
        <path d='M63.62 15.82L67 10.15c.93.64 1.7 1.48 2.26 2.47.56.98.89 2.08.96 3.21h-6.6z' />
        <path d='M67.14 10.88a6.977 6.977 0 012.52 4.44h-5.17l2.65-4.44m-.31-1.43l-4.1 6.87h8c0-1.39-.36-2.75-1.04-3.95s-1.67-2.21-2.86-2.92z' />
      </g>
      <rect
        x={29.64}
        y={27.75}
        width={41.62}
        height={18.62}
        rx={1.69}
        ry={1.69}
        fill='#fff'
      />
    </svg>
  )
}


================================================
FILE: src/assets/custom/icon-theme-system.tsx
================================================
import { type SVGProps } from 'react'
import { cn } from '@/lib/utils'

export function IconThemeSystem({
  className,
  ...props
}: SVGProps<SVGSVGElement>) {
  return (
    <svg
      data-name='icon-theme-system'
      xmlns='http://www.w3.org/2000/svg'
      viewBox='0 0 79.86 51.14'
      className={cn(
        'overflow-hidden rounded-[6px]',
        'fill-primary stroke-primary group-data-[state=unchecked]:fill-muted-foreground group-data-[state=unchecked]:stroke-muted-foreground',
        className
      )}
      {...props}
    >
      <path opacity={0.2} d='M0 0.03H22.88V51.17H0z' />
      <circle
        cx={6.7}
        cy={7.04}
        r={3.54}
        fill='#fff'
        opacity={0.8}
        stroke='#fff'
        strokeLinecap='round'
        strokeMiterlimit={10}
      />
      <path
        d='M18.12 6.39h-5.87c-.6 0-1.09-.45-1.09-1s.49-1 1.09-1h5.87c.6 0 1.09.45 1.09 1s-.49 1-1.09 1zM16.55 9.77h-4.24c-.55 0-1-.45-1-1s.45-1 1-1h4.24c.55 0 1 .45 1 1s-.45 1-1 1z'
        fill='#fff'
        stroke='none'
        opacity={0.75}
      />
      <path
        d='M18.32 17.37H4.59c-.69 0-1.25-.47-1.25-1.05s.56-1.05 1.25-1.05h13.73c.69 0 1.25.47 1.25 1.05s-.56 1.05-1.25 1.05z'
        fill='#fff'
        stroke='none'
        opacity={0.72}
      />
      <path
        d='M15.34 21.26h-11c-.55 0-1-.41-1-.91s.45-.91 1-.91h11c.55 0 1 .41 1 .91s-.45.91-1 .91z'
        fill='#fff'
        stroke='none'
        opacity={0.55}
      />
      <path
        d='M16.46 25.57H4.43c-.6 0-1.09-.44-1.09-.98s.49-.98 1.09-.98h12.03c.6 0 1.09.44 1.09.98s-.49.98-1.09.98z'
        fill='#fff'
        stroke='none'
        opacity={0.67}
      />
      <rect
        x={33.36}
        y={19.73}
        width={2.75}
        height={3.42}
        rx={0.33}
        ry={0.33}
        opacity={0.31}
        stroke='none'
      />
      <rect
        x={29.64}
        y={16.57}
        width={2.75}
        height={6.58}
        rx={0.33}
        ry={0.33}
        opacity={0.4}
        stroke='none'
      />
      <rect
        x={37.16}
        y={14.44}
        width={2.75}
        height={8.7}
        rx={0.33}
        ry={0.33}
        opacity={0.26}
        stroke='none'
      />
      <rect
        x={41.19}
        y={10.75}
        width={2.75}
        height={12.4}
        rx={0.33}
        ry={0.33}
        opacity={0.37}
        stroke='none'
      />
      <g>
        <circle cx={62.74} cy={16.32} r={8} opacity={0.25} />
        <path
          d='M62.74 16.32l4.1-6.87c1.19.71 2.18 1.72 2.86 2.92s1.04 2.57 1.04 3.95h-8z'
          opacity={0.45}
        />
      </g>
      <rect
        x={29.64}
        y={27.75}
        width={41.62}
        height={18.62}
        rx={1.69}
        ry={1.69}
        opacity={0.3}
        stroke='none'
        strokeLinecap='round'
        strokeMiterlimit={10}
      />
    </svg>
  )
}


================================================
FILE: src/assets/logo.tsx
================================================
import { type SVGProps } from 'react'
import { cn } from '@/lib/utils'

export function Logo({ className, ...props }: SVGProps<SVGSVGElement>) {
  return (
    <svg
      id='shadcn-admin-logo'
      viewBox='0 0 24 24'
      xmlns='http://www.w3.org/2000/svg'
      height='24'
      width='24'
      fill='none'
      stroke='currentColor'
      strokeWidth='2'
      strokeLinecap='round'
      strokeLinejoin='round'
      className={cn('size-6', className)}
      {...props}
    >
      <title>Shadcn-Admin</title>
      <path d='M15 6v12a3 3 0 1 0 3-3H6a3 3 0 1 0 3 3V6a3 3 0 1 0-3 3h12a3 3 0 1 0-3-3' />
    </svg>
  )
}


================================================
FILE: src/components/coming-soon.tsx
================================================
import { Telescope } from 'lucide-react'

export function ComingSoon() {
  return (
    <div className='h-svh'>
      <div className='m-auto flex h-full w-full flex-col items-center justify-center gap-2'>
        <Telescope size={72} />
        <h1 className='text-4xl leading-tight font-bold'>Coming Soon!</h1>
        <p className='text-center text-muted-foreground'>
          This page has not been created yet. <br />
          Stay tuned though!
        </p>
      </div>
    </div>
  )
}


================================================
FILE: src/components/command-menu.tsx
================================================
import React from 'react'
import { useNavigate } from '@tanstack/react-router'
import { ArrowRight, ChevronRight, Laptop, Moon, Sun } from 'lucide-react'
import { useSearch } from '@/context/search-provider'
import { useTheme } from '@/context/theme-provider'
import {
  CommandDialog,
  CommandEmpty,
  CommandGroup,
  CommandInput,
  CommandItem,
  CommandList,
  CommandSeparator,
} from '@/components/ui/command'
import { sidebarData } from './layout/data/sidebar-data'
import { ScrollArea } from './ui/scroll-area'

export function CommandMenu() {
  const navigate = useNavigate()
  const { setTheme } = useTheme()
  const { open, setOpen } = useSearch()

  const runCommand = React.useCallback(
    (command: () => unknown) => {
      setOpen(false)
      command()
    },
    [setOpen]
  )

  return (
    <CommandDialog modal open={open} onOpenChange={setOpen}>
      <CommandInput placeholder='Type a command or search...' />
      <CommandList>
        <ScrollArea type='hover' className='h-72 pe-1'>
          <CommandEmpty>No results found.</CommandEmpty>
          {sidebarData.navGroups.map((group) => (
            <CommandGroup key={group.title} heading={group.title}>
              {group.items.map((navItem, i) => {
                if (navItem.url)
                  return (
                    <CommandItem
                      key={`${navItem.url}-${i}`}
                      value={navItem.title}
                      onSelect={() => {
                        runCommand(() => navigate({ to: navItem.url }))
                      }}
                    >
                      <div className='flex size-4 items-center justify-center'>
                        <ArrowRight className='size-2 text-muted-foreground/80' />
                      </div>
                      {navItem.title}
                    </CommandItem>
                  )

                return navItem.items?.map((subItem, i) => (
                  <CommandItem
                    key={`${navItem.title}-${subItem.url}-${i}`}
                    value={`${navItem.title}-${subItem.url}`}
                    onSelect={() => {
                      runCommand(() => navigate({ to: subItem.url }))
                    }}
                  >
                    <div className='flex size-4 items-center justify-center'>
                      <ArrowRight className='size-2 text-muted-foreground/80' />
                    </div>
                    {navItem.title} <ChevronRight /> {subItem.title}
                  </CommandItem>
                ))
              })}
            </CommandGroup>
          ))}
          <CommandSeparator />
          <CommandGroup heading='Theme'>
            <CommandItem onSelect={() => runCommand(() => setTheme('light'))}>
              <Sun /> <span>Light</span>
            </CommandItem>
            <CommandItem onSelect={() => runCommand(() => setTheme('dark'))}>
              <Moon className='scale-90' />
              <span>Dark</span>
            </CommandItem>
            <CommandItem onSelect={() => runCommand(() => setTheme('system'))}>
              <Laptop />
              <span>System</span>
            </CommandItem>
          </CommandGroup>
        </ScrollArea>
      </CommandList>
    </CommandDialog>
  )
}


================================================
FILE: src/components/config-drawer.tsx
================================================
import { type SVGProps } from 'react'
import { Root as Radio, Item } from '@radix-ui/react-radio-group'
import { CircleCheck, RotateCcw, Settings } from 'lucide-react'
import { IconDir } from '@/assets/custom/icon-dir'
import { IconLayoutCompact } from '@/assets/custom/icon-layout-compact'
import { IconLayoutDefault } from '@/assets/custom/icon-layout-default'
import { IconLayoutFull } from '@/assets/custom/icon-layout-full'
import { IconSidebarFloating } from '@/assets/custom/icon-sidebar-floating'
import { IconSidebarInset } from '@/assets/custom/icon-sidebar-inset'
import { IconSidebarSidebar } from '@/assets/custom/icon-sidebar-sidebar'
import { IconThemeDark } from '@/assets/custom/icon-theme-dark'
import { IconThemeLight } from '@/assets/custom/icon-theme-light'
import { IconThemeSystem } from '@/assets/custom/icon-theme-system'
import { cn } from '@/lib/utils'
import { useDirection } from '@/context/direction-provider'
import { type Collapsible, useLayout } from '@/context/layout-provider'
import { useTheme } from '@/context/theme-provider'
import { Button } from '@/components/ui/button'
import {
  Sheet,
  SheetContent,
  SheetDescription,
  SheetFooter,
  SheetHeader,
  SheetTitle,
  SheetTrigger,
} from '@/components/ui/sheet'
import { useSidebar } from './ui/sidebar'

export function ConfigDrawer() {
  const { setOpen } = useSidebar()
  const { resetDir } = useDirection()
  const { resetTheme } = useTheme()
  const { resetLayout } = useLayout()

  const handleReset = () => {
    setOpen(true)
    resetDir()
    resetTheme()
    resetLayout()
  }

  return (
    <Sheet>
      <SheetTrigger asChild>
        <Button
          size='icon'
          variant='ghost'
          aria-label='Open theme settings'
          aria-describedby='config-drawer-description'
          className='rounded-full'
        >
          <Settings aria-hidden='true' />
        </Button>
      </SheetTrigger>
      <SheetContent className='flex flex-col'>
        <SheetHeader className='pb-0 text-start'>
          <SheetTitle>Theme Settings</SheetTitle>
          <SheetDescription id='config-drawer-description'>
            Adjust the appearance and layout to suit your preferences.
          </SheetDescription>
        </SheetHeader>
        <div className='space-y-6 overflow-y-auto px-4'>
          <ThemeConfig />
          <SidebarConfig />
          <LayoutConfig />
          <DirConfig />
        </div>
        <SheetFooter className='gap-2'>
          <Button
            variant='destructive'
            onClick={handleReset}
            aria-label='Reset all settings to default values'
          >
            Reset
          </Button>
        </SheetFooter>
      </SheetContent>
    </Sheet>
  )
}

function SectionTitle({
  title,
  showReset = false,
  onReset,
  className,
}: {
  title: string
  showReset?: boolean
  onReset?: () => void
  className?: string
}) {
  return (
    <div
      className={cn(
        'mb-2 flex items-center gap-2 text-sm font-semibold text-muted-foreground',
        className
      )}
    >
      {title}
      {showReset && onReset && (
        <Button
          size='icon'
          variant='secondary'
          className='size-4 rounded-full'
          onClick={onReset}
        >
          <RotateCcw className='size-3' />
        </Button>
      )}
    </div>
  )
}

function RadioGroupItem({
  item,
  isTheme = false,
}: {
  item: {
    value: string
    label: string
    icon: (props: SVGProps<SVGSVGElement>) => React.ReactElement
  }
  isTheme?: boolean
}) {
  return (
    <Item
      value={item.value}
      className={cn('group outline-none', 'transition duration-200 ease-in')}
      aria-label={`Select ${item.label.toLowerCase()}`}
      aria-describedby={`${item.value}-description`}
    >
      <div
        className={cn(
          'relative rounded-[6px] ring-[1px] ring-border',
          'group-data-[state=checked]:shadow-2xl group-data-[state=checked]:ring-primary',
          'group-focus-visible:ring-2'
        )}
        role='img'
        aria-hidden='false'
        aria-label={`${item.label} option preview`}
      >
        <CircleCheck
          className={cn(
            'size-6 fill-primary stroke-white',
            'group-data-[state=unchecked]:hidden',
            'absolute top-0 right-0 translate-x-1/2 -translate-y-1/2'
          )}
          aria-hidden='true'
        />
        <item.icon
          className={cn(
            !isTheme &&
              'fill-primary stroke-primary group-data-[state=unchecked]:fill-muted-foreground group-data-[state=unchecked]:stroke-muted-foreground'
          )}
          aria-hidden='true'
        />
      </div>
      <div
        className='mt-1 text-xs'
        id={`${item.value}-description`}
        aria-live='polite'
      >
        {item.label}
      </div>
    </Item>
  )
}

function ThemeConfig() {
  const { defaultTheme, theme, setTheme } = useTheme()
  return (
    <div>
      <SectionTitle
        title='Theme'
        showReset={theme !== defaultTheme}
        onReset={() => setTheme(defaultTheme)}
      />
      <Radio
        value={theme}
        onValueChange={setTheme}
        className='grid w-full max-w-md grid-cols-3 gap-4'
        aria-label='Select theme preference'
        aria-describedby='theme-description'
      >
        {[
          {
            value: 'system',
            label: 'System',
            icon: IconThemeSystem,
          },
          {
            value: 'light',
            label: 'Light',
            icon: IconThemeLight,
          },
          {
            value: 'dark',
            label: 'Dark',
            icon: IconThemeDark,
          },
        ].map((item) => (
          <RadioGroupItem key={item.value} item={item} isTheme />
        ))}
      </Radio>
      <div id='theme-description' className='sr-only'>
        Choose between system preference, light mode, or dark mode
      </div>
    </div>
  )
}

function SidebarConfig() {
  const { defaultVariant, variant, setVariant } = useLayout()
  return (
    <div className='max-md:hidden'>
      <SectionTitle
        title='Sidebar'
        showReset={defaultVariant !== variant}
        onReset={() => setVariant(defaultVariant)}
      />
      <Radio
        value={variant}
        onValueChange={setVariant}
        className='grid w-full max-w-md grid-cols-3 gap-4'
        aria-label='Select sidebar style'
        aria-describedby='sidebar-description'
      >
        {[
          {
            value: 'inset',
            label: 'Inset',
            icon: IconSidebarInset,
          },
          {
            value: 'floating',
            label: 'Floating',
            icon: IconSidebarFloating,
          },
          {
            value: 'sidebar',
            label: 'Sidebar',
            icon: IconSidebarSidebar,
          },
        ].map((item) => (
          <RadioGroupItem key={item.value} item={item} />
        ))}
      </Radio>
      <div id='sidebar-description' className='sr-only'>
        Choose between inset, floating, or standard sidebar layout
      </div>
    </div>
  )
}

function LayoutConfig() {
  const { open, setOpen } = useSidebar()
  const { defaultCollapsible, collapsible, setCollapsible } = useLayout()

  const radioState = open ? 'default' : collapsible

  return (
    <div className='max-md:hidden'>
      <SectionTitle
        title='Layout'
        showReset={radioState !== 'default'}
        onReset={() => {
          setOpen(true)
          setCollapsible(defaultCollapsible)
        }}
      />
      <Radio
        value={radioState}
        onValueChange={(v) => {
          if (v === 'default') {
            setOpen(true)
            return
          }
          setOpen(false)
          setCollapsible(v as Collapsible)
        }}
        className='grid w-full max-w-md grid-cols-3 gap-4'
        aria-label='Select layout style'
        aria-describedby='layout-description'
      >
        {[
          {
            value: 'default',
            label: 'Default',
            icon: IconLayoutDefault,
          },
          {
            value: 'icon',
            label: 'Compact',
            icon: IconLayoutCompact,
          },
          {
            value: 'offcanvas',
            label: 'Full layout',
            icon: IconLayoutFull,
          },
        ].map((item) => (
          <RadioGroupItem key={item.value} item={item} />
        ))}
      </Radio>
      <div id='layout-description' className='sr-only'>
        Choose between default expanded, compact icon-only, or full layout mode
      </div>
    </div>
  )
}

function DirConfig() {
  const { defaultDir, dir, setDir } = useDirection()
  return (
    <div>
      <SectionTitle
        title='Direction'
        showReset={defaultDir !== dir}
        onReset={() => setDir(defaultDir)}
      />
      <Radio
        value={dir}
        onValueChange={setDir}
        className='grid w-full max-w-md grid-cols-3 gap-4'
        aria-label='Select site direction'
        aria-describedby='direction-description'
      >
        {[
          {
            value: 'ltr',
            label: 'Left to Right',
            icon: (props: SVGProps<SVGSVGElement>) => (
              <IconDir dir='ltr' {...props} />
            ),
          },
          {
            value: 'rtl',
            label: 'Right to Left',
            icon: (props: SVGProps<SVGSVGElement>) => (
              <IconDir dir='rtl' {...props} />
            ),
          },
        ].map((item) => (
          <RadioGroupItem key={item.value} item={item} />
        ))}
      </Radio>
      <div id='direction-description' className='sr-only'>
        Choose between left-to-right or right-to-left site direction
      </div>
    </div>
  )
}


================================================
FILE: src/components/confirm-dialog.tsx
================================================
import { cn } from '@/lib/utils'
import {
  AlertDialog,
  AlertDialogCancel,
  AlertDialogContent,
  AlertDialogDescription,
  AlertDialogFooter,
  AlertDialogHeader,
  AlertDialogTitle,
} from '@/components/ui/alert-dialog'
import { Button } from '@/components/ui/button'

type ConfirmDialogProps = {
  open: boolean
  onOpenChange: (open: boolean) => void
  title: React.ReactNode
  disabled?: boolean
  desc: React.JSX.Element | string
  cancelBtnText?: string
  confirmText?: React.ReactNode
  destructive?: boolean
  handleConfirm: () => void
  isLoading?: boolean
  className?: string
  children?: React.ReactNode
}

export function ConfirmDialog(props: ConfirmDialogProps) {
  const {
    title,
    desc,
    children,
    className,
    confirmText,
    cancelBtnText,
    destructive,
    isLoading,
    disabled = false,
    handleConfirm,
    ...actions
  } = props
  return (
    <AlertDialog {...actions}>
      <AlertDialogContent className={cn(className && className)}>
        <AlertDialogHeader className='text-start'>
          <AlertDialogTitle>{title}</AlertDialogTitle>
          <AlertDialogDescription asChild>
            <div>{desc}</div>
          </AlertDialogDescription>
        </AlertDialogHeader>
        {children}
        <AlertDialogFooter>
          <AlertDialogCancel disabled={isLoading}>
            {cancelBtnText ?? 'Cancel'}
          </AlertDialogCancel>
          <Button
            variant={destructive ? 'destructive' : 'default'}
            onClick={handleConfirm}
            disabled={disabled || isLoading}
          >
            {confirmText ?? 'Continue'}
          </Button>
        </AlertDialogFooter>
      </AlertDialogContent>
    </AlertDialog>
  )
}


================================================
FILE: src/components/data-table/bulk-actions.tsx
================================================
import { useState, useEffect, useRef } from 'react'
import { type Table } from '@tanstack/react-table'
import { X } from 'lucide-react'
import { cn } from '@/lib/utils'
import { Badge } from '@/components/ui/badge'
import { Button } from '@/components/ui/button'
import { Separator } from '@/components/ui/separator'
import {
  Tooltip,
  TooltipContent,
  TooltipTrigger,
} from '@/components/ui/tooltip'

type DataTableBulkActionsProps<TData> = {
  table: Table<TData>
  entityName: string
  children: React.ReactNode
}

/**
 * A modular toolbar for displaying bulk actions when table rows are selected.
 *
 * @template TData The type of data in the table.
 * @param {object} props The component props.
 * @param {Table<TData>} props.table The react-table instance.
 * @param {string} props.entityName The name of the entity being acted upon (e.g., "task", "user").
 * @param {React.ReactNode} props.children The action buttons to be rendered inside the toolbar.
 * @returns {React.ReactNode | null} The rendered component or null if no rows are selected.
 */
export function DataTableBulkActions<TData>({
  table,
  entityName,
  children,
}: DataTableBulkActionsProps<TData>): React.ReactNode | null {
  const selectedRows = table.getFilteredSelectedRowModel().rows
  const selectedCount = selectedRows.length
  const toolbarRef = useRef<HTMLDivElement>(null)
  const [announcement, setAnnouncement] = useState('')

  // Announce selection changes to screen readers
  useEffect(() => {
    if (selectedCount > 0) {
      const message = `${selectedCount} ${entityName}${selectedCount > 1 ? 's' : ''} selected. Bulk actions toolbar is available.`

      // Use queueMicrotask to defer state update and avoid cascading renders
      queueMicrotask(() => {
        setAnnouncement(message)
      })

      // Clear announcement after a delay
      const timer = setTimeout(() => setAnnouncement(''), 3000)
      return () => clearTimeout(timer)
    }
  }, [selectedCount, entityName])

  const handleClearSelection = () => {
    table.resetRowSelection()
  }

  const handleKeyDown = (event: React.KeyboardEvent) => {
    const buttons = toolbarRef.current?.querySelectorAll('button')
    if (!buttons) return

    const currentIndex = Array.from(buttons).findIndex(
      (button) => button === document.activeElement
    )

    switch (event.key) {
      case 'ArrowRight': {
        event.preventDefault()
        const nextIndex = (currentIndex + 1) % buttons.length
        buttons[nextIndex]?.focus()
        break
      }
      case 'ArrowLeft': {
        event.preventDefault()
        const prevIndex =
          currentIndex === 0 ? buttons.length - 1 : currentIndex - 1
        buttons[prevIndex]?.focus()
        break
      }
      case 'Home':
        event.preventDefault()
        buttons[0]?.focus()
        break
      case 'End':
        event.preventDefault()
        buttons[buttons.length - 1]?.focus()
        break
      case 'Escape': {
        // Check if the Escape key came from a dropdown trigger or content
        // We can't check dropdown state because Radix UI closes it before our handler runs
        const target = event.target as HTMLElement
        const activeElement = document.activeElement as HTMLElement

        // Check if the event target or currently focused element is a dropdown trigger
        const isFromDropdownTrigger =
          target?.getAttribute('data-slot') === 'dropdown-menu-trigger' ||
          activeElement?.getAttribute('data-slot') ===
            'dropdown-menu-trigger' ||
          target?.closest('[data-slot="dropdown-menu-trigger"]') ||
          activeElement?.closest('[data-slot="dropdown-menu-trigger"]')

        // Check if the focused element is inside dropdown content (which is portaled)
        const isFromDropdownContent =
          activeElement?.closest('[data-slot="dropdown-menu-content"]') ||
          target?.closest('[data-slot="dropdown-menu-content"]')

        if (isFromDropdownTrigger || isFromDropdownContent) {
          // Escape was meant for the dropdown - don't clear selection
          return
        }

        // Escape was meant for the toolbar - clear selection
        event.preventDefault()
        handleClearSelection()
        break
      }
    }
  }

  if (selectedCount === 0) {
    return null
  }

  return (
    <>
      {/* Live region for screen reader announcements */}
      <div
        aria-live='polite'
        aria-atomic='true'
        className='sr-only'
        role='status'
      >
        {announcement}
      </div>

      <div
        ref={toolbarRef}
        role='toolbar'
        aria-label={`Bulk actions for ${selectedCount} selected ${entityName}${selectedCount > 1 ? 's' : ''}`}
        aria-describedby='bulk-actions-description'
        tabIndex={-1}
        onKeyDown={handleKeyDown}
        className={cn(
          'fixed bottom-6 left-1/2 z-50 -translate-x-1/2 rounded-xl',
          'transition-all delay-100 duration-300 ease-out hover:scale-105',
          'focus-visible:ring-2 focus-visible:ring-ring/50 focus-visible:outline-none'
        )}
      >
        <div
          className={cn(
            'p-2 shadow-xl',
            'rounded-xl border',
            'bg-background/95 backdrop-blur-lg supports-backdrop-filter:bg-background/60',
            'flex items-center gap-x-2'
          )}
        >
          <Tooltip>
            <TooltipTrigger asChild>
              <Button
                variant='outline'
                size='icon'
                onClick={handleClearSelection}
                className='size-6 rounded-full'
                aria-label='Clear selection'
                title='Clear selection (Escape)'
              >
                <X />
                <span className='sr-only'>Clear selection</span>
              </Button>
            </TooltipTrigger>
            <TooltipContent>
              <p>Clear selection (Escape)</p>
            </TooltipContent>
          </Tooltip>

          <Separator
            className='h-5'
            orientation='vertical'
            aria-hidden='true'
          />

          <div
            className='flex items-center gap-x-1 text-sm'
            id='bulk-actions-description'
          >
            <Badge
              variant='default'
              className='min-w-8 rounded-lg'
              aria-label={`${selectedCount} selected`}
            >
              {selectedCount}
            </Badge>{' '}
            <span className='hidden sm:inline'>
              {entityName}
              {selectedCount > 1 ? 's' : ''}
            </span>{' '}
            selected
          </div>

          <Separator
            className='h-5'
            orientation='vertical'
            aria-hidden='true'
          />

          {children}
        </div>
      </div>
    </>
  )
}


================================================
FILE: src/components/data-table/column-header.tsx
================================================
import {
  ArrowDownIcon,
  ArrowUpIcon,
  CaretSortIcon,
  EyeNoneIcon,
} from '@radix-ui/react-icons'
import { type Column } from '@tanstack/react-table'
import { cn } from '@/lib/utils'
import { Button } from '@/components/ui/button'
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuSeparator,
  DropdownMenuTrigger,
} from '@/components/ui/dropdown-menu'

type DataTableColumnHeaderProps<TData, TValue> =
  React.HTMLAttributes<HTMLDivElement> & {
    column: Column<TData, TValue>
    title: string
  }

export function DataTableColumnHeader<TData, TValue>({
  column,
  title,
  className,
}: DataTableColumnHeaderProps<TData, TValue>) {
  if (!column.getCanSort()) {
    return <div className={cn(className)}>{title}</div>
  }

  return (
    <div className={cn('flex items-center space-x-2', className)}>
      <DropdownMenu>
        <DropdownMenuTrigger asChild>
          <Button
            variant='ghost'
            size='sm'
            className='h-8 data-[state=open]:bg-accent'
          >
            <span>{title}</span>
            {column.getIsSorted() === 'desc' ? (
              <ArrowDownIcon className='ms-2 h-4 w-4' />
            ) : column.getIsSorted() === 'asc' ? (
              <ArrowUpIcon className='ms-2 h-4 w-4' />
            ) : (
              <CaretSortIcon className='ms-2 h-4 w-4' />
            )}
          </Button>
        </DropdownMenuTrigger>
        <DropdownMenuContent align='start'>
          <DropdownMenuItem onClick={() => column.toggleSorting(false)}>
            <ArrowUpIcon className='size-3.5 text-muted-foreground/70' />
            Asc
          </DropdownMenuItem>
          <DropdownMenuItem onClick={() => column.toggleSorting(true)}>
            <ArrowDownIcon className='size-3.5 text-muted-foreground/70' />
            Desc
          </DropdownMenuItem>
          {column.getCanHide() && (
            <>
              <DropdownMenuSeparator />
              <DropdownMenuItem onClick={() => column.toggleVisibility(false)}>
                <EyeNoneIcon className='size-3.5 text-muted-foreground/70' />
                Hide
              </DropdownMenuItem>
            </>
          )}
        </DropdownMenuContent>
      </DropdownMenu>
    </div>
  )
}


================================================
FILE: src/components/data-table/faceted-filter.tsx
================================================
import * as React from 'react'
import { CheckIcon, PlusCircledIcon } from '@radix-ui/react-icons'
import { type Column } from '@tanstack/react-table'
import { cn } from '@/lib/utils'
import { Badge } from '@/components/ui/badge'
import { Button } from '@/components/ui/button'
import {
  Command,
  CommandEmpty,
  CommandGroup,
  CommandInput,
  CommandItem,
  CommandList,
  CommandSeparator,
} from '@/components/ui/command'
import {
  Popover,
  PopoverContent,
  PopoverTrigger,
} from '@/components/ui/popover'
import { Separator } from '@/components/ui/separator'

type DataTableFacetedFilterProps<TData, TValue> = {
  column?: Column<TData, TValue>
  title?: string
  options: {
    label: string
    value: string
    icon?: React.ComponentType<{ className?: string }>
  }[]
}

export function DataTableFacetedFilter<TData, TValue>({
  column,
  title,
  options,
}: DataTableFacetedFilterProps<TData, TValue>) {
  const facets = column?.getFacetedUniqueValues()
  const selectedValues = new Set(column?.getFilterValue() as string[])

  return (
    <Popover>
      <PopoverTrigger asChild>
        <Button variant='outline' size='sm' className='h-8 border-dashed'>
          <PlusCircledIcon className='size-4' />
          {title}
          {selectedValues?.size > 0 && (
            <>
              <Separator orientation='vertical' className='mx-2 h-4' />
              <Badge
                variant='secondary'
                className='rounded-sm px-1 font-normal lg:hidden'
              >
                {selectedValues.size}
              </Badge>
              <div className='hidden space-x-1 lg:flex'>
                {selectedValues.size > 2 ? (
                  <Badge
                    variant='secondary'
                    className='rounded-sm px-1 font-normal'
                  >
                    {selectedValues.size} selected
                  </Badge>
                ) : (
                  options
                    .filter((option) => selectedValues.has(option.value))
                    .map((option) => (
                      <Badge
                        variant='secondary'
                        key={option.value}
                        className='rounded-sm px-1 font-normal'
                      >
                        {option.label}
                      </Badge>
                    ))
                )}
              </div>
            </>
          )}
        </Button>
      </PopoverTrigger>
      <PopoverContent className='w-[200px] p-0' align='start'>
        <Command>
          <CommandInput placeholder={title} />
          <CommandList>
            <CommandEmpty>No results found.</CommandEmpty>
            <CommandGroup>
              {options.map((option) => {
                const isSelected = selectedValues.has(option.value)
                return (
                  <CommandItem
                    key={option.value}
                    onSelect={() => {
                      if (isSelected) {
                        selectedValues.delete(option.value)
                      } else {
                        selectedValues.add(option.value)
                      }
                      const filterValues = Array.from(selectedValues)
                      column?.setFilterValue(
                        filterValues.length ? filterValues : undefined
                      )
                    }}
                  >
                    <div
                      className={cn(
                        'flex size-4 items-center justify-center rounded-sm border border-primary',
                        isSelected
                          ? 'bg-primary text-primary-foreground'
                          : 'opacity-50 [&_svg]:invisible'
                      )}
                    >
                      <CheckIcon className={cn('h-4 w-4 text-background')} />
                    </div>
                    {option.icon && (
                      <option.icon className='size-4 text-muted-foreground' />
                    )}
                    <span>{option.label}</span>
                    {facets?.get(option.value) && (
                      <span className='ms-auto flex h-4 w-4 items-center justify-center font-mono text-xs'>
                        {facets.get(option.value)}
                      </span>
                    )}
                  </CommandItem>
                )
              })}
            </CommandGroup>
            {selectedValues.size > 0 && (
              <>
                <CommandSeparator />
                <CommandGroup>
                  <CommandItem
                    onSelect={() => column?.setFilterValue(undefined)}
                    className='justify-center text-center'
                  >
                    Clear filters
                  </CommandItem>
                </CommandGroup>
              </>
            )}
          </CommandList>
        </Command>
      </PopoverContent>
    </Popover>
  )
}


================================================
FILE: src/components/data-table/index.ts
================================================
export { DataTablePagination } from './pagination'
export { DataTableColumnHeader } from './column-header'
export { DataTableFacetedFilter } from './faceted-filter'
export { DataTableViewOptions } from './view-options'
export { DataTableToolbar } from './toolbar'
export { DataTableBulkActions } from './bulk-actions'


================================================
FILE: src/components/data-table/pagination.tsx
================================================
import {
  ChevronLeftIcon,
  ChevronRightIcon,
  DoubleArrowLeftIcon,
  DoubleArrowRightIcon,
} from '@radix-ui/react-icons'
import { type Table } from '@tanstack/react-table'
import { cn, getPageNumbers } from '@/lib/utils'
import { Button } from '@/components/ui/button'
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from '@/components/ui/select'

type DataTablePaginationProps<TData> = {
  table: Table<TData>
  className?: string
}

export function DataTablePagination<TData>({
  table,
  className,
}: DataTablePaginationProps<TData>) {
  const currentPage = table.getState().pagination.pageIndex + 1
  const totalPages = table.getPageCount()
  const pageNumbers = getPageNumbers(currentPage, totalPages)

  return (
    <div
      className={cn(
        'flex items-center justify-between overflow-clip px-2',
        '@max-2xl/content:flex-col-reverse @max-2xl/content:gap-4',
        className
      )}
      style={{ overflowClipMargin: 1 }}
    >
      <div className='flex w-full items-center justify-between'>
        <div className='flex w-[100px] items-center justify-center text-sm font-medium @2xl/content:hidden'>
          Page {currentPage} of {totalPages}
        </div>
        <div className='flex items-center gap-2 @max-2xl/content:flex-row-reverse'>
          <Select
            value={`${table.getState().pagination.pageSize}`}
            onValueChange={(value) => {
              table.setPageSize(Number(value))
            }}
          >
            <SelectTrigger className='h-8 w-[70px]'>
              <SelectValue placeholder={table.getState().pagination.pageSize} />
            </SelectTrigger>
            <SelectContent side='top'>
              {[10, 20, 30, 40, 50].map((pageSize) => (
                <SelectItem key={pageSize} value={`${pageSize}`}>
                  {pageSize}
                </SelectItem>
              ))}
            </SelectContent>
          </Select>
          <p className='hidden text-sm font-medium sm:block'>Rows per page</p>
        </div>
      </div>

      <div className='flex items-center sm:space-x-6 lg:space-x-8'>
        <div className='flex w-[100px] items-center justify-center text-sm font-medium @max-3xl/content:hidden'>
          Page {currentPage} of {totalPages}
        </div>
        <div className='flex items-center space-x-2'>
          <Button
            variant='outline'
            className='size-8 p-0 @max-md/content:hidden'
            onClick={() => table.setPageIndex(0)}
            disabled={!table.getCanPreviousPage()}
          >
            <span className='sr-only'>Go to first page</span>
            <DoubleArrowLeftIcon className='h-4 w-4' />
          </Button>
          <Button
            variant='outline'
            className='size-8 p-0'
            onClick={() => table.previousPage()}
            disabled={!table.getCanPreviousPage()}
          >
            <span className='sr-only'>Go to previous page</span>
            <ChevronLeftIcon className='h-4 w-4' />
          </Button>

          {/* Page number buttons */}
          {pageNumbers.map((pageNumber, index) => (
            <div key={`${pageNumber}-${index}`} className='flex items-center'>
              {pageNumber === '...' ? (
                <span className='px-1 text-sm text-muted-foreground'>...</span>
              ) : (
                <Button
                  variant={currentPage === pageNumber ? 'default' : 'outline'}
                  className='h-8 min-w-8 px-2'
                  onClick={() => table.setPageIndex((pageNumber as number) - 1)}
                >
                  <span className='sr-only'>Go to page {pageNumber}</span>
                  {pageNumber}
                </Button>
              )}
            </div>
          ))}

          <Button
            variant='outline'
            className='size-8 p-0'
            onClick={() => table.nextPage()}
            disabled={!table.getCanNextPage()}
          >
            <span className='sr-only'>Go to next page</span>
            <ChevronRightIcon className='h-4 w-4' />
          </Button>
          <Button
            variant='outline'
            className='size-8 p-0 @max-md/content:hidden'
            onClick={() => table.setPageIndex(table.getPageCount() - 1)}
            disabled={!table.getCanNextPage()}
          >
            <span className='sr-only'>Go to last page</span>
            <DoubleArrowRightIcon className='h-4 w-4' />
          </Button>
        </div>
      </div>
    </div>
  )
}


================================================
FILE: src/components/data-table/toolbar.tsx
================================================
import { Cross2Icon } from '@radix-ui/react-icons'
import { type Table } from '@tanstack/react-table'
import { Button } from '@/components/ui/button'
import { Input } from '@/components/ui/input'
import { DataTableFacetedFilter } from './faceted-filter'
import { DataTableViewOptions } from './view-options'

type DataTableToolbarProps<TData> = {
  table: Table<TData>
  searchPlaceholder?: string
  searchKey?: string
  filters?: {
    columnId: string
    title: string
    options: {
      label: string
      value: string
      icon?: React.ComponentType<{ className?: string }>
    }[]
  }[]
}

export function DataTableToolbar<TData>({
  table,
  searchPlaceholder = 'Filter...',
  searchKey,
  filters = [],
}: DataTableToolbarProps<TData>) {
  const isFiltered =
    table.getState().columnFilters.length > 0 || table.getState().globalFilter

  return (
    <div className='flex items-center justify-between'>
      <div className='flex flex-1 flex-col-reverse items-start gap-y-2 sm:flex-row sm:items-center sm:space-x-2'>
        {searchKey ? (
          <Input
            placeholder={searchPlaceholder}
            value={
              (table.getColumn(searchKey)?.getFilterValue() as string) ?? ''
            }
            onChange={(event) =>
              table.getColumn(searchKey)?.setFilterValue(event.target.value)
            }
            className='h-8 w-[150px] lg:w-[250px]'
          />
        ) : (
          <Input
            placeholder={searchPlaceholder}
            value={table.getState().globalFilter ?? ''}
            onChange={(event) => table.setGlobalFilter(event.target.value)}
            className='h-8 w-[150px] lg:w-[250px]'
          />
        )}
        <div className='flex gap-x-2'>
          {filters.map((filter) => {
            const column = table.getColumn(filter.columnId)
            if (!column) return null
            return (
              <DataTableFacetedFilter
                key={filter.columnId}
                column={column}
                title={filter.title}
                options={filter.options}
              />
            )
          })}
        </div>
        {isFiltered && (
          <Button
            variant='ghost'
            onClick={() => {
              table.resetColumnFilters()
              table.setGlobalFilter('')
            }}
            className='h-8 px-2 lg:px-3'
          >
            Reset
            <Cross2Icon className='ms-2 h-4 w-4' />
          </Button>
        )}
      </div>
      <DataTableViewOptions table={table} />
    </div>
  )
}


================================================
FILE: src/components/data-table/view-options.tsx
================================================
import { DropdownMenuTrigger } from '@radix-ui/react-dropdown-menu'
import { MixerHorizontalIcon } from '@radix-ui/react-icons'
import { type Table } from '@tanstack/react-table'
import { Button } from '@/components/ui/button'
import {
  DropdownMenu,
  DropdownMenuCheckboxItem,
  DropdownMenuContent,
  DropdownMenuLabel,
  DropdownMenuSeparator,
} from '@/components/ui/dropdown-menu'

type DataTableViewOptionsProps<TData> = {
  table: Table<TData>
}

export function DataTableViewOptions<TData>({
  table,
}: DataTableViewOptionsProps<TData>) {
  return (
    <DropdownMenu modal={false}>
      <DropdownMenuTrigger asChild>
        <Button
          variant='outline'
          size='sm'
          className='ms-auto hidden h-8 lg:flex'
        >
          <MixerHorizontalIcon className='size-4' />
          View
        </Button>
      </DropdownMenuTrigger>
      <DropdownMenuContent align='end' className='w-[150px]'>
        <DropdownMenuLabel>Toggle columns</DropdownMenuLabel>
        <DropdownMenuSeparator />
        {table
          .getAllColumns()
          .filter(
            (column) =>
              typeof column.accessorFn !== 'undefined' && column.getCanHide()
          )
          .map((column) => {
            return (
              <DropdownMenuCheckboxItem
                key={column.id}
                className='capitalize'
                checked={column.getIsVisible()}
                onCheckedChange={(value) => column.toggleVisibility(!!value)}
              >
                {column.id}
              </DropdownMenuCheckboxItem>
            )
          })}
      </DropdownMenuContent>
    </DropdownMenu>
  )
}


================================================
FILE: src/components/date-picker.tsx
================================================
import { format } from 'date-fns'
import { Calendar as CalendarIcon } from 'lucide-react'
import { Button } from '@/components/ui/button'
import { Calendar } from '@/components/ui/calendar'
import {
  Popover,
  PopoverContent,
  PopoverTrigger,
} from '@/components/ui/popover'

type DatePickerProps = {
  selected: Date | undefined
  onSelect: (date: Date | undefined) => void
  placeholder?: string
}

export function DatePicker({
  selected,
  onSelect,
  placeholder = 'Pick a date',
}: DatePickerProps) {
  return (
    <Popover>
      <PopoverTrigger asChild>
        <Button
          variant='outline'
          data-empty={!selected}
          className='w-[240px] justify-start text-start font-normal data-[empty=true]:text-muted-foreground'
        >
          {selected ? (
            format(selected, 'MMM d, yyyy')
          ) : (
            <span>{placeholder}</span>
          )}
          <CalendarIcon className='ms-auto h-4 w-4 opacity-50' />
        </Button>
      </PopoverTrigger>
      <PopoverContent className='w-auto p-0'>
        <Calendar
          mode='single'
          captionLayout='dropdown'
          selected={selected}
          onSelect={onSelect}
          disabled={(date: Date) =>
            date > new Date() || date < new Date('1900-01-01')
          }
        />
      </PopoverContent>
    </Popover>
  )
}


================================================
FILE: src/components/layout/app-sidebar.tsx
================================================
import { useLayout } from '@/context/layout-provider'
import {
  Sidebar,
  SidebarContent,
  SidebarFooter,
  SidebarHeader,
  SidebarRail,
} from '@/components/ui/sidebar'
// import { AppTitle } from './app-title'
import { sidebarData } from './data/sidebar-data'
import { NavGroup } from './nav-group'
import { NavUser } from './nav-user'
import { TeamSwitcher } from './team-switcher'

export function AppSidebar() {
  const { collapsible, variant } = useLayout()
  return (
    <Sidebar collapsible={collapsible} variant={variant}>
      <SidebarHeader>
        <TeamSwitcher teams={sidebarData.teams} />

        {/* Replace <TeamSwitch /> with the following <AppTitle />
         /* if you want to use the normal app title instead of TeamSwitch dropdown */}
        {/* <AppTitle /> */}
      </SidebarHeader>
      <SidebarContent>
        {sidebarData.navGroups.map((props) => (
          <NavGroup key={props.title} {...props} />
        ))}
      </SidebarContent>
      <SidebarFooter>
        <NavUser user={sidebarData.user} />
      </SidebarFooter>
      <SidebarRail />
    </Sidebar>
  )
}


================================================
FILE: src/components/layout/app-title.tsx
================================================
import { Link } from '@tanstack/react-router'
import { Menu, X } from 'lucide-react'
import { cn } from '@/lib/utils'
import {
  SidebarMenu,
  SidebarMenuButton,
  SidebarMenuItem,
  useSidebar,
} from '@/components/ui/sidebar'
import { Button } from '../ui/button'

export function AppTitle() {
  const { setOpenMobile } = useSidebar()
  return (
    <SidebarMenu>
      <SidebarMenuItem>
        <SidebarMenuButton
          size='lg'
          className='gap-0 py-0 hover:bg-transparent active:bg-transparent'
          asChild
        >
          <div>
            <Link
              to='/'
              onClick={() => setOpenMobile(false)}
              className='grid flex-1 text-start text-sm leading-tight'
            >
              <span className='truncate font-bold'>Shadcn-Admin</span>
              <span className='truncate text-xs'>Vite + ShadcnUI</span>
            </Link>
            <ToggleSidebar />
          </div>
        </SidebarMenuButton>
      </SidebarMenuItem>
    </SidebarMenu>
  )
}

function ToggleSidebar({
  className,
  onClick,
  ...props
}: React.ComponentProps<typeof Button>) {
  const { toggleSidebar } = useSidebar()

  return (
    <Button
      data-sidebar='trigger'
      data-slot='sidebar-trigger'
      variant='ghost'
      size='icon'
      className={cn('aspect-square size-8 max-md:scale-125', className)}
      onClick={(event) => {
        onClick?.(event)
        toggleSidebar()
      }}
      {...props}
    >
      <X className='md:hidden' />
      <Menu className='max-md:hidden' />
      <span className='sr-only'>Toggle Sidebar</span>
    </Button>
  )
}


================================================
FILE: src/components/layout/authenticated-layout.tsx
================================================
import { Outlet } from '@tanstack/react-router'
import { getCookie } from '@/lib/cookies'
import { cn } from '@/lib/utils'
import { LayoutProvider } from '@/context/layout-provider'
import { SearchProvider } from '@/context/search-provider'
import { SidebarInset, SidebarProvider } from '@/components/ui/sidebar'
import { AppSidebar } from '@/components/layout/app-sidebar'
import { SkipToMain } from '@/components/skip-to-main'

type AuthenticatedLayoutProps = {
  children?: React.ReactNode
}

export function AuthenticatedLayout({ children }: AuthenticatedLayoutProps) {
  const defaultOpen = getCookie('sidebar_state') !== 'false'
  return (
    <SearchProvider>
      <LayoutProvider>
        <SidebarProvider defaultOpen={defaultOpen}>
          <SkipToMain />
          <AppSidebar />
          <SidebarInset
            className={cn(
              // Set content container, so we can use container queries
              '@container/content',

              // If layout is fixed, set the height
              // to 100svh to prevent overflow
              'has-data-[layout=fixed]:h-svh',

              // If layout is fixed and sidebar is inset,
              // set the height to 100svh - spacing (total margins) to prevent overflow
              'peer-data-[variant=inset]:has-data-[layout=fixed]:h-[calc(100svh-(var(--spacing)*4))]'
            )}
          >
            {children ?? <Outlet />}
          </SidebarInset>
        </SidebarProvider>
      </LayoutProvider>
    </SearchProvider>
  )
}


================================================
FILE: src/components/layout/data/sidebar-data.ts
================================================
import {
  Construction,
  LayoutDashboard,
  Monitor,
  Bug,
  ListTodo,
  FileX,
  HelpCircle,
  Lock,
  Bell,
  Package,
  Palette,
  ServerOff,
  Settings,
  Wrench,
  UserCog,
  UserX,
  Users,
  MessagesSquare,
  ShieldCheck,
  AudioWaveform,
  Command,
  GalleryVerticalEnd,
} from 'lucide-react'
import { ClerkLogo } from '@/assets/clerk-logo'
import { type SidebarData } from '../types'

export const sidebarData: SidebarData = {
  user: {
    name: 'satnaing',
    email: 'satnaingdev@gmail.com',
    avatar: '/avatars/shadcn.jpg',
  },
  teams: [
    {
      name: 'Shadcn Admin',
      logo: Command,
      plan: 'Vite + ShadcnUI',
    },
    {
      name: 'Acme Inc',
      logo: GalleryVerticalEnd,
      plan: 'Enterprise',
    },
    {
      name: 'Acme Corp.',
      logo: AudioWaveform,
      plan: 'Startup',
    },
  ],
  navGroups: [
    {
      title: 'General',
      items: [
        {
          title: 'Dashboard',
          url: '/',
          icon: LayoutDashboard,
        },
        {
          title: 'Tasks',
          url: '/tasks',
          icon: ListTodo,
        },
        {
          title: 'Apps',
          url: '/apps',
          icon: Package,
        },
        {
          title: 'Chats',
          url: '/chats',
          badge: '3',
          icon: MessagesSquare,
        },
        {
          title: 'Users',
          url: '/users',
          icon: Users,
        },
        {
          title: 'Secured by Clerk',
          icon: ClerkLogo,
          items: [
            {
              title: 'Sign In',
              url: '/clerk/sign-in',
            },
            {
              title: 'Sign Up',
              url: '/clerk/sign-up',
            },
            {
              title: 'User Management',
              url: '/clerk/user-management',
            },
          ],
        },
      ],
    },
    {
      title: 'Pages',
      items: [
        {
          title: 'Auth',
          icon: ShieldCheck,
          items: [
            {
              title: 'Sign In',
              url: '/sign-in',
            },
            {
              title: 'Sign In (2 Col)',
              url: '/sign-in-2',
            },
            {
              title: 'Sign Up',
              url: '/sign-up',
            },
            {
              title: 'Forgot Password',
              url: '/forgot-password',
            },
            {
              title: 'OTP',
              url: '/otp',
            },
          ],
        },
        {
          title: 'Errors',
          icon: Bug,
          items: [
            {
              title: 'Unauthorized',
              url: '/errors/unauthorized',
              icon: Lock,
            },
            {
              title: 'Forbidden',
              url: '/errors/forbidden',
              icon: UserX,
            },
            {
              title: 'Not Found',
              url: '/errors/not-found',
              icon: FileX,
            },
            {
              title: 'Internal Server Error',
              url: '/errors/internal-server-error',
              icon: ServerOff,
            },
            {
              title: 'Maintenance Error',
              url: '/errors/maintenance-error',
              icon: Construction,
            },
          ],
        },
      ],
    },
    {
      title: 'Other',
      items: [
        {
          title: 'Settings',
          icon: Settings,
          items: [
            {
              title: 'Profile',
              url: '/settings',
              icon: UserCog,
            },
            {
              title: 'Account',
              url: '/settings/account',
              icon: Wrench,
            },
            {
              title: 'Appearance',
              url: '/settings/appearance',
              icon: Palette,
            },
            {
              title: 'Notifications',
              url: '/settings/notifications',
              icon: Bell,
            },
            {
              title: 'Display',
              url: '/settings/display',
              icon: Monitor,
            },
          ],
        },
        {
          title: 'Help Center',
          url: '/help-center',
          icon: HelpCircle,
        },
      ],
    },
  ],
}


================================================
FILE: src/components/layout/header.tsx
================================================
import { useEffect, useState } from 'react'
import { cn } from '@/lib/utils'
import { Separator } from '@/components/ui/separator'
import { SidebarTrigger } from '@/components/ui/sidebar'

type HeaderProps = React.HTMLAttributes<HTMLElement> & {
  fixed?: boolean
  ref?: React.Ref<HTMLElement>
}

export function Header({ className, fixed, children, ...props }: HeaderProps) {
  const [offset, setOffset] = useState(0)

  useEffect(() => {
    const onScroll = () => {
      setOffset(document.body.scrollTop || document.documentElement.scrollTop)
    }

    // Add scroll listener to the body
    document.addEventListener('scroll', onScroll, { passive: true })

    // Clean up the event listener on unmount
    return () => document.removeEventListener('scroll', onScroll)
  }, [])

  return (
    <header
      className={cn(
        'z-50 h-16',
        fixed && 'header-fixed peer/header sticky top-0 w-[inherit]',
        offset > 10 && fixed ? 'shadow' : 'shadow-none',
        className
      )}
      {...props}
    >
      <div
        className={cn(
          'relative flex h-full items-center gap-3 p-4 sm:gap-4',
          offset > 10 &&
            fixed &&
            'after:absolute after:inset-0 after:-z-10 after:bg-background/20 after:backdrop-blur-lg'
        )}
      >
        <SidebarTrigger variant='outline' className='max-md:scale-125' />
        <Separator orientation='vertical' className='h-6' />
        {children}
      </div>
    </header>
  )
}


================================================
FILE: src/components/layout/main.tsx
================================================
import { cn } from '@/lib/utils'

type MainProps = React.HTMLAttributes<HTMLElement> & {
  fixed?: boolean
  fluid?: boolean
  ref?: React.Ref<HTMLElement>
}

export function Main({ fixed, className, fluid, ...props }: MainProps) {
  return (
    <main
      data-layout={fixed ? 'fixed' : 'auto'}
      className={cn(
        'px-4 py-6',

        // If layout is fixed, make the main container flex and grow
        fixed && 'flex grow flex-col overflow-hidden',

        // If layout is not fluid, set the max-width
        !fluid &&
          '@7xl/content:mx-auto @7xl/content:w-full @7xl/content:max-w-7xl',
        className
      )}
      {...props}
    />
  )
}


================================================
FILE: src/components/layout/nav-group.tsx
================================================
import { type ReactNode } from 'react'
import { Link, useLocation } from '@tanstack/react-router'
import { ChevronRight } from 'lucide-react'
import {
  Collapsible,
  CollapsibleContent,
  CollapsibleTrigger,
} from '@/components/ui/collapsible'
import {
  SidebarGroup,
  SidebarGroupLabel,
  SidebarMenu,
  SidebarMenuButton,
  SidebarMenuItem,
  SidebarMenuSub,
  SidebarMenuSubButton,
  SidebarMenuSubItem,
  useSidebar,
} from '@/components/ui/sidebar'
import { Badge } from '../ui/badge'
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuLabel,
  DropdownMenuSeparator,
  DropdownMenuTrigger,
} from '../ui/dropdown-menu'
import {
  type NavCollapsible,
  type NavItem,
  type NavLink,
  type NavGroup as NavGroupProps,
} from './types'

export function NavGroup({ title, items }: NavGroupProps) {
  const { state, isMobile } = useSidebar()
  const href = useLocation({ select: (location) => location.href })
  return (
    <SidebarGroup>
      <SidebarGroupLabel>{title}</SidebarGroupLabel>
      <SidebarMenu>
        {items.map((item) => {
          const key = `${item.title}-${item.url}`

          if (!item.items)
            return <SidebarMenuLink key={key} item={item} href={href} />

          if (state === 'collapsed' && !isMobile)
            return (
              <SidebarMenuCollapsedDropdown key={key} item={item} href={href} />
            )

          return <SidebarMenuCollapsible key={key} item={item} href={href} />
        })}
      </SidebarMenu>
    </SidebarGroup>
  )
}

function NavBadge({ children }: { children: ReactNode }) {
  return <Badge className='rounded-full px-1 py-0 text-xs'>{children}</Badge>
}

function SidebarMenuLink({ item, href }: { item: NavLink; href: string }) {
  const { setOpenMobile } = useSidebar()
  return (
    <SidebarMenuItem>
      <SidebarMenuButton
        asChild
        isActive={checkIsActive(href, item)}
        tooltip={item.title}
      >
        <Link to={item.url} onClick={() => setOpenMobile(false)}>
          {item.icon && <item.icon />}
          <span>{item.title}</span>
          {item.badge && <NavBadge>{item.badge}</NavBadge>}
        </Link>
      </SidebarMenuButton>
    </SidebarMenuItem>
  )
}

function SidebarMenuCollapsible({
  item,
  href,
}: {
  item: NavCollapsible
  href: string
}) {
  const { setOpenMobile } = useSidebar()
  return (
    <Collapsible
      asChild
      defaultOpen={checkIsActive(href, item, true)}
      className='group/collapsible'
    >
      <SidebarMenuItem>
        <CollapsibleTrigger asChild>
          <SidebarMenuButton tooltip={item.title}>
            {item.icon && <item.icon />}
            <span>{item.title}</span>
            {item.badge && <NavBadge>{item.badge}</NavBadge>}
            <ChevronRight className='ms-auto transition-transform duration-200 group-data-[state=open]/collapsible:rotate-90 rtl:rotate-180' />
          </SidebarMenuButton>
        </CollapsibleTrigger>
        <CollapsibleContent className='CollapsibleContent'>
          <SidebarMenuSub>
            {item.items.map((subItem) => (
              <SidebarMenuSubItem key={subItem.title}>
                <SidebarMenuSubButton
                  asChild
                  isActive={checkIsActive(href, subItem)}
                >
                  <Link to={subItem.url} onClick={() => setOpenMobile(false)}>
                    {subItem.icon && <subItem.icon />}
                    <span>{subItem.title}</span>
                    {subItem.badge && <NavBadge>{subItem.badge}</NavBadge>}
                  </Link>
                </SidebarMenuSubButton>
              </SidebarMenuSubItem>
            ))}
          </SidebarMenuSub>
        </CollapsibleContent>
      </SidebarMenuItem>
    </Collapsible>
  )
}

function SidebarMenuCollapsedDropdown({
  item,
  href,
}: {
  item: NavCollapsible
  href: string
}) {
  return (
    <SidebarMenuItem>
      <DropdownMenu>
        <DropdownMenuTrigger asChild>
          <SidebarMenuButton
            tooltip={item.title}
            isActive={checkIsActive(href, item)}
          >
            {item.icon && <item.icon />}
            <span>{item.title}</span>
            {item.badge && <NavBadge>{item.badge}</NavBadge>}
            <ChevronRight className='ms-auto transition-transform duration-200 group-data-[state=open]/collapsible:rotate-90' />
          </SidebarMenuButton>
        </DropdownMenuTrigger>
        <DropdownMenuContent side='right' align='start' sideOffset={4}>
          <DropdownMenuLabel>
            {item.title} {item.badge ? `(${item.badge})` : ''}
          </DropdownMenuLabel>
          <DropdownMenuSeparator />
          {item.items.map((sub) => (
            <DropdownMenuItem key={`${sub.title}-${sub.url}`} asChild>
              <Link
                to={sub.url}
                className={`${checkIsActive(href, sub) ? 'bg-secondary' : ''}`}
              >
                {sub.icon && <sub.icon />}
                <span className='max-w-52 text-wrap'>{sub.title}</span>
                {sub.badge && (
                  <span className='ms-auto text-xs'>{sub.badge}</span>
                )}
              </Link>
            </DropdownMenuItem>
          ))}
        </DropdownMenuContent>
      </DropdownMenu>
    </SidebarMenuItem>
  )
}

function checkIsActive(href: string, item: NavItem, mainNav = false) {
  return (
    href === item.url || // /endpint?search=param
    href.split('?')[0] === item.url || // endpoint
    !!item?.items?.filter((i) => i.url === href).length || // if child nav is active
    (mainNav &&
      href.split('/')[1] !== '' &&
      href.split('/')[1] === item?.url?.split('/')[1])
  )
}


================================================
FILE: src/components/layout/nav-user.tsx
================================================
import { Link } from '@tanstack/react-router'
import {
  BadgeCheck,
  Bell,
  ChevronsUpDown,
  CreditCard,
  LogOut,
  Sparkles,
} from 'lucide-react'
import useDialogState from '@/hooks/use-dialog-state'
import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar'
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuGroup,
  DropdownMenuItem,
  DropdownMenuLabel,
  DropdownMenuSeparator,
  DropdownMenuTrigger,
} from '@/components/ui/dropdown-menu'
import {
  SidebarMenu,
  SidebarMenuButton,
  SidebarMenuItem,
  useSidebar,
} from '@/components/ui/sidebar'
import { SignOutDialog } from '@/components/sign-out-dialog'

type NavUserProps = {
  user: {
    name: string
    email: string
    avatar: string
  }
}

export function NavUser({ user }: NavUserProps) {
  const { isMobile } = useSidebar()
  const [open, setOpen] = useDialogState()

  return (
    <>
      <SidebarMenu>
        <SidebarMenuItem>
          <DropdownMenu>
            <DropdownMenuTrigger asChild>
              <SidebarMenuButton
                size='lg'
                className='data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground'
              >
                <Avatar className='h-8 w-8 rounded-lg'>
                  <AvatarImage src={user.avatar} alt={user.name} />
                  <AvatarFallback className='rounded-lg'>SN</AvatarFallback>
                </Avatar>
                <div className='grid flex-1 text-start text-sm leading-tight'>
                  <span className='truncate font-semibold'>{user.name}</span>
                  <span className='truncate text-xs'>{user.email}</span>
                </div>
                <ChevronsUpDown className='ms-auto size-4' />
              </SidebarMenuButton>
            </DropdownMenuTrigger>
            <DropdownMenuContent
              className='w-(--radix-dropdown-menu-trigger-width) min-w-56 rounded-lg'
              side={isMobile ? 'bottom' : 'right'}
              align='end'
              sideOffset={4}
            >
              <DropdownMenuLabel className='p-0 font-normal'>
                <div className='flex items-center gap-2 px-1 py-1.5 text-start text-sm'>
                  <Avatar className='h-8 w-8 rounded-lg'>
                    <AvatarImage src={user.avatar} alt={user.name} />
                    <AvatarFallback className='rounded-lg'>SN</AvatarFallback>
                  </Avatar>
                  <div className='grid flex-1 text-start text-sm leading-tight'>
                    <span className='truncate font-semibold'>{user.name}</span>
                    <span className='truncate text-xs'>{user.email}</span>
                  </div>
                </div>
              </DropdownMenuLabel>
              <DropdownMenuSeparator />
              <DropdownMenuGroup>
                <DropdownMenuItem>
                  <Sparkles />
                  Upgrade to Pro
                </DropdownMenuItem>
              </DropdownMenuGroup>
              <DropdownMenuSeparator />
              <DropdownMenuGroup>
                <DropdownMenuItem asChild>
                  <Link to='/settings/account'>
                    <BadgeCheck />
                    Account
                  </Link>
                </DropdownMenuItem>
                <DropdownMenuItem asChild>
                  <Link to='/settings'>
                    <CreditCard />
                    Billing
                  </Link>
                </DropdownMenuItem>
                <DropdownMenuItem asChild>
                  <Link to='/settings/notifications'>
                    <Bell />
                    Notifications
                  </Link>
                </DropdownMenuItem>
              </DropdownMenuGroup>
              <DropdownMenuSeparator />
              <DropdownMenuItem
                variant='destructive'
                onClick={() => setOpen(true)}
              >
                <LogOut />
                Sign out
              </DropdownMenuItem>
            </DropdownMenuContent>
          </DropdownMenu>
        </SidebarMenuItem>
      </SidebarMenu>

      <SignOutDialog open={!!open} onOpenChange={setOpen} />
    </>
  )
}


================================================
FILE: src/components/layout/team-switcher.tsx
================================================
import * as React from 'react'
import { ChevronsUpDown, Plus } from 'lucide-react'
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuLabel,
  DropdownMenuSeparator,
  DropdownMenuShortcut,
  DropdownMenuTrigger,
} from '@/components/ui/dropdown-menu'
import {
  SidebarMenu,
  SidebarMenuButton,
  SidebarMenuItem,
  useSidebar,
} from '@/components/ui/sidebar'

type TeamSwitcherProps = {
  teams: {
    name: string
    logo: React.ElementType
    plan: string
  }[]
}

export function TeamSwitcher({ teams }: TeamSwitcherProps) {
  const { isMobile } = useSidebar()
  const [activeTeam, setActiveTeam] = React.useState(teams[0])

  return (
    <SidebarMenu>
      <SidebarMenuItem>
        <DropdownMenu>
          <DropdownMenuTrigger asChild>
            <SidebarMenuButton
              size='lg'
              className='data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground'
            >
              <div className='flex aspect-square size-8 items-center justify-center rounded-lg bg-sidebar-primary text-sidebar-primary-foreground'>
                <activeTeam.logo className='size-4' />
              </div>
              <div className='grid flex-1 text-start text-sm leading-tight'>
                <span className='truncate font-semibold'>
                  {activeTeam.name}
                </span>
                <span className='truncate text-xs'>{activeTeam.plan}</span>
              </div>
              <ChevronsUpDown className='ms-auto' />
            </SidebarMenuButton>
          </DropdownMenuTrigger>
          <DropdownMenuContent
            className='w-(--radix-dropdown-menu-trigger-width) min-w-56 rounded-lg'
            align='start'
            side={isMobile ? 'bottom' : 'right'}
            sideOffset={4}
          >
            <DropdownMenuLabel className='text-xs text-muted-foreground'>
              Teams
            </DropdownMenuLabel>
            {teams.map((team, index) => (
              <DropdownMenuItem
                key={team.name}
                onClick={() => setActiveTeam(team)}
                className='gap-2 p-2'
              >
                <div className='flex size-6 items-center justify-center rounded-sm border'>
                  <team.logo className='size-4 shrink-0' />
                </div>
                {team.name}
                <DropdownMenuShortcut>⌘{index + 1}</DropdownMenuShortcut>
              </DropdownMenuItem>
            ))}
            <DropdownMenuSeparator />
            <DropdownMenuItem className='gap-2 p-2'>
              <div className='flex size-6 items-center justify-center rounded-md border bg-background'>
                <Plus className='size-4' />
              </div>
              <div className='font-medium text-muted-foreground'>Add team</div>
            </DropdownMenuItem>
          </DropdownMenuContent>
        </DropdownMenu>
      </SidebarMenuItem>
    </SidebarMenu>
  )
}


================================================
FILE: src/components/layout/top-nav.tsx
================================================
import { Link } from '@tanstack/react-router'
import { Menu } from 'lucide-react'
import { cn } from '@/lib/utils'
import { Button } from '@/components/ui/button'
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuTrigger,
} from '@/components/ui/dropdown-menu'

type TopNavProps = React.HTMLAttributes<HTMLElement> & {
  links: {
    title: string
    href: string
    isActive: boolean
    disabled?: boolean
  }[]
}

export function TopNav({ className, links, ...props }: TopNavProps) {
  return (
    <>
      <div className='lg:hidden'>
        <DropdownMenu modal={false}>
          <DropdownMenuTrigger asChild>
            <Button size='icon' variant='outline' className='md:size-7'>
              <Menu />
            </Button>
          </DropdownMenuTrigger>
          <DropdownMenuContent side='bottom' align='start'>
            {links.map(({ title, href, isActive, disabled }) => (
              <DropdownMenuItem key={`${title}-${href}`} asChild>
                <Link
                  to={href}
                  className={!isActive ? 'text-muted-foreground' : ''}
                  disabled={disabled}
                >
                  {title}
                </Link>
              </DropdownMenuItem>
            ))}
          </DropdownMenuContent>
        </DropdownMenu>
      </div>

      <nav
        className={cn(
          'hidden items-center space-x-4 lg:flex lg:space-x-4 xl:space-x-6',
          className
        )}
        {...props}
      >
        {links.map(({ title, href, isActive, disabled }) => (
          <Link
            key={`${title}-${href}`}
            to={href}
            disabled={disabled}
            className={`text-sm font-medium transition-colors hover:text-primary ${isActive ? '' : 'text-muted-foreground'}`}
          >
            {title}
          </Link>
        ))}
      </nav>
    </>
  )
}


================================================
FILE: src/components/layout/types.ts
================================================
import { type LinkProps } from '@tanstack/react-router'

type User = {
  name: string
  email: string
  avatar: string
}

type Team = {
  name: string
  logo: React.ElementType
  plan: string
}

type BaseNavItem = {
  title: string
  badge?: string
  icon?: React.ElementType
}

type NavLink = BaseNavItem & {
  url: LinkProps['to'] | (string & {})
  items?: never
}

type NavCollapsible = BaseNavItem & {
  items: (BaseNavItem & { url: LinkProps['to'] | (string & {}) })[]
  url?: never
}

type NavItem = NavCollapsible | NavLink

type NavGroup = {
  title: string
  items: NavItem[]
}

type SidebarData = {
  user: User
  teams: Team[]
  navGroups: NavGroup[]
}

export type { SidebarData, NavGroup, NavItem, NavCollapsible, NavLink }


================================================
FILE: src/components/learn-more.tsx
================================================
import { type Root, type Content, type Trigger } from '@radix-ui/react-popover'
import { CircleQuestionMark } from 'lucide-react'
import { cn } from '@/lib/utils'
import { Button } from '@/components/ui/button'
import {
  Popover,
  PopoverContent,
  PopoverTrigger,
} from '@/components/ui/popover'

type LearnMoreProps = React.ComponentProps<typeof Root> & {
  contentProps?: React.ComponentProps<typeof Content>
  triggerProps?: React.ComponentProps<typeof Trigger>
}

export function LearnMore({
  children,
  contentProps,
  triggerProps,
  ...props
}: LearnMoreProps) {
  return (
    <Popover {...props}>
      <PopoverTrigger
        asChild
        {...triggerProps}
        className={cn('size-5 rounded-full', triggerProps?.className)}
      >
        <Button variant='outline' size='icon'>
          <span className='sr-only'>Learn more</span>
          <CircleQuestionMark className='size-4 [&>circle]:hidden' />
        </Button>
      </PopoverTrigger>
      <PopoverContent
        side='top'
        align='start'
        {...contentProps}
        className={cn('text-sm text-muted-foreground', contentProps?.className)}
      >
        {children}
      </PopoverContent>
    </Popover>
  )
}


================================================
FILE: src/components/long-text.tsx
================================================
import { useRef, useState } from 'react'
import { cn } from '@/lib/utils'
import {
  Popover,
  PopoverContent,
  PopoverTrigger,
} from '@/components/ui/popover'
import {
  Tooltip,
  TooltipContent,
  TooltipProvider,
  TooltipTrigger,
} from '@/components/ui/tooltip'

type LongTextProps = {
  children: React.ReactNode
  className?: string
  contentClassName?: string
}

export function LongText({
  children,
  className = '',
  contentClassName = '',
}: LongTextProps) {
  const ref = useRef<HTMLDivElement>(null)
  const [isOverflown, setIsOverflown] = useState(false)

  // Use ref callback to check overflow when element is mounted
  const refCallback = (node: HTMLDivElement | null) => {
    ref.current = node
    if (node && checkOverflow(node)) {
      queueMicrotask(() => setIsOverflown(true))
    }
  }

  if (!isOverflown)
    return (
      <div ref={refCallback} className={cn('truncate', className)}>
        {children}
      </div>
    )

  return (
    <>
      <div className='hidden sm:block'>
        <TooltipProvider delayDuration={0}>
          <Tooltip>
            <TooltipTrigger asChild>
              <div ref={refCallback} className={cn('truncate', className)}>
                {children}
              </div>
            </TooltipTrigger>
            <TooltipContent>
              <p className={contentClassName}>{children}</p>
            </TooltipContent>
          </Tooltip>
        </TooltipProvider>
      </div>
      <div className='sm:hidden'>
        <Popover>
          <PopoverTrigger asChild>
            <div ref={refCallback} className={cn('truncate', className)}>
              {children}
            </div>
          </PopoverTrigger>
          <PopoverContent className={cn('w-fit', contentClassName)}>
            <p>{children}</p>
          </PopoverContent>
        </Popover>
      </div>
    </>
  )
}

const checkOverflow = (textContainer: HTMLDivElement | null) => {
  if (textContainer) {
    return (
      textContainer.offsetHeight < textContainer.scrollHeight ||
      textContainer.offsetWidth < textContainer.scrollWidth
    )
  }
  return false
}


================================================
FILE: src/components/navigation-progress.tsx
================================================
import { useEffect, useRef } from 'react'
import { useRouterState } from '@tanstack/react-router'
import LoadingBar, { type LoadingBarRef } from 'react-top-loading-bar'

export function NavigationProgress() {
  const ref = useRef<LoadingBarRef>(null)
  const state = useRouterState()

  useEffect(() => {
    if (state.status === 'pending') {
      ref.current?.continuousStart()
    } else {
      ref.current?.complete()
    }
  }, [state.status])

  return (
    <LoadingBar
      color='var(--muted-foreground)'
      ref={ref}
      shadow={true}
      height={2}
    />
  )
}


================================================
FILE: src/components/password-input.tsx
================================================
import * as React from 'react'
import { Eye, EyeOff } from 'lucide-react'
import { cn } from '@/lib/utils'
import { Button } from './ui/button'

type PasswordInputProps = Omit<
  React.InputHTMLAttributes<HTMLInputElement>,
  'type'
> & {
  ref?: React.Ref<HTMLInputElement>
}

export function PasswordInput({
  className,
  disabled,
  ref,
  ...props
}: PasswordInputProps) {
  const [showPassword, setShowPassword] = React.useState(false)

  return (
    <div className={cn('relative rounded-md', className)}>
      <input
        type={showPassword ? 'text' : 'password'}
        className='flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-xs transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:ring-1 focus-visible:ring-ring focus-visible:outline-hidden disabled:cursor-not-allowed disabled:opacity-50'
        ref={ref}
        disabled={disabled}
        {...props}
      />
      <Button
        type='button'
        size='icon'
        variant='ghost'
        disabled={disabled}
        className='absolute end-1 top-1/2 h-6 w-6 -translate-y-1/2 rounded-md text-muted-foreground'
        onClick={() => setShowPassword((prev) => !prev)}
      >
        {showPassword ? <Eye size={18} /> : <EyeOff size={18} />}
      </Button>
    </div>
  )
}


================================================
FILE: src/components/profile-dropdown.tsx
================================================
import { Link } from '@tanstack/react-router'
import useDialogState from '@/hooks/use-dialog-state'
import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar'
import { Button } from '@/components/ui/button'
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuGroup,
  DropdownMenuItem,
  DropdownMenuLabel,
  DropdownMenuSeparator,
  DropdownMenuShortcut,
  DropdownMenuTrigger,
} from '@/components/ui/dropdown-menu'
import { SignOutDialog } from '@/components/sign-out-dialog'

export function ProfileDropdown() {
  const [open, setOpen] = useDialogState()

  return (
    <>
      <DropdownMenu modal={false}>
        <DropdownMenuTrigger asChild>
          <Button variant='ghost' className='relative h-8 w-8 rounded-full'>
            <Avatar className='h-8 w-8'>
              <AvatarImage src='/avatars/01.png' alt='@shadcn' />
              <AvatarFallback>SN</AvatarFallback>
            </Avatar>
          </Button>
        </DropdownMenuTrigger>
        <DropdownMenuContent className='w-56' align='end' forceMount>
          <DropdownMenuLabel className='font-normal'>
            <div className='flex flex-col gap-1.5'>
              <p className='text-sm leading-none font-medium'>satnaing</p>
              <p className='text-xs leading-none text-muted-foreground'>
                satnaingdev@gmail.com
              </p>
            </div>
          </DropdownMenuLabel>
          <DropdownMenuSeparator />
          <DropdownMenuGroup>
            <DropdownMenuItem asChild>
              <Link to='/settings'>
                Profile
                <DropdownMenuShortcut>⇧⌘P</DropdownMenuShortcut>
              </Link>
            </DropdownMenuItem>
            <DropdownMenuItem asChild>
              <Link to='/settings'>
                Billing
                <DropdownMenuShortcut>⌘B</DropdownMenuShortcut>
              </Link>
            </DropdownMenuItem>
            <DropdownMenuItem asChild>
              <Link to='/settings'>
                Settings
                <DropdownMenuShortcut>⌘S</DropdownMenuShortcut>
              </Link>
            </DropdownMenuItem>
            <DropdownMenuItem>New Team</DropdownMenuItem>
          </DropdownMenuGroup>
          <DropdownMenuSeparator />
          <DropdownMenuItem variant='destructive' onClick={() => setOpen(true)}>
            Sign out
            <DropdownMenuShortcut className='text-current'>
              ⇧⌘Q
            </DropdownMenuShortcut>
          </DropdownMenuItem>
        </DropdownMenuContent>
      </DropdownMenu>

      <SignOutDialog open={!!open} onOpenChange={setOpen} />
    </>
  )
}


================================================
FILE: src/components/search.tsx
================================================
import { SearchIcon } from 'lucide-react'
import { cn } from '@/lib/utils'
import { useSearch } from '@/context/search-provider'
import { Button } from './ui/button'

type SearchProps = {
  className?: string
  type?: React.HTMLInputTypeAttribute
  placeholder?: string
}

export function Search({
  className = '',
  placeholder = 'Search',
}: SearchProps) {
  const { setOpen } = useSearch()
  return (
    <Button
      variant='outline'
      className={cn(
        'group relative h-8 w-full flex-1 justify-start rounded-md bg-muted/25 text-sm font-normal text-muted-foreground shadow-none hover:bg-accent sm:w-40 sm:pe-12 md:flex-none lg:w-52 xl:w-64',
        className
      )}
      onClick={() => setOpen(true)}
    >
      <SearchIcon
        aria-hidden='true'
        className='absolute start-1.5 top-1/2 -translate-y-1/2'
        size={16}
      />
      <span className='ms-4'>{placeholder}</span>
      <kbd className='pointer-events-none absolute end-[0.3rem] top-[0.3rem] hidden h-5 items-center gap-1 rounded border bg-muted px-1.5 font-mono text-[10px] font-medium opacity-100 select-none group-hover:bg-accent sm:flex'>
        <span className='text-xs'>⌘</span>K
      </kbd>
    </Button>
  )
}


================================================
FILE: src/components/select-dropdown.tsx
================================================
import { Loader } from 'lucide-react'
import { cn } from '@/lib/utils'
import { FormControl } from '@/components/ui/form'
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from '@/components/ui/select'

type SelectDropdownProps = {
  onValueChange?: (value: string) => void
  defaultValue: string | undefined
  placeholder?: string
  isPending?: boolean
  items: { label: string; value: string }[] | undefined
  disabled?: boolean
  className?: string
  isControlled?: boolean
}

export function SelectDropdown({
  defaultValue,
  onValueChange,
  isPending,
  items,
  placeholder,
  disabled,
  className = '',
  isControlled = false,
}: SelectDropdownProps) {
  const defaultState = isControlled
    ? { value: defaultValue, onValueChange }
    : { defaultValue, onValueChange }
  return (
    <Select {...defaultState}>
      <FormControl>
        <SelectTrigger disabled={disabled} className={cn(className)}>
          <SelectValue placeholder={placeholder ?? 'Select'} />
        </SelectTrigger>
      </FormControl>
      <SelectContent>
        {isPending ? (
          <SelectItem disabled value='loading' className='h-14'>
            <div className='flex items-center justify-center gap-2'>
              <Loader className='h-5 w-5 animate-spin' />
              {'  '}
              Loading...
            </div>
          </SelectItem>
        ) : (
          items?.map(({ label, value }) => (
            <SelectItem key={value} value={value}>
              {label}
            </SelectItem>
          ))
        )}
      </SelectContent>
    </Select>
  )
}


================================================
FILE: src/components/sign-out-dialog.tsx
================================================
import { useNavigate, useLocation } from '@tanstack/react-router'
import { useAuthStore } from '@/stores/auth-store'
import { ConfirmDialog } from '@/components/confirm-dialog'

interface SignOutDialogProps {
  open: boolean
  onOpenChange: (open: boolean) => void
}

export function SignOutDialog({ open, onOpenChange }: SignOutDialogProps) {
  const navigate = useNavigate()
  const location = useLocation()
  const { auth } = useAuthStore()

  const handleSignOut = () => {
    auth.reset()
    // Preserve current location for redirect after sign-in
    const currentPath = location.href
    navigate({
      to: '/sign-in',
      search: { redirect: currentPath },
      replace: true,
    })
  }

  return (
    <ConfirmDialog
      open={open}
      onOpenChange={onOpenChange}
      title='Sign out'
      desc='Are you sure you want to sign out? You will need to sign in again to access your account.'
      confirmText='Sign out'
      destructive
      handleConfirm={handleSignOut}
      className='sm:max-w-sm'
    />
  )
}


================================================
FILE: src/components/skip-to-main.tsx
================================================
export function SkipToMain() {
  return (
    <a
      className={`fixed start-44 z-999 -translate-y-52 bg-primary px-4 py-2 text-sm font-medium whitespace-nowrap text-primary-foreground opacity-95 shadow-sm transition hover:bg-primary/90 focus:translate-y-3 focus:transform focus-visible:ring-1 focus-visible:ring-ring`}
      href='#content'
    >
      Skip to Main
    </a>
  )
}


================================================
FILE: src/components/theme-switch.tsx
================================================
import { useEffect } from 'react'
import { Check, Moon, Sun } from 'lucide-react'
import { cn } from '@/lib/utils'
import { useTheme } from '@/context/theme-provider'
import { Button } from '@/components/ui/button'
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuTrigger,
} from '@/components/ui/dropdown-menu'

export function ThemeSwitch() {
  const { theme, setTheme } = useTheme()

  /* Update theme-color meta tag
   * when theme is updated */
  useEffect(() => {
    const themeColor = theme === 'dark' ? '#020817' : '#fff'
    const metaThemeColor = document.querySelector("meta[name='theme-color']")
    if (metaThemeColor) metaThemeColor.setAttribute('content', themeColor)
  }, [theme])

  return (
    <DropdownMenu modal={false}>
      <DropdownMenuTrigger asChild>
        <Button variant='ghost' size='icon' className='scale-95 rounded-full'>
          <Sun className='size-[1.2rem] scale-100 rotate-0 transition-all dark:scale-0 dark:-rotate-90' />
          <Moon className='absolute size-[1.2rem] scale-0 rotate-90 transition-all dark:scale-100 dark:rotate-0' />
          <span className='sr-only'>Toggle theme</span>
        </Button>
      </DropdownMenuTrigger>
      <DropdownMenuContent align='end'>
        <DropdownMenuItem onClick={() => setTheme('light')}>
          Light{' '}
          <Check
            size={14}
            className={cn('ms-auto', theme !== 'light' && 'hidden')}
          />
        </DropdownMenuItem>
        <DropdownMenuItem onClick={() => setTheme('dark')}>
          Dark
          <Check
            size={14}
            className={cn('ms-auto', theme !== 'dark' && 'hidden')}
          />
        </DropdownMenuItem>
        <DropdownMenuItem onClick={() => setTheme('system')}>
          System
          <Check
            size={14}
            className={cn('ms-auto', theme !== 'system' && 'hidden')}
          />
        </DropdownMenuItem>
      </DropdownMenuContent>
    </DropdownMenu>
  )
}


================================================
FILE: src/components/ui/alert-dialog.tsx
================================================
import * as React from 'react'
import * as AlertDialogPrimitive from '@radix-ui/react-alert-dialog'
import { cn } from '@/lib/utils'
import { buttonVariants } from '@/components/ui/button'

function AlertDialog({
  ...props
}: React.ComponentProps<typeof AlertDialogPrimitive.Root>) {
  return <AlertDialogPrimitive.Root data-slot='alert-dialog' {...props} />
}

function AlertDialogTrigger({
  ...props
}: React.ComponentProps<typeof AlertDialogPrimitive.Trigger>) {
  return (
    <AlertDialogPrimitive.Trigger data-slot='alert-dialog-trigger' {...props} />
  )
}

function AlertDialogPortal({
  ...props
}: React.ComponentProps<typeof AlertDialogPrimitive.Portal>) {
  return (
    <AlertDialogPrimitive.Portal data-slot='alert-dialog-portal' {...props} />
  )
}

function AlertDialogOverlay({
  className,
  ...props
}: React.ComponentProps<typeof AlertDialogPrimitive.Overlay>) {
  return (
    <AlertDialogPrimitive.Overlay
      data-slot='alert-dialog-overlay'
      className={cn(
        'fixed inset-0 z-50 bg-black/50 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:animate-in data-[state=open]:fade-in-0',
        className
      )}
      {...props}
    />
  )
}

function AlertDialogContent({
  className,
  ...props
}: React.ComponentProps<typeof AlertDialogPrimitive.Content>) {
  return (
    <AlertDialogPortal>
      <AlertDialogOverlay />
      <AlertDialogPrimitive.Content
        data-slot='alert-dialog-content'
        className={cn(
          'fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border bg-background p-6 shadow-lg duration-200 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95 sm:max-w-lg',
          className
        )}
        {...props}
      />
    </AlertDialogPortal>
  )
}

function AlertDialogHeader({
  className,
  ...props
}: React.ComponentProps<'div'>) {
  return (
    <div
      data-slot='alert-dialog-header'
      className={cn('flex flex-col gap-2 text-center sm:text-start', className)}
      {...props}
    />
  )
}

function AlertDialogFooter({
  className,
  ...props
}: React.ComponentProps<'div'>) {
  return (
    <div
      data-slot='alert-dialog-footer'
      className={cn(
        'flex flex-col-reverse gap-2 sm:flex-row sm:justify-end',
        className
      )}
      {...props}
    />
  )
}

function AlertDialogTitle({
  className,
  ...props
}: React.ComponentProps<typeof AlertDialogPrimitive.Title>) {
  return (
    <AlertDialogPrimitive.Title
      data-slot='alert-dialog-title'
      className={cn('text-lg font-semibold', className)}
      {...props}
    />
  )
}

function AlertDialogDescription({
  className,
  ...props
}: React.ComponentProps<typeof AlertDialogPrimitive.Description>) {
  return (
    <AlertDialogPrimitive.Description
      data-slot='alert-dialog-description'
      className={cn('text-sm text-muted-foreground', className)}
      {...props}
    />
  )
}

function AlertDialogAction({
  className,
  ...props
}: React.ComponentProps<typeof AlertDialogPrimitive.Action>) {
  return (
    <AlertDialogPrimitive.Action
      className={cn(buttonVariants(), className)}
      {...props}
    />
  )
}

function AlertDialogCancel({
  className,
  ...props
}: React.ComponentProps<typeof AlertDialogPrimitive.Cancel>) {
  return (
    <AlertDialogPrimitive.Cancel
      className={cn(buttonVariants({ variant: 'outline' }), className)}
      {...props}
    />
  )
}

export {
  AlertDialog,
  AlertDialogPortal,
  AlertDialogOverlay,
  AlertDialogTrigger,
  AlertDialogContent,
  AlertDialogHeader,
  AlertDialogFooter,
  AlertDialogTitle,
  AlertDialogDescription,
  AlertDialogAction,
  AlertDialogCancel,
}


================================================
FILE: src/components/ui/alert.tsx
================================================
import * as React from 'react'
import { cva, type VariantProps } from 'class-variance-authority'
import { cn } from '@/lib/utils'

const alertVariants = cva(
  'relative w-full rounded-lg border px-4 py-3 text-sm grid has-[>svg]:grid-cols-[calc(var(--spacing)*4)_1fr] grid-cols-[0_1fr] has-[>svg]:gap-x-3 gap-y-0.5 items-start [&>svg]:size-4 [&>svg]:translate-y-0.5 [&>svg]:text-current',
  {
    variants: {
      variant: {
        default: 'bg-card text-card-foreground',
        destructive:
          'text-destructive bg-card [&>svg]:text-current *:data-[slot=alert-description]:text-destructive/90',
      },
    },
    defaultVariants: {
      variant: 'default',
    },
  }
)

function Alert({
  className,
  variant,
  ...props
}: React.ComponentProps<'div'> & VariantProps<typeof alertVariants>) {
  return (
    <div
      data-slot='alert'
      role='alert'
      className={cn(alertVariants({ variant }), className)}
      {...props}
    />
  )
}

function AlertTitle({ className, ...props }: React.ComponentProps<'div'>) {
  return (
    <div
      data-slot='alert-title'
      className={cn(
        'col-start-2 line-clamp-1 min-h-4 font-medium tracking-tight',
        className
      )}
      {...props}
    />
  )
}

function AlertDescription({
  className,
  ...props
}: React.ComponentProps<'div'>) {
  return (
    <div
      data-slot='alert-description'
      className={cn(
        'col-start-2 grid justify-items-start gap-1 text-sm text-muted-foreground [&_p]:leading-relaxed',
        className
      )}
      {...props}
    />
  )
}

export { Alert, AlertTitle, AlertDescription }


================================================
FILE: src/components/ui/avatar.tsx
================================================
import * as React from 'react'
import * as AvatarPrimitive from '@radix-ui/react-avatar'
import { cn } from '@/lib/utils'

function Avatar({
  className,
  ...props
}: React.ComponentProps<typeof AvatarPrimitive.Root>) {
  return (
    <AvatarPrimitive.Root
      data-slot='avatar'
      className={cn(
        'relative flex size-8 shrink-0 overflow-hidden rounded-full',
        className
      )}
      {...props}
    />
  )
}

function AvatarImage({
  className,
  ...props
}: React.ComponentProps<typeof AvatarPrimitive.Image>) {
  return (
    <AvatarPrimitive.Image
      data-slot='avatar-image'
      className={cn('aspect-square size-full', className)}
      {...props}
    />
  )
}

function AvatarFallback({
  className,
  ...props
}: React.ComponentProps<typeof AvatarPrimitive.Fallback>) {
  return (
    <AvatarPrimitive.Fallback
      data-slot='avatar-fallback'
      className={cn(
        'flex size-full items-center justify-center rounded-full bg-muted',
        className
      )}
      {...props}
    />
  )
}

export { Avatar, AvatarImage, AvatarFallback }


================================================
FILE: src/components/ui/badge.tsx
================================================
import * as React from 'react'
import { Slot } from '@radix-ui/react-slot'
import { cva, type VariantProps } from 'class-variance-authority'
import { cn } from '@/lib/utils'

const badgeVariants = cva(
  'inline-flex items-center justify-center rounded-md border px-2 py-0.5 text-xs font-medium w-fit whitespace-nowrap shrink-0 [&>svg]:size-3 gap-1 [&>svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive transition-[color,box-shadow] overflow-hidden',
  {
    variants: {
      variant: {
        default:
          'border-transparent bg-primary text-primary-foreground [a&]:hover:bg-primary/90',
        secondary:
          'border-transparent bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90',
        destructive:
          'border-transparent bg-destructive text-white [a&]:hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60',
        outline:
          'text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground',
      },
    },
    defaultVariants: {
      variant: 'default',
    },
  }
)

function Badge({
  className,
  variant,
  asChild = false,
  ...props
}: React.ComponentProps<'span'> &
  VariantProps<typeof badgeVariants> & { asChild?: boolean }) {
  const Comp = asChild ? Slot : 'span'

  return (
    <Comp
      data-slot='badge'
      className={cn(badgeVariants({ variant }), className)}
      {...props}
    />
  )
}

export { Badge, badgeVariants }


================================================
FILE: src/components/ui/button.tsx
================================================
import * as React from 'react'
import { Slot } from '@radix-ui/react-slot'
import { cva, type VariantProps } from 'class-variance-authority'
import { cn } from '@/lib/utils'

const buttonVariants = cva(
  "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
  {
    variants: {
      variant: {
        default:
          'bg-primary text-primary-foreground shadow-xs hover:bg-primary/90',
        destructive:
          'bg-destructive text-white shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60',
        outline:
          'border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50',
        secondary:
          'bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80',
        ghost:
          'hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50',
        link: 'text-primary underline-offset-4 hover:underline',
      },
      size: {
        default: 'h-9 px-4 py-2 has-[>svg]:px-3',
        sm: 'h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5',
        lg: 'h-10 rounded-md px-6 has-[>svg]:px-4',
        icon: 'size-9',
      },
    },
    defaultVariants: {
      variant: 'default',
      size: 'default',
    },
  }
)

function Button({
  className,
  variant,
  size,
  asChild = false,
  ...props
}: React.ComponentProps<'button'> &
  VariantProps<typeof buttonVariants> & {
    asChild?: boolean
  }) {
  const Comp = asChild ? Slot : 'button'

  return (
    <Comp
      data-slot='button'
      className={cn(buttonVariants({ variant, size, className }))}
      {...props}
    />
  )
}

export { Button, buttonVariants }


================================================
FILE: src/components/ui/calendar.tsx
================================================
import * as React from 'react'
import {
  ChevronDownIcon,
  ChevronLeftIcon,
  ChevronRightIcon,
} from 'lucide-react'
import { DayButton, DayPicker, getDefaultClassNames } from 'react-day-picker'
import { cn } from '@/lib/utils'
import { Button, buttonVariants } from '@/components/ui/button'

function Calendar({
  className,
  classNames,
  showOutsideDays = true,
  captionLayout = 'label',
  buttonVariant = 'ghost',
  formatters,
  components,
  ...props
}: React.ComponentProps<typeof DayPicker> & {
  buttonVariant?: React.ComponentProps<typeof Button>['variant']
}) {
  const defaultClassNames = getDefaultClassNames()

  return (
    <DayPicker
      showOutsideDays={showOutsideDays}
      className={cn(
        'group/calendar bg-background p-3 [--cell-size:--spacing(8)] [[data-slot=card-content]_&]:bg-transparent [[data-slot=popover-content]_&]:bg-transparent',
        String.raw`rtl:**:[.rdp-button\_next>svg]:rotate-180`,
        String.raw`rtl:**:[.rdp-button\_previous>svg]:rotate-180`,
        className
      )}
      captionLayout={captionLayout}
      formatters={{
        formatMonthDropdown: (date) =>
          date.toLocaleString('default', { month: 'short' }),
        ...formatters,
      }}
      classNames={{
        root: cn('w-fit', defaultClassNames.root),
        months: cn(
          'flex gap-4 flex-col md:flex-row relative',
          defaultClassNames.months
        ),
        month: cn('flex flex-col w-full gap-4', defaultClassNames.month),
        nav: cn(
          'flex items-center gap-1 w-full absolute top-0 inset-x-0 justify-between',
          defaultClassNames.nav
        ),
        button_previous: cn(
          buttonVariants({ variant: buttonVariant }),
          'size-(--cell-size) aria-disabled:opacity-50 p-0 select-none',
          defaultClassNames.button_previous
        ),
        button_next: cn(
          buttonVariants({ variant: buttonVariant }),
          'size-(--cell-size) aria-disabled:opacity-50 p-0 select-none',
          defaultClassNames.button_next
        ),
        month_caption: cn(
          'flex items-center justify-center h-(--cell-size) w-full px-(--cell-size)',
          defaultClassNames.month_caption
        ),
        dropdowns: cn(
          'w-full flex items-center text-sm font-medium justify-center h-(--cell-size) gap-1.5',
          defaultClassNames.dropdowns
        ),
        dropdown_root: cn(
          'relative has-focus:border-ring border border-input shadow-xs has-focus:ring-ring/50 has-focus:ring-[3px] rounded-md',
          defaultClassNames.dropdown_root
        ),
        dropdown: cn(
          'absolute bg-popover inset-0 opacity-0',
          defaultClassNames.dropdown
        ),
        caption_label: cn(
          'select-none font-medium',
          captionLayout === 'label'
            ? 'text-sm'
            : 'rounded-md ps-2 pe-1 flex items-center gap-1 text-sm h-8 [&>svg]:text-muted-foreground [&>svg]:size-3.5',
          defaultClassNames.caption_label
        ),
        table: 'w-full border-collapse',
        weekdays: cn('flex', defaultClassNames.weekdays),
        weekday: cn(
          'text-muted-foreground rounded-md flex-1 font-normal text-[0.8rem] select-none',
          defaultClassNames.weekday
        ),
        week: cn('flex w-full mt-2', defaultClassNames.week),
        week_number_header: cn(
          'select-none w-(--cell-size)',
          defaultClassNames.week_number_header
        ),
        week_number: cn(
          'text-[0.8rem] select-none text-muted-foreground',
          defaultClassNames.week_number
        ),
        day: cn(
          'relative w-full h-full p-0 text-center [&:first-child[data-selected=true]_button]:rounded-l-md [&:last-child[data-selected=true]_button]:rounded-r-md group/day aspect-square select-none',
          defaultClassNames.day
        ),
        range_start: cn(
          'rounded-l-md bg-accent',
          defaultClassNames.range_start
        ),
        range_middle: cn('rounded-none', defaultClassNames.range_middle),
        range_end: cn('rounded-r-md bg-accent', defaultClassNames.range_end),
        today: cn(
          'bg-accent text-accent-foreground rounded-md data-[selected=true]:rounded-none',
          defaultClassNames.today
        ),
        outside: cn(
          'text-muted-foreground aria-selected:text-muted-foreground',
          defaultClassNames.outside
        ),
        disabled: cn(
          'text-muted-foreground opacity-50',
          defaultClassNames.disabled
        ),
        hidden: cn('invisible', defaultClassNames.hidden),
        ...classNames,
      }}
      components={{
        Root: ({ className, rootRef, ...props }) => {
          return (
            <div
              data-slot='calendar'
              ref={rootRef}
              className={cn(className)}
              {...props}
            />
          )
        },
        Chevron: ({ className, orientation, ...props }) => {
          if (orientation === 'left') {
            return (
              <ChevronLeftIcon className={cn('size-4', className)} {...props} />
            )
          }

          if (orientation === 'right') {
            return (
              <ChevronRightIcon
                className={cn('size-4', className)}
                {...props}
              />
            )
          }

          return (
            <ChevronDownIcon className={cn('size-4', className)} {...props} />
          )
        },
        DayButton: CalendarDayButton,
        WeekNumber: ({ children, ...props }) => {
          return (
            <td {...props}>
              <div className='flex size-(--cell-size) items-center justify-center text-center'>
                {children}
              </div>
            </td>
          )
        },
        ...components,
      }}
      {...props}
    />
  )
}

function CalendarDayButton({
  className,
  day,
  modifiers,
  ...props
}: React.ComponentProps<typeof DayButton>) {
  const defaultClassNames = getDefaultClassNames()

  const ref = React.useRef<HTMLButtonElement>(null)
  React.useEffect(() => {
    if (modifiers.focused) ref.current?.focus()
  }, [modifiers.focused])

  return (
    <Button
      ref={ref}
      variant='ghost'
      size='icon'
      data-day={day.date.toLocaleDateString()}
      data-selected-single={
        modifiers.selected &&
        !modifiers.range_start &&
        !modifiers.range_end &&
        !modifiers.range_middle
      }
      data-range-start={modifiers.range_start}
      data-range-end={modifiers.range_end}
      data-range-middle={modifiers.range_middle}
      className={cn(
        'flex aspect-square size-auto w-full min-w-(--cell-size) flex-col gap-1 leading-none font-normal group-data-[focused=true]/day:relative group-data-[focused=true]/day:z-10 group-data-[focused=true]/day:border-ring group-data-[focused=true]/day:ring-[3px] group-data-[focused=true]/day:ring-ring/50 data-[range-end=true]:rounded-md data-[range-end=true]:rounded-r-md data-[range-end=true]:bg-primary data-[range-end=true]:text-primary-foreground data-[range-middle=true]:rounded-none data-[range-middle=true]:bg-accent data-[range-middle=true]:text-accent-foreground data-[range-start=true]:rounded-md data-[range-start=true]:rounded-l-md data-[range-start=true]:bg-primary data-[range-start=true]:text-primary-foreground data-[selected-single=true]:bg-primary data-[selected-single=true]:text-primary-foreground dark:hover:text-accent-foreground [&>span]:text-xs [&>span]:opacity-70',
        defaultClassNames.day,
        className
      )}
      {...props}
    />
  )
}

export { Calendar, CalendarDayButton }


================================================
FILE: src/components/ui/card.tsx
================================================
import * as React from 'react'
import { cn } from '@/lib/utils'

function Card({ className, ...props }: React.ComponentProps<'div'>) {
  return (
    <div
      data-slot='card'
      className={cn(
        'flex flex-col gap-6 rounded-xl border bg-card py-6 text-card-foreground shadow-sm',
        className
      )}
      {...props}
    />
  )
}

function CardHeader({ className, ...props }: React.ComponentProps<'div'>) {
  return (
    <div
      data-slot='card-header'
      className={cn(
        '@container/card-header grid auto-rows-min grid-rows-[auto_auto] items-start gap-1.5 px-6 has-data-[slot=card-action]:grid-cols-[1fr_auto] [.border-b]:pb-6',
        className
      )}
      {...props}
    />
  )
}

function CardTitle({ className, ...props }: React.ComponentProps<'div'>) {
  return (
    <div
      data-slot='card-title'
      className={cn('leading-none font-semibold', className)}
      {...props}
    />
  )
}

function CardDescription({ className, ...props }: React.ComponentProps<'div'>) {
  return (
    <div
      data-slot='card-description'
      className={cn('text-sm text-muted-foreground', className)}
      {...props}
    />
  )
}

function CardAction({ className, ...props }: React.ComponentProps<'div'>) {
  return (
    <div
      data-slot='card-action'
      className={cn(
        'col-start-2 row-span-2 row-start-1 self-start justify-self-end',
        className
      )}
      {...props}
    />
  )
}

function CardContent({ className, ...props }: React.ComponentProps<'div'>) {
  return (
    <div
      data-slot='card-content'
      className={cn('px-6', className)}
      {...props}
    />
  )
}

function CardFooter({ className, ...props }: React.ComponentProps<'div'>) {
  return (
    <div
      data-slot='card-footer'
      className={cn('flex items-center px-6 [.border-t]:pt-6', className)}
      {...props}
    />
  )
}

export {
  Card,
  CardHeader,
  CardFooter,
  CardTitle,
  CardAction,
  CardDescription,
  CardContent,
}


================================================
FILE: src/components/ui/checkbox.tsx
================================================
import * as React from 'react'
import * as CheckboxPrimitive from '@radix-ui/react-checkbox'
import { CheckIcon } from 'lucide-react'
import { cn } from '@/lib/utils'

function Checkbox({
  className,
  ...props
}: React.ComponentProps<typeof CheckboxPrimitive.Root>) {
  return (
    <CheckboxPrimitive.Root
      data-slot='checkbox'
      className={cn(
        'peer size-4 shrink-0 rounded-[4px] border border-input shadow-xs transition-shadow outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 data-[state=checked]:border-primary data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground dark:bg-input/30 dark:aria-invalid:ring-destructive/40 dark:data-[state=checked]:bg-primary',
        className
      )}
      {...props}
    >
      <CheckboxPrimitive.Indicator
        data-slot='checkbox-indicator'
        className='flex items-center justify-center text-current transition-none'
      >
        <CheckIcon className='size-3.5' />
      </CheckboxPrimitive.Indicator>
    </CheckboxPrimitive.Root>
  )
}

export { Checkbox }


================================================
FILE: src/components/ui/collapsible.tsx
================================================
import * as CollapsiblePrimitive from '@radix-ui/react-collapsible'

function Collapsible({
  ...props
}: React.ComponentProps<typeof CollapsiblePrimitive.Root>) {
  return <CollapsiblePrimitive.Root data-slot='collapsible' {...props} />
}

function CollapsibleTrigger({
  ...props
}: React.ComponentProps<typeof CollapsiblePrimitive.CollapsibleTrigger>) {
  return (
    <CollapsiblePrimitive.CollapsibleTrigger
      data-slot='collapsible-trigger'
      {...props}
    />
  )
}

function CollapsibleContent({
  ...props
}: React.ComponentProps<typeof CollapsiblePrimitive.CollapsibleContent>) {
  return (
    <CollapsiblePrimitive.CollapsibleContent
      data-slot='collapsible-content'
      {...props}
    />
  )
}

export { Collapsible, CollapsibleTrigger, CollapsibleContent }


================================================
FILE: src/components/ui/command.tsx
================================================
import * as React from 'react'
import { Command as CommandPrimitive } from 'cmdk'
import { SearchIcon } from 'lucide-react'
import { cn } from '@/lib/utils'
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogHeader,
  DialogTitle,
} from '@/components/ui/dialog'

function Command({
  className,
  ...props
}: React.ComponentProps<typeof CommandPrimitive>) {
  return (
    <CommandPrimitive
      data-slot='command'
      className={cn(
        'flex h-full w-full flex-col overflow-hidden rounded-md bg-popover text-popover-foreground',
        className
      )}
      {...props}
    />
  )
}

function CommandDialog({
  title = 'Command Palette',
  description = 'Search for a command to run...',
  children,
  className,
  showCloseButton = true,
  ...props
}: React.ComponentProps<typeof Dialog> & {
  title?: string
  description?: string
  className?: string
  showCloseButton?: boolean
}) {
  return (
    <Dialog {...props}>
      <DialogHeader className='sr-only'>
        <DialogTitle>{title}</DialogTitle>
        <DialogDescription>{description}</DialogDescription>
      </DialogHeader>
      <DialogContent
        className={cn('overflow-hidden p-0', className)}
        showCloseButton={showCloseButton}
      >
        <Command className='**:data-[slot=command-input-wrapper]:h-12 [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground [&_[cmdk-group]]:px-2 [&_[cmdk-group]:not([hidden])_~[cmdk-group]]:pt-0 [&_[cmdk-input-wrapper]_svg]:h-5 [&_[cmdk-input-wrapper]_svg]:w-5 [&_[cmdk-input]]:h-12 [&_[cmdk-item]]:px-2 [&_[cmdk-item]]:py-3 [&_[cmdk-item]_svg]:h-5 [&_[cmdk-item]_svg]:w-5'>
          {children}
        </Command>
      </DialogContent>
    </Dialog>
  )
}

function CommandInput({
  className,
  ...props
}: React.ComponentProps<typeof CommandPrimitive.Input>) {
  return (
    <div
      data-slot='command-input-wrapper'
      className='flex h-9 items-center gap-2 border-b px-3'
    >
      <SearchIcon className='size-4 shrink-0 opacity-50' />
      <CommandPrimitive.Input
        data-slot='command-input'
        className={cn(
          'flex h-10 w-full rounded-md bg-transparent py-3 text-sm outline-hidden placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50',
          className
        )}
        {...props}
      />
    </div>
  )
}

function CommandList({
  className,
  ...props
}: React.ComponentProps<typeof CommandPrimitive.List>) {
  return (
    <CommandPrimitive.List
      data-slot='command-list'
      className={cn(
        'max-h-[300px] scroll-py-1 overflow-x-hidden overflow-y-auto',
        className
      )}
      {...props}
    />
  )
}

function CommandEmpty({
  ...props
}: React.ComponentProps<typeof CommandPrimitive.Empty>) {
  return (
    <CommandPrimitive.Empty
      data-slot='command-empty'
      className='py-6 text-center text-sm'
      {...props}
    />
  )
}

function CommandGroup({
  className,
  ...props
}: React.ComponentProps<typeof CommandPrimitive.Group>) {
  return (
    <CommandPrimitive.Group
      data-slot='command-group'
      className={cn(
        'overflow-hidden p-1 text-foreground [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground',
        className
      )}
      {...props}
    />
  )
}

function CommandSeparator({
  className,
  ...props
}: React.ComponentProps<typeof CommandPrimitive.Separator>) {
  return (
    <CommandPrimitive.Separator
      data-slot='command-separator'
      className={cn('-mx-1 h-px bg-border', className)}
      {...props}
    />
  )
}

function CommandItem({
  className,
  ...props
}: React.ComponentProps<typeof CommandPrimitive.Item>) {
  return (
    <CommandPrimitive.Item
      data-slot='command-item'
      className={cn(
        "relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50 data-[selected=true]:bg-accent data-[selected=true]:text-accent-foreground [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 [&_svg:not([class*='text-'])]:text-muted-foreground",
        className
      )}
      {...props}
    />
  )
}

function CommandShortcut({
  className,
  ...props
}: React.ComponentProps<'span'>) {
  return (
    <span
      data-slot='command-shortcut'
      className={cn(
        'ms-auto text-xs tracking-widest text-muted-foreground',
        className
      )}
      {...props}
    />
  )
}

export {
  Command,
  CommandDialog,
  CommandInput,
  CommandList,
  CommandEmpty,
  CommandGroup,
  CommandItem,
  CommandShortcut,
  CommandSeparator,
}


================================================
FILE: src/components/ui/dialog.tsx
================================================
'use client'

import * as React from 'react'
import * as DialogPrimitive from '@radix-ui/react-dialog'
import { XIcon } from 'lucide-react'
import { cn } from '@/lib/utils'

function Dialog({
  ...props
}: React.ComponentProps<typeof DialogPrimitive.Root>) {
  return <DialogPrimitive.Root data-slot='dialog' {...props} />
}

function DialogTrigger({
  ...props
}: React.ComponentProps<typeof DialogPrimitive.Trigger>) {
  return <DialogPrimitive.Trigger data-slot='dialog-trigger' {...props} />
}

function DialogPortal({
  ...props
}: React.ComponentProps<typeof DialogPrimitive.Portal>) {
  return <DialogPrimitive.Portal data-slot='dialog-portal' {...props} />
}

function DialogClose({
  ...props
}: React.ComponentProps<typeof DialogPrimitive.Close>) {
  return <DialogPrimitive.Close data-slot='dialog-close' {...props} />
}

function DialogOverlay({
  className,
  ...props
}: React.ComponentProps<typeof DialogPrimitive.Overlay>) {
  return (
    <DialogPrimitive.Overlay
      data-slot='dialog-overlay'
      className={cn(
        'fixed inset-0 z-50 bg-black/50 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:animate-in data-[state=open]:fade-in-0',
        className
      )}
      {...props}
    />
  )
}

function DialogContent({
  className,
  children,
  showCloseButton = true,
  ...props
}: React.ComponentProps<typeof DialogPrimitive.Content> & {
  showCloseButton?: boolean
}) {
  return (
    <DialogPortal data-slot='dialog-portal'>
      <DialogOverlay />
      <DialogPrimitive.Content
        data-slot='dialog-content'
        className={cn(
          'fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border bg-background p-6 shadow-lg duration-200 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95 sm:max-w-lg',
          className
        )}
        {...props}
      >
        {children}
        {showCloseButton && (
          <DialogPrimitive.Close
            data-slot='dialog-close'
            c
Download .txt
gitextract_5m319v_v/

├── .github/
│   ├── CODE_OF_CONDUCT.md
│   ├── CONTRIBUTING.md
│   ├── FUNDING.yml
│   ├── ISSUE_TEMPLATE/
│   │   ├── config.yml
│   │   ├── ✨-feature-request.md
│   │   └── 🐞-bug-report.md
│   ├── PULL_REQUEST_TEMPLATE.md
│   └── workflows/
│       ├── ci.yml
│       └── stale.yml
├── .gitignore
├── .prettierignore
├── .prettierrc
├── CHANGELOG.md
├── LICENSE
├── README.md
├── components.json
├── cz.yaml
├── eslint.config.js
├── index.html
├── knip.config.ts
├── netlify.toml
├── package.json
├── src/
│   ├── assets/
│   │   ├── brand-icons/
│   │   │   ├── icon-discord.tsx
│   │   │   ├── icon-docker.tsx
│   │   │   ├── icon-facebook.tsx
│   │   │   ├── icon-figma.tsx
│   │   │   ├── icon-github.tsx
│   │   │   ├── icon-gitlab.tsx
│   │   │   ├── icon-gmail.tsx
│   │   │   ├── icon-medium.tsx
│   │   │   ├── icon-notion.tsx
│   │   │   ├── icon-skype.tsx
│   │   │   ├── icon-slack.tsx
│   │   │   ├── icon-stripe.tsx
│   │   │   ├── icon-telegram.tsx
│   │   │   ├── icon-trello.tsx
│   │   │   ├── icon-whatsapp.tsx
│   │   │   ├── icon-zoom.tsx
│   │   │   └── index.ts
│   │   ├── clerk-full-logo.tsx
│   │   ├── clerk-logo.tsx
│   │   ├── custom/
│   │   │   ├── icon-dir.tsx
│   │   │   ├── icon-layout-compact.tsx
│   │   │   ├── icon-layout-default.tsx
│   │   │   ├── icon-layout-full.tsx
│   │   │   ├── icon-sidebar-floating.tsx
│   │   │   ├── icon-sidebar-inset.tsx
│   │   │   ├── icon-sidebar-sidebar.tsx
│   │   │   ├── icon-theme-dark.tsx
│   │   │   ├── icon-theme-light.tsx
│   │   │   └── icon-theme-system.tsx
│   │   └── logo.tsx
│   ├── components/
│   │   ├── coming-soon.tsx
│   │   ├── command-menu.tsx
│   │   ├── config-drawer.tsx
│   │   ├── confirm-dialog.tsx
│   │   ├── data-table/
│   │   │   ├── bulk-actions.tsx
│   │   │   ├── column-header.tsx
│   │   │   ├── faceted-filter.tsx
│   │   │   ├── index.ts
│   │   │   ├── pagination.tsx
│   │   │   ├── toolbar.tsx
│   │   │   └── view-options.tsx
│   │   ├── date-picker.tsx
│   │   ├── layout/
│   │   │   ├── app-sidebar.tsx
│   │   │   ├── app-title.tsx
│   │   │   ├── authenticated-layout.tsx
│   │   │   ├── data/
│   │   │   │   └── sidebar-data.ts
│   │   │   ├── header.tsx
│   │   │   ├── main.tsx
│   │   │   ├── nav-group.tsx
│   │   │   ├── nav-user.tsx
│   │   │   ├── team-switcher.tsx
│   │   │   ├── top-nav.tsx
│   │   │   └── types.ts
│   │   ├── learn-more.tsx
│   │   ├── long-text.tsx
│   │   ├── navigation-progress.tsx
│   │   ├── password-input.tsx
│   │   ├── profile-dropdown.tsx
│   │   ├── search.tsx
│   │   ├── select-dropdown.tsx
│   │   ├── sign-out-dialog.tsx
│   │   ├── skip-to-main.tsx
│   │   ├── theme-switch.tsx
│   │   └── ui/
│   │       ├── alert-dialog.tsx
│   │       ├── alert.tsx
│   │       ├── avatar.tsx
│   │       ├── badge.tsx
│   │       ├── button.tsx
│   │       ├── calendar.tsx
│   │       ├── card.tsx
│   │       ├── checkbox.tsx
│   │       ├── collapsible.tsx
│   │       ├── command.tsx
│   │       ├── dialog.tsx
│   │       ├── dropdown-menu.tsx
│   │       ├── form.tsx
│   │       ├── input-otp.tsx
│   │       ├── input.tsx
│   │       ├── label.tsx
│   │       ├── popover.tsx
│   │       ├── radio-group.tsx
│   │       ├── scroll-area.tsx
│   │       ├── select.tsx
│   │       ├── separator.tsx
│   │       ├── sheet.tsx
│   │       ├── sidebar.tsx
│   │       ├── skeleton.tsx
│   │       ├── sonner.tsx
│   │       ├── switch.tsx
│   │       ├── table.tsx
│   │       ├── tabs.tsx
│   │       ├── textarea.tsx
│   │       └── tooltip.tsx
│   ├── config/
│   │   └── fonts.ts
│   ├── context/
│   │   ├── direction-provider.tsx
│   │   ├── font-provider.tsx
│   │   ├── layout-provider.tsx
│   │   ├── search-provider.tsx
│   │   └── theme-provider.tsx
│   ├── features/
│   │   ├── apps/
│   │   │   ├── data/
│   │   │   │   └── apps.tsx
│   │   │   └── index.tsx
│   │   ├── auth/
│   │   │   ├── auth-layout.tsx
│   │   │   ├── forgot-password/
│   │   │   │   ├── components/
│   │   │   │   │   └── forgot-password-form.tsx
│   │   │   │   └── index.tsx
│   │   │   ├── otp/
│   │   │   │   ├── components/
│   │   │   │   │   └── otp-form.tsx
│   │   │   │   └── index.tsx
│   │   │   ├── sign-in/
│   │   │   │   ├── components/
│   │   │   │   │   └── user-auth-form.tsx
│   │   │   │   ├── index.tsx
│   │   │   │   └── sign-in-2.tsx
│   │   │   └── sign-up/
│   │   │       ├── components/
│   │   │       │   └── sign-up-form.tsx
│   │   │       └── index.tsx
│   │   ├── chats/
│   │   │   ├── components/
│   │   │   │   └── new-chat.tsx
│   │   │   ├── data/
│   │   │   │   ├── chat-types.ts
│   │   │   │   └── convo.json
│   │   │   └── index.tsx
│   │   ├── dashboard/
│   │   │   ├── components/
│   │   │   │   ├── analytics-chart.tsx
│   │   │   │   ├── analytics.tsx
│   │   │   │   ├── overview.tsx
│   │   │   │   └── recent-sales.tsx
│   │   │   └── index.tsx
│   │   ├── errors/
│   │   │   ├── forbidden.tsx
│   │   │   ├── general-error.tsx
│   │   │   ├── maintenance-error.tsx
│   │   │   ├── not-found-error.tsx
│   │   │   └── unauthorized-error.tsx
│   │   ├── settings/
│   │   │   ├── account/
│   │   │   │   ├── account-form.tsx
│   │   │   │   └── index.tsx
│   │   │   ├── appearance/
│   │   │   │   ├── appearance-form.tsx
│   │   │   │   └── index.tsx
│   │   │   ├── components/
│   │   │   │   ├── content-section.tsx
│   │   │   │   └── sidebar-nav.tsx
│   │   │   ├── display/
│   │   │   │   ├── display-form.tsx
│   │   │   │   └── index.tsx
│   │   │   ├── index.tsx
│   │   │   ├── notifications/
│   │   │   │   ├── index.tsx
│   │   │   │   └── notifications-form.tsx
│   │   │   └── profile/
│   │   │       ├── index.tsx
│   │   │       └── profile-form.tsx
│   │   ├── tasks/
│   │   │   ├── components/
│   │   │   │   ├── data-table-bulk-actions.tsx
│   │   │   │   ├── data-table-row-actions.tsx
│   │   │   │   ├── tasks-columns.tsx
│   │   │   │   ├── tasks-dialogs.tsx
│   │   │   │   ├── tasks-import-dialog.tsx
│   │   │   │   ├── tasks-multi-delete-dialog.tsx
│   │   │   │   ├── tasks-mutate-drawer.tsx
│   │   │   │   ├── tasks-primary-buttons.tsx
│   │   │   │   ├── tasks-provider.tsx
│   │   │   │   └── tasks-table.tsx
│   │   │   ├── data/
│   │   │   │   ├── data.tsx
│   │   │   │   ├── schema.ts
│   │   │   │   └── tasks.ts
│   │   │   └── index.tsx
│   │   └── users/
│   │       ├── components/
│   │       │   ├── data-table-bulk-actions.tsx
│   │       │   ├── data-table-row-actions.tsx
│   │       │   ├── users-action-dialog.tsx
│   │       │   ├── users-columns.tsx
│   │       │   ├── users-delete-dialog.tsx
│   │       │   ├── users-dialogs.tsx
│   │       │   ├── users-invite-dialog.tsx
│   │       │   ├── users-multi-delete-dialog.tsx
│   │       │   ├── users-primary-buttons.tsx
│   │       │   ├── users-provider.tsx
│   │       │   └── users-table.tsx
│   │       ├── data/
│   │       │   ├── data.ts
│   │       │   ├── schema.ts
│   │       │   └── users.ts
│   │       └── index.tsx
│   ├── hooks/
│   │   ├── use-dialog-state.tsx
│   │   ├── use-mobile.tsx
│   │   └── use-table-url-state.ts
│   ├── lib/
│   │   ├── cookies.ts
│   │   ├── handle-server-error.ts
│   │   ├── show-submitted-data.tsx
│   │   └── utils.ts
│   ├── main.tsx
│   ├── routeTree.gen.ts
│   ├── routes/
│   │   ├── (auth)/
│   │   │   ├── forgot-password.tsx
│   │   │   ├── otp.tsx
│   │   │   ├── sign-in-2.tsx
│   │   │   ├── sign-in.tsx
│   │   │   └── sign-up.tsx
│   │   ├── (errors)/
│   │   │   ├── 401.tsx
│   │   │   ├── 403.tsx
│   │   │   ├── 404.tsx
│   │   │   ├── 500.tsx
│   │   │   └── 503.tsx
│   │   ├── __root.tsx
│   │   ├── _authenticated/
│   │   │   ├── apps/
│   │   │   │   └── index.tsx
│   │   │   ├── chats/
│   │   │   │   └── index.tsx
│   │   │   ├── errors/
│   │   │   │   └── $error.tsx
│   │   │   ├── help-center/
│   │   │   │   └── index.tsx
│   │   │   ├── index.tsx
│   │   │   ├── route.tsx
│   │   │   ├── settings/
│   │   │   │   ├── account.tsx
│   │   │   │   ├── appearance.tsx
│   │   │   │   ├── display.tsx
│   │   │   │   ├── index.tsx
│   │   │   │   ├── notifications.tsx
│   │   │   │   └── route.tsx
│   │   │   ├── tasks/
│   │   │   │   └── index.tsx
│   │   │   └── users/
│   │   │       └── index.tsx
│   │   └── clerk/
│   │       ├── (auth)/
│   │       │   ├── route.tsx
│   │       │   ├── sign-in.tsx
│   │       │   └── sign-up.tsx
│   │       ├── _authenticated/
│   │       │   ├── route.tsx
│   │       │   └── user-management.tsx
│   │       └── route.tsx
│   ├── stores/
│   │   └── auth-store.ts
│   ├── styles/
│   │   ├── index.css
│   │   └── theme.css
│   ├── tanstack-table.d.ts
│   └── vite-env.d.ts
├── tsconfig.app.json
├── tsconfig.json
├── tsconfig.node.json
└── vite.config.ts
Download .txt
SYMBOL INDEX (435 symbols across 170 files)

FILE: src/assets/brand-icons/icon-discord.tsx
  function IconDiscord (line 4) | function IconDiscord({ className, ...props }: SVGProps<SVGSVGElement>) {

FILE: src/assets/brand-icons/icon-docker.tsx
  function IconDocker (line 4) | function IconDocker({ className, ...props }: SVGProps<SVGSVGElement>) {

FILE: src/assets/brand-icons/icon-facebook.tsx
  function IconFacebook (line 4) | function IconFacebook({ className, ...props }: SVGProps<SVGSVGElement>) {

FILE: src/assets/brand-icons/icon-figma.tsx
  function IconFigma (line 4) | function IconFigma({ className, ...props }: SVGProps<SVGSVGElement>) {

FILE: src/assets/brand-icons/icon-github.tsx
  function IconGithub (line 4) | function IconGithub({ className, ...props }: SVGProps<SVGSVGElement>) {

FILE: src/assets/brand-icons/icon-gitlab.tsx
  function IconGitlab (line 4) | function IconGitlab({ className, ...props }: SVGProps<SVGSVGElement>) {

FILE: src/assets/brand-icons/icon-gmail.tsx
  function IconGmail (line 4) | function IconGmail({ className, ...props }: SVGProps<SVGSVGElement>) {

FILE: src/assets/brand-icons/icon-medium.tsx
  function IconMedium (line 4) | function IconMedium({ className, ...props }: SVGProps<SVGSVGElement>) {

FILE: src/assets/brand-icons/icon-notion.tsx
  function IconNotion (line 4) | function IconNotion({ className, ...props }: SVGProps<SVGSVGElement>) {

FILE: src/assets/brand-icons/icon-skype.tsx
  function IconSkype (line 4) | function IconSkype({ className, ...props }: SVGProps<SVGSVGElement>) {

FILE: src/assets/brand-icons/icon-slack.tsx
  function IconSlack (line 4) | function IconSlack({ className, ...props }: SVGProps<SVGSVGElement>) {

FILE: src/assets/brand-icons/icon-stripe.tsx
  function IconStripe (line 4) | function IconStripe({ className, ...props }: SVGProps<SVGSVGElement>) {

FILE: src/assets/brand-icons/icon-telegram.tsx
  function IconTelegram (line 4) | function IconTelegram({ className, ...props }: SVGProps<SVGSVGElement>) {

FILE: src/assets/brand-icons/icon-trello.tsx
  function IconTrello (line 4) | function IconTrello({ className, ...props }: SVGProps<SVGSVGElement>) {

FILE: src/assets/brand-icons/icon-whatsapp.tsx
  function IconWhatsapp (line 4) | function IconWhatsapp({ className, ...props }: SVGProps<SVGSVGElement>) {

FILE: src/assets/brand-icons/icon-zoom.tsx
  function IconZoom (line 4) | function IconZoom({ className, ...props }: SVGProps<SVGSVGElement>) {

FILE: src/assets/clerk-full-logo.tsx
  function ClerkFullLogo (line 3) | function ClerkFullLogo(props: SVGProps<SVGSVGElement>) {

FILE: src/assets/clerk-logo.tsx
  function ClerkLogo (line 4) | function ClerkLogo({ className, ...props }: SVGProps<SVGSVGElement>) {

FILE: src/assets/custom/icon-dir.tsx
  type IconDirProps (line 5) | type IconDirProps = SVGProps<SVGSVGElement> & {
  function IconDir (line 9) | function IconDir({ dir, className, ...props }: IconDirProps) {

FILE: src/assets/custom/icon-layout-compact.tsx
  function IconLayoutCompact (line 3) | function IconLayoutCompact(props: SVGProps<SVGSVGElement>) {

FILE: src/assets/custom/icon-layout-default.tsx
  function IconLayoutDefault (line 3) | function IconLayoutDefault(props: SVGProps<SVGSVGElement>) {

FILE: src/assets/custom/icon-layout-full.tsx
  function IconLayoutFull (line 3) | function IconLayoutFull(props: SVGProps<SVGSVGElement>) {

FILE: src/assets/custom/icon-sidebar-floating.tsx
  function IconSidebarFloating (line 3) | function IconSidebarFloating(props: SVGProps<SVGSVGElement>) {

FILE: src/assets/custom/icon-sidebar-inset.tsx
  function IconSidebarInset (line 3) | function IconSidebarInset(props: SVGProps<SVGSVGElement>) {

FILE: src/assets/custom/icon-sidebar-sidebar.tsx
  function IconSidebarSidebar (line 3) | function IconSidebarSidebar(props: SVGProps<SVGSVGElement>) {

FILE: src/assets/custom/icon-theme-dark.tsx
  function IconThemeDark (line 3) | function IconThemeDark(props: SVGProps<SVGSVGElement>) {

FILE: src/assets/custom/icon-theme-light.tsx
  function IconThemeLight (line 3) | function IconThemeLight(props: SVGProps<SVGSVGElement>) {

FILE: src/assets/custom/icon-theme-system.tsx
  function IconThemeSystem (line 4) | function IconThemeSystem({

FILE: src/assets/logo.tsx
  function Logo (line 4) | function Logo({ className, ...props }: SVGProps<SVGSVGElement>) {

FILE: src/components/coming-soon.tsx
  function ComingSoon (line 3) | function ComingSoon() {

FILE: src/components/command-menu.tsx
  function CommandMenu (line 18) | function CommandMenu() {

FILE: src/components/config-drawer.tsx
  function ConfigDrawer (line 30) | function ConfigDrawer() {
  function SectionTitle (line 83) | function SectionTitle({
  function RadioGroupItem (line 116) | function RadioGroupItem({
  function ThemeConfig (line 171) | function ThemeConfig() {
  function SidebarConfig (line 214) | function SidebarConfig() {
  function LayoutConfig (line 257) | function LayoutConfig() {
  function DirConfig (line 314) | function DirConfig() {

FILE: src/components/confirm-dialog.tsx
  type ConfirmDialogProps (line 13) | type ConfirmDialogProps = {
  function ConfirmDialog (line 28) | function ConfirmDialog(props: ConfirmDialogProps) {

FILE: src/components/data-table/bulk-actions.tsx
  type DataTableBulkActionsProps (line 14) | type DataTableBulkActionsProps<TData> = {
  function DataTableBulkActions (line 30) | function DataTableBulkActions<TData>({

FILE: src/components/data-table/column-header.tsx
  type DataTableColumnHeaderProps (line 18) | type DataTableColumnHeaderProps<TData, TValue> =
  function DataTableColumnHeader (line 24) | function DataTableColumnHeader<TData, TValue>({

FILE: src/components/data-table/faceted-filter.tsx
  type DataTableFacetedFilterProps (line 23) | type DataTableFacetedFilterProps<TData, TValue> = {
  function DataTableFacetedFilter (line 33) | function DataTableFacetedFilter<TData, TValue>({

FILE: src/components/data-table/pagination.tsx
  type DataTablePaginationProps (line 18) | type DataTablePaginationProps<TData> = {
  function DataTablePagination (line 23) | function DataTablePagination<TData>({

FILE: src/components/data-table/toolbar.tsx
  type DataTableToolbarProps (line 8) | type DataTableToolbarProps<TData> = {
  function DataTableToolbar (line 23) | function DataTableToolbar<TData>({

FILE: src/components/data-table/view-options.tsx
  type DataTableViewOptionsProps (line 13) | type DataTableViewOptionsProps<TData> = {
  function DataTableViewOptions (line 17) | function DataTableViewOptions<TData>({

FILE: src/components/date-picker.tsx
  type DatePickerProps (line 11) | type DatePickerProps = {
  function DatePicker (line 17) | function DatePicker({

FILE: src/components/layout/app-sidebar.tsx
  function AppSidebar (line 15) | function AppSidebar() {

FILE: src/components/layout/app-title.tsx
  function AppTitle (line 12) | function AppTitle() {
  function ToggleSidebar (line 39) | function ToggleSidebar({

FILE: src/components/layout/authenticated-layout.tsx
  type AuthenticatedLayoutProps (line 10) | type AuthenticatedLayoutProps = {
  function AuthenticatedLayout (line 14) | function AuthenticatedLayout({ children }: AuthenticatedLayoutProps) {

FILE: src/components/layout/header.tsx
  type HeaderProps (line 6) | type HeaderProps = React.HTMLAttributes<HTMLElement> & {
  function Header (line 11) | function Header({ className, fixed, children, ...props }: HeaderProps) {

FILE: src/components/layout/main.tsx
  type MainProps (line 3) | type MainProps = React.HTMLAttributes<HTMLElement> & {
  function Main (line 9) | function Main({ fixed, className, fluid, ...props }: MainProps) {

FILE: src/components/layout/nav-group.tsx
  function NavGroup (line 36) | function NavGroup({ title, items }: NavGroupProps) {
  function NavBadge (line 61) | function NavBadge({ children }: { children: ReactNode }) {
  function SidebarMenuLink (line 65) | function SidebarMenuLink({ item, href }: { item: NavLink; href: string }) {
  function SidebarMenuCollapsible (line 84) | function SidebarMenuCollapsible({
  function SidebarMenuCollapsedDropdown (line 130) | function SidebarMenuCollapsedDropdown({
  function checkIsActive (line 176) | function checkIsActive(href: string, item: NavItem, mainNav = false) {

FILE: src/components/layout/nav-user.tsx
  type NavUserProps (line 29) | type NavUserProps = {
  function NavUser (line 37) | function NavUser({ user }: NavUserProps) {

FILE: src/components/layout/team-switcher.tsx
  type TeamSwitcherProps (line 19) | type TeamSwitcherProps = {
  function TeamSwitcher (line 27) | function TeamSwitcher({ teams }: TeamSwitcherProps) {

FILE: src/components/layout/top-nav.tsx
  type TopNavProps (line 12) | type TopNavProps = React.HTMLAttributes<HTMLElement> & {
  function TopNav (line 21) | function TopNav({ className, links, ...props }: TopNavProps) {

FILE: src/components/layout/types.ts
  type User (line 3) | type User = {
  type Team (line 9) | type Team = {
  type BaseNavItem (line 15) | type BaseNavItem = {
  type NavLink (line 21) | type NavLink = BaseNavItem & {
  type NavCollapsible (line 26) | type NavCollapsible = BaseNavItem & {
  type NavItem (line 31) | type NavItem = NavCollapsible | NavLink
  type NavGroup (line 33) | type NavGroup = {
  type SidebarData (line 38) | type SidebarData = {

FILE: src/components/learn-more.tsx
  type LearnMoreProps (line 11) | type LearnMoreProps = React.ComponentProps<typeof Root> & {
  function LearnMore (line 16) | function LearnMore({

FILE: src/components/long-text.tsx
  type LongTextProps (line 15) | type LongTextProps = {
  function LongText (line 21) | function LongText({

FILE: src/components/navigation-progress.tsx
  function NavigationProgress (line 5) | function NavigationProgress() {

FILE: src/components/password-input.tsx
  type PasswordInputProps (line 6) | type PasswordInputProps = Omit<
  function PasswordInput (line 13) | function PasswordInput({

FILE: src/components/profile-dropdown.tsx
  function ProfileDropdown (line 17) | function ProfileDropdown() {

FILE: src/components/search.tsx
  type SearchProps (line 6) | type SearchProps = {
  function Search (line 12) | function Search({

FILE: src/components/select-dropdown.tsx
  type SelectDropdownProps (line 12) | type SelectDropdownProps = {
  function SelectDropdown (line 23) | function SelectDropdown({

FILE: src/components/sign-out-dialog.tsx
  type SignOutDialogProps (line 5) | interface SignOutDialogProps {
  function SignOutDialog (line 10) | function SignOutDialog({ open, onOpenChange }: SignOutDialogProps) {

FILE: src/components/skip-to-main.tsx
  function SkipToMain (line 1) | function SkipToMain() {

FILE: src/components/theme-switch.tsx
  function ThemeSwitch (line 13) | function ThemeSwitch() {

FILE: src/components/ui/alert-dialog.tsx
  function AlertDialog (line 6) | function AlertDialog({
  function AlertDialogTrigger (line 12) | function AlertDialogTrigger({
  function AlertDialogPortal (line 20) | function AlertDialogPortal({
  function AlertDialogOverlay (line 28) | function AlertDialogOverlay({
  function AlertDialogContent (line 44) | function AlertDialogContent({
  function AlertDialogHeader (line 63) | function AlertDialogHeader({
  function AlertDialogFooter (line 76) | function AlertDialogFooter({
  function AlertDialogTitle (line 92) | function AlertDialogTitle({
  function AlertDialogDescription (line 105) | function AlertDialogDescription({
  function AlertDialogAction (line 118) | function AlertDialogAction({
  function AlertDialogCancel (line 130) | function AlertDialogCancel({

FILE: src/components/ui/alert.tsx
  function Alert (line 21) | function Alert({
  function AlertTitle (line 36) | function AlertTitle({ className, ...props }: React.ComponentProps<'div'>) {
  function AlertDescription (line 49) | function AlertDescription({

FILE: src/components/ui/avatar.tsx
  function Avatar (line 5) | function Avatar({
  function AvatarImage (line 21) | function AvatarImage({
  function AvatarFallback (line 34) | function AvatarFallback({

FILE: src/components/ui/badge.tsx
  function Badge (line 27) | function Badge({

FILE: src/components/ui/button.tsx
  function Button (line 37) | function Button({

FILE: src/components/ui/calendar.tsx
  function Calendar (line 11) | function Calendar({
  function CalendarDayButton (line 172) | function CalendarDayButton({

FILE: src/components/ui/card.tsx
  function Card (line 4) | function Card({ className, ...props }: React.ComponentProps<'div'>) {
  function CardHeader (line 17) | function CardHeader({ className, ...props }: React.ComponentProps<'div'>) {
  function CardTitle (line 30) | function CardTitle({ className, ...props }: React.ComponentProps<'div'>) {
  function CardDescription (line 40) | function CardDescription({ className, ...props }: React.ComponentProps<'...
  function CardAction (line 50) | function CardAction({ className, ...props }: React.ComponentProps<'div'>) {
  function CardContent (line 63) | function CardContent({ className, ...props }: React.ComponentProps<'div'...
  function CardFooter (line 73) | function CardFooter({ className, ...props }: React.ComponentProps<'div'>) {

FILE: src/components/ui/checkbox.tsx
  function Checkbox (line 6) | function Checkbox({

FILE: src/components/ui/collapsible.tsx
  function Collapsible (line 3) | function Collapsible({
  function CollapsibleTrigger (line 9) | function CollapsibleTrigger({
  function CollapsibleContent (line 20) | function CollapsibleContent({

FILE: src/components/ui/command.tsx
  function Command (line 13) | function Command({
  function CommandDialog (line 29) | function CommandDialog({
  function CommandInput (line 60) | function CommandInput({
  function CommandList (line 82) | function CommandList({
  function CommandEmpty (line 98) | function CommandEmpty({
  function CommandGroup (line 110) | function CommandGroup({
  function CommandSeparator (line 126) | function CommandSeparator({
  function CommandItem (line 139) | function CommandItem({
  function CommandShortcut (line 155) | function CommandShortcut({

FILE: src/components/ui/dialog.tsx
  function Dialog (line 8) | function Dialog({
  function DialogTrigger (line 14) | function DialogTrigger({
  function DialogPortal (line 20) | function DialogPortal({
  function DialogClose (line 26) | function DialogClose({
  function DialogOverlay (line 32) | function DialogOverlay({
  function DialogContent (line 48) | function DialogContent({
  function DialogHeader (line 82) | function DialogHeader({ className, ...props }: React.ComponentProps<'div...
  function DialogFooter (line 92) | function DialogFooter({ className, ...props }: React.ComponentProps<'div...
  function DialogTitle (line 105) | function DialogTitle({
  function DialogDescription (line 118) | function DialogDescription({

FILE: src/components/ui/dropdown-menu.tsx
  function DropdownMenu (line 6) | function DropdownMenu({
  function DropdownMenuPortal (line 12) | function DropdownMenuPortal({
  function DropdownMenuTrigger (line 20) | function DropdownMenuTrigger({
  function DropdownMenuContent (line 31) | function DropdownMenuContent({
  function DropdownMenuGroup (line 51) | function DropdownMenuGroup({
  function DropdownMenuItem (line 59) | function DropdownMenuItem({
  function DropdownMenuCheckboxItem (line 82) | function DropdownMenuCheckboxItem({
  function DropdownMenuRadioGroup (line 108) | function DropdownMenuRadioGroup({
  function DropdownMenuRadioItem (line 119) | function DropdownMenuRadioItem({
  function DropdownMenuLabel (line 143) | function DropdownMenuLabel({
  function DropdownMenuSeparator (line 163) | function DropdownMenuSeparator({
  function DropdownMenuShortcut (line 176) | function DropdownMenuShortcut({
  function DropdownMenuSub (line 192) | function DropdownMenuSub({
  function DropdownMenuSubTrigger (line 198) | function DropdownMenuSubTrigger({
  function DropdownMenuSubContent (line 222) | function DropdownMenuSubContent({

FILE: src/components/ui/form.tsx
  type FormFieldContextValue (line 18) | type FormFieldContextValue<
  type FormItemContextValue (line 65) | type FormItemContextValue = {
  function FormItem (line 73) | function FormItem({ className, ...props }: React.ComponentProps<'div'>) {
  function FormLabel (line 87) | function FormLabel({
  function FormControl (line 104) | function FormControl({ ...props }: React.ComponentProps<typeof Slot>) {
  function FormDescription (line 122) | function FormDescription({ className, ...props }: React.ComponentProps<'...
  function FormMessage (line 135) | function FormMessage({ className, ...props }: React.ComponentProps<'p'>) {

FILE: src/components/ui/input-otp.tsx
  function InputOTP (line 6) | function InputOTP({
  function InputOTPGroup (line 26) | function InputOTPGroup({ className, ...props }: React.ComponentProps<'di...
  function InputOTPSlot (line 36) | function InputOTPSlot({
  function InputOTPSeparator (line 66) | function InputOTPSeparator({ ...props }: React.ComponentProps<'div'>) {

FILE: src/components/ui/input.tsx
  function Input (line 4) | function Input({ className, type, ...props }: React.ComponentProps<'inpu...

FILE: src/components/ui/label.tsx
  function Label (line 7) | function Label({

FILE: src/components/ui/popover.tsx
  function Popover (line 5) | function Popover({
  function PopoverTrigger (line 11) | function PopoverTrigger({
  function PopoverContent (line 17) | function PopoverContent({
  function PopoverAnchor (line 39) | function PopoverAnchor({

FILE: src/components/ui/radio-group.tsx
  function RadioGroup (line 6) | function RadioGroup({
  function RadioGroupItem (line 19) | function RadioGroupItem({

FILE: src/components/ui/scroll-area.tsx
  type ScrollAreaProps (line 5) | interface ScrollAreaProps extends React.ComponentProps<
  function ScrollArea (line 11) | function ScrollArea({
  function ScrollBar (line 38) | function ScrollBar({

FILE: src/components/ui/select.tsx
  function Select (line 6) | function Select({
  function SelectGroup (line 12) | function SelectGroup({
  function SelectValue (line 18) | function SelectValue({
  function SelectTrigger (line 24) | function SelectTrigger({
  function SelectContent (line 50) | function SelectContent({
  function SelectLabel (line 85) | function SelectLabel({
  function SelectItem (line 98) | function SelectItem({
  function SelectSeparator (line 122) | function SelectSeparator({
  function SelectScrollUpButton (line 135) | function SelectScrollUpButton({
  function SelectScrollDownButton (line 153) | function SelectScrollDownButton({

FILE: src/components/ui/separator.tsx
  function Separator (line 5) | function Separator({

FILE: src/components/ui/sheet.tsx
  function Sheet (line 6) | function Sheet({ ...props }: React.ComponentProps<typeof SheetPrimitive....
  function SheetTrigger (line 10) | function SheetTrigger({
  function SheetClose (line 16) | function SheetClose({
  function SheetPortal (line 22) | function SheetPortal({
  function SheetOverlay (line 28) | function SheetOverlay({
  function SheetContent (line 44) | function SheetContent({
  function SheetHeader (line 81) | function SheetHeader({ className, ...props }: React.ComponentProps<'div'...
  function SheetFooter (line 91) | function SheetFooter({ className, ...props }: React.ComponentProps<'div'...
  function SheetTitle (line 101) | function SheetTitle({
  function SheetDescription (line 114) | function SheetDescription({

FILE: src/components/ui/sidebar.tsx
  constant SIDEBAR_COOKIE_NAME (line 25) | const SIDEBAR_COOKIE_NAME = 'sidebar_state'
  constant SIDEBAR_COOKIE_MAX_AGE (line 26) | const SIDEBAR_COOKIE_MAX_AGE = 60 * 60 * 24 * 7
  constant SIDEBAR_WIDTH (line 27) | const SIDEBAR_WIDTH = '16rem'
  constant SIDEBAR_WIDTH_MOBILE (line 28) | const SIDEBAR_WIDTH_MOBILE = '18rem'
  constant SIDEBAR_WIDTH_ICON (line 29) | const SIDEBAR_WIDTH_ICON = '3rem'
  constant SIDEBAR_KEYBOARD_SHORTCUT (line 30) | const SIDEBAR_KEYBOARD_SHORTCUT = 'b'
  type SidebarContextProps (line 32) | type SidebarContextProps = {
  function useSidebar (line 44) | function useSidebar() {
  function SidebarProvider (line 53) | function SidebarProvider({
  function Sidebar (line 151) | function Sidebar({
  function SidebarTrigger (line 253) | function SidebarTrigger({
  function SidebarRail (line 279) | function SidebarRail({ className, ...props }: React.ComponentProps<'butt...
  function SidebarInset (line 309) | function SidebarInset({ className, ...props }: React.ComponentProps<'div...
  function SidebarInput (line 323) | function SidebarInput({
  function SidebarHeader (line 337) | function SidebarHeader({ className, ...props }: React.ComponentProps<'di...
  function SidebarFooter (line 348) | function SidebarFooter({ className, ...props }: React.ComponentProps<'di...
  function SidebarSeparator (line 359) | function SidebarSeparator({
  function SidebarContent (line 373) | function SidebarContent({ className, ...props }: React.ComponentProps<'d...
  function SidebarGroup (line 387) | function SidebarGroup({ className, ...props }: React.ComponentProps<'div...
  function SidebarGroupLabel (line 398) | function SidebarGroupLabel({
  function SidebarGroupAction (line 419) | function SidebarGroupAction({
  function SidebarGroupContent (line 442) | function SidebarGroupContent({
  function SidebarMenu (line 456) | function SidebarMenu({ className, ...props }: React.ComponentProps<'ul'>) {
  function SidebarMenuItem (line 467) | function SidebarMenuItem({ className, ...props }: React.ComponentProps<'...
  function SidebarMenuButton (line 500) | function SidebarMenuButton({
  function SidebarMenuAction (line 550) | function SidebarMenuAction({
  function SidebarMenuBadge (line 582) | function SidebarMenuBadge({
  function SidebarMenuSkeleton (line 604) | function SidebarMenuSkeleton({
  function SidebarMenuSub (line 642) | function SidebarMenuSub({ className, ...props }: React.ComponentProps<'u...
  function SidebarMenuSubItem (line 657) | function SidebarMenuSubItem({
  function SidebarMenuSubButton (line 671) | function SidebarMenuSubButton({

FILE: src/components/ui/skeleton.tsx
  function Skeleton (line 3) | function Skeleton({ className, ...props }: React.ComponentProps<'div'>) {

FILE: src/components/ui/sonner.tsx
  function Toaster (line 4) | function Toaster({ ...props }: ToasterProps) {

FILE: src/components/ui/switch.tsx
  function Switch (line 5) | function Switch({

FILE: src/components/ui/table.tsx
  function Table (line 4) | function Table({ className, ...props }: React.ComponentProps<'table'>) {
  function TableHeader (line 19) | function TableHeader({ className, ...props }: React.ComponentProps<'thea...
  function TableBody (line 29) | function TableBody({ className, ...props }: React.ComponentProps<'tbody'...
  function TableFooter (line 39) | function TableFooter({ className, ...props }: React.ComponentProps<'tfoo...
  function TableRow (line 52) | function TableRow({ className, ...props }: React.ComponentProps<'tr'>) {
  function TableHead (line 65) | function TableHead({ className, ...props }: React.ComponentProps<'th'>) {
  function TableCell (line 78) | function TableCell({ className, ...props }: React.ComponentProps<'td'>) {
  function TableCaption (line 91) | function TableCaption({

FILE: src/components/ui/tabs.tsx
  function Tabs (line 5) | function Tabs({
  function TabsList (line 18) | function TabsList({
  function TabsTrigger (line 34) | function TabsTrigger({
  function TabsContent (line 50) | function TabsContent({

FILE: src/components/ui/textarea.tsx
  function Textarea (line 4) | function Textarea({ className, ...props }: React.ComponentProps<'textare...

FILE: src/components/ui/tooltip.tsx
  function TooltipProvider (line 7) | function TooltipProvider({
  function Tooltip (line 20) | function Tooltip({
  function TooltipTrigger (line 30) | function TooltipTrigger({
  function TooltipContent (line 36) | function TooltipContent({

FILE: src/context/direction-provider.tsx
  type Direction (line 5) | type Direction = 'ltr' | 'rtl'
  constant DEFAULT_DIRECTION (line 7) | const DEFAULT_DIRECTION = 'ltr'
  constant DIRECTION_COOKIE_NAME (line 8) | const DIRECTION_COOKIE_NAME = 'dir'
  constant DIRECTION_COOKIE_MAX_AGE (line 9) | const DIRECTION_COOKIE_MAX_AGE = 60 * 60 * 24 * 365 // 1 year
  type DirectionContextType (line 11) | type DirectionContextType = {
  function DirectionProvider (line 20) | function DirectionProvider({ children }: { children: React.ReactNode }) {
  function useDirection (line 55) | function useDirection() {

FILE: src/context/font-provider.tsx
  type Font (line 5) | type Font = (typeof fonts)[number]
  constant FONT_COOKIE_NAME (line 7) | const FONT_COOKIE_NAME = 'font'
  constant FONT_COOKIE_MAX_AGE (line 8) | const FONT_COOKIE_MAX_AGE = 60 * 60 * 24 * 365 // 1 year
  type FontContextType (line 10) | type FontContextType = {
  function FontProvider (line 18) | function FontProvider({ children }: { children: React.ReactNode }) {

FILE: src/context/layout-provider.tsx
  type Collapsible (line 4) | type Collapsible = 'offcanvas' | 'icon' | 'none'
  type Variant (line 5) | type Variant = 'inset' | 'sidebar' | 'floating'
  constant LAYOUT_COLLAPSIBLE_COOKIE_NAME (line 8) | const LAYOUT_COLLAPSIBLE_COOKIE_NAME = 'layout_collapsible'
  constant LAYOUT_VARIANT_COOKIE_NAME (line 9) | const LAYOUT_VARIANT_COOKIE_NAME = 'layout_variant'
  constant LAYOUT_COOKIE_MAX_AGE (line 10) | const LAYOUT_COOKIE_MAX_AGE = 60 * 60 * 24 * 7 // 7 days
  constant DEFAULT_VARIANT (line 13) | const DEFAULT_VARIANT = 'inset'
  constant DEFAULT_COLLAPSIBLE (line 14) | const DEFAULT_COLLAPSIBLE = 'icon'
  type LayoutContextType (line 16) | type LayoutContextType = {
  type LayoutProviderProps (line 30) | type LayoutProviderProps = {
  function LayoutProvider (line 34) | function LayoutProvider({ children }: LayoutProviderProps) {
  function useLayout (line 79) | function useLayout() {

FILE: src/context/search-provider.tsx
  type SearchContextType (line 4) | type SearchContextType = {
  type SearchProviderProps (line 11) | type SearchProviderProps = {
  function SearchProvider (line 15) | function SearchProvider({ children }: SearchProviderProps) {

FILE: src/context/theme-provider.tsx
  type Theme (line 4) | type Theme = 'dark' | 'light' | 'system'
  type ResolvedTheme (line 5) | type ResolvedTheme = Exclude<Theme, 'system'>
  constant DEFAULT_THEME (line 7) | const DEFAULT_THEME = 'system'
  constant THEME_COOKIE_NAME (line 8) | const THEME_COOKIE_NAME = 'vite-ui-theme'
  constant THEME_COOKIE_MAX_AGE (line 9) | const THEME_COOKIE_MAX_AGE = 60 * 60 * 24 * 365 // 1 year
  type ThemeProviderProps (line 11) | type ThemeProviderProps = {
  type ThemeProviderState (line 17) | type ThemeProviderState = {
  function ThemeProvider (line 35) | function ThemeProvider({

FILE: src/features/apps/index.tsx
  type AppType (line 24) | type AppType = 'all' | 'connected' | 'notConnected'
  function Apps (line 32) | function Apps() {

FILE: src/features/auth/auth-layout.tsx
  type AuthLayoutProps (line 3) | type AuthLayoutProps = {
  function AuthLayout (line 7) | function AuthLayout({ children }: AuthLayoutProps) {

FILE: src/features/auth/forgot-password/components/forgot-password-form.tsx
  function ForgotPasswordForm (line 26) | function ForgotPasswordForm({

FILE: src/features/auth/forgot-password/index.tsx
  function ForgotPassword (line 13) | function ForgotPassword() {

FILE: src/features/auth/otp/components/otp-form.tsx
  type OtpFormProps (line 31) | type OtpFormProps = React.HTMLAttributes<HTMLFormElement>
  function OtpForm (line 33) | function OtpForm({ className, ...props }: OtpFormProps) {

FILE: src/features/auth/otp/index.tsx
  function Otp (line 13) | function Otp() {

FILE: src/features/auth/sign-in/components/user-auth-form.tsx
  type UserAuthFormProps (line 33) | interface UserAuthFormProps extends React.HTMLAttributes<HTMLFormElement> {
  function UserAuthForm (line 37) | function UserAuthForm({

FILE: src/features/auth/sign-in/index.tsx
  function SignIn (line 13) | function SignIn() {

FILE: src/features/auth/sign-in/sign-in-2.tsx
  function SignIn2 (line 7) | function SignIn2() {

FILE: src/features/auth/sign-up/components/sign-up-form.tsx
  function SignUpForm (line 36) | function SignUpForm({

FILE: src/features/auth/sign-up/index.tsx
  function SignUp (line 13) | function SignUp() {

FILE: src/features/chats/components/new-chat.tsx
  type User (line 22) | type User = Omit<ChatUser, 'messages'>
  type NewChatProps (line 24) | type NewChatProps = {
  function NewChat (line 29) | function NewChat({ users, onOpenChange, open }: NewChatProps) {

FILE: src/features/chats/data/chat-types.ts
  type ChatUser (line 3) | type ChatUser = (typeof conversations)[number]
  type Convo (line 4) | type Convo = ChatUser['messages'][number]

FILE: src/features/chats/index.tsx
  function Chats (line 33) | function Chats() {

FILE: src/features/dashboard/components/analytics-chart.tsx
  function AnalyticsChart (line 41) | function AnalyticsChart() {

FILE: src/features/dashboard/components/analytics.tsx
  function Analytics (line 10) | function Analytics() {
  function SimpleBarList (line 154) | function SimpleBarList({

FILE: src/features/dashboard/components/overview.tsx
  function Overview (line 54) | function Overview() {

FILE: src/features/dashboard/components/recent-sales.tsx
  function RecentSales (line 3) | function RecentSales() {

FILE: src/features/dashboard/index.tsx
  function Dashboard (line 21) | function Dashboard() {

FILE: src/features/errors/forbidden.tsx
  function ForbiddenError (line 4) | function ForbiddenError() {

FILE: src/features/errors/general-error.tsx
  type GeneralErrorProps (line 5) | type GeneralErrorProps = React.HTMLAttributes<HTMLDivElement> & {
  function GeneralError (line 9) | function GeneralError({

FILE: src/features/errors/maintenance-error.tsx
  function MaintenanceError (line 3) | function MaintenanceError() {

FILE: src/features/errors/not-found-error.tsx
  function NotFoundError (line 4) | function NotFoundError() {

FILE: src/features/errors/unauthorized-error.tsx
  function UnauthorisedError (line 4) | function UnauthorisedError() {

FILE: src/features/settings/account/account-form.tsx
  type AccountFormValues (line 55) | type AccountFormValues = z.infer<typeof accountFormSchema>
  function AccountForm (line 62) | function AccountForm() {

FILE: src/features/settings/account/index.tsx
  function SettingsAccount (line 4) | function SettingsAccount() {

FILE: src/features/settings/appearance/appearance-form.tsx
  type AppearanceFormValues (line 27) | type AppearanceFormValues = z.infer<typeof appearanceFormSchema>
  function AppearanceForm (line 29) | function AppearanceForm() {

FILE: src/features/settings/appearance/index.tsx
  function SettingsAppearance (line 4) | function SettingsAppearance() {

FILE: src/features/settings/components/content-section.tsx
  type ContentSectionProps (line 3) | type ContentSectionProps = {
  function ContentSection (line 9) | function ContentSection({ title, desc, children }: ContentSectionProps) {

FILE: src/features/settings/components/sidebar-nav.tsx
  type SidebarNavProps (line 14) | type SidebarNavProps = React.HTMLAttributes<HTMLElement> & {
  function SidebarNav (line 22) | function SidebarNav({ className, items, ...props }: SidebarNavProps) {

FILE: src/features/settings/display/display-form.tsx
  type DisplayFormValues (line 50) | type DisplayFormValues = z.infer<typeof displayFormSchema>
  function DisplayForm (line 57) | function DisplayForm() {

FILE: src/features/settings/display/index.tsx
  function SettingsDisplay (line 4) | function SettingsDisplay() {

FILE: src/features/settings/index.tsx
  function Settings (line 40) | function Settings() {

FILE: src/features/settings/notifications/index.tsx
  function SettingsNotifications (line 4) | function SettingsNotifications() {

FILE: src/features/settings/notifications/notifications-form.tsx
  type NotificationsFormValues (line 34) | type NotificationsFormValues = z.infer<typeof notificationsFormSchema>
  function NotificationsForm (line 44) | function NotificationsForm() {

FILE: src/features/settings/profile/index.tsx
  function SettingsProfile (line 4) | function SettingsProfile() {

FILE: src/features/settings/profile/profile-form.tsx
  type ProfileFormValues (line 48) | type ProfileFormValues = z.infer<typeof profileFormSchema>
  function ProfileForm (line 59) | function ProfileForm() {

FILE: src/features/tasks/components/data-table-bulk-actions.tsx
  type DataTableBulkActionsProps (line 23) | type DataTableBulkActionsProps<TData> = {
  function DataTableBulkActions (line 27) | function DataTableBulkActions<TData>({

FILE: src/features/tasks/components/data-table-row-actions.tsx
  type DataTableRowActionsProps (line 22) | type DataTableRowActionsProps<TData> = {
  function DataTableRowActions (line 26) | function DataTableRowActions<TData>({

FILE: src/features/tasks/components/tasks-dialogs.tsx
  function TasksDialogs (line 7) | function TasksDialogs() {

FILE: src/features/tasks/components/tasks-import-dialog.tsx
  type TaskImportDialogProps (line 37) | type TaskImportDialogProps = {
  function TasksImportDialog (line 42) | function TasksImportDialog({

FILE: src/features/tasks/components/tasks-multi-delete-dialog.tsx
  type TaskMultiDeleteDialogProps (line 13) | type TaskMultiDeleteDialogProps<TData> = {
  constant CONFIRM_WORD (line 19) | const CONFIRM_WORD = 'DELETE'
  function TasksMultiDeleteDialog (line 21) | function TasksMultiDeleteDialog<TData>({

FILE: src/features/tasks/components/tasks-mutate-drawer.tsx
  type TaskMutateDrawerProps (line 28) | type TaskMutateDrawerProps = {
  type TaskForm (line 40) | type TaskForm = z.infer<typeof formSchema>
  function TasksMutateDrawer (line 42) | function TasksMutateDrawer({

FILE: src/features/tasks/components/tasks-primary-buttons.tsx
  function TasksPrimaryButtons (line 5) | function TasksPrimaryButtons() {

FILE: src/features/tasks/components/tasks-provider.tsx
  type TasksDialogType (line 5) | type TasksDialogType = 'create' | 'update' | 'delete' | 'import'
  type TasksContextType (line 7) | type TasksContextType = {
  function TasksProvider (line 16) | function TasksProvider({ children }: { children: React.ReactNode }) {

FILE: src/features/tasks/components/tasks-table.tsx
  type DataTableProps (line 33) | type DataTableProps = {
  function TasksTable (line 37) | function TasksTable({ data }: DataTableProps) {

FILE: src/features/tasks/data/schema.ts
  type Task (line 13) | type Task = z.infer<typeof taskSchema>

FILE: src/features/tasks/index.tsx
  function Tasks (line 13) | function Tasks() {

FILE: src/features/users/components/data-table-bulk-actions.tsx
  type DataTableBulkActionsProps (line 16) | type DataTableBulkActionsProps<TData> = {
  function DataTableBulkActions (line 20) | function DataTableBulkActions<TData>({

FILE: src/features/users/components/data-table-row-actions.tsx
  type DataTableRowActionsProps (line 16) | type DataTableRowActionsProps = {
  function DataTableRowActions (line 20) | function DataTableRowActions({ row }: DataTableRowActionsProps) {

FILE: src/features/users/components/users-action-dialog.tsx
  type UserForm (line 94) | type UserForm = z.infer<typeof formSchema>
  type UserActionDialogProps (line 96) | type UserActionDialogProps = {
  function UsersActionDialog (line 102) | function UsersActionDialog({

FILE: src/features/users/components/users-delete-dialog.tsx
  type UserDeleteDialogProps (line 12) | type UserDeleteDialogProps = {
  function UsersDeleteDialog (line 18) | function UsersDeleteDialog({

FILE: src/features/users/components/users-dialogs.tsx
  function UsersDialogs (line 6) | function UsersDialogs() {

FILE: src/features/users/components/users-invite-dialog.tsx
  type UserInviteForm (line 38) | type UserInviteForm = z.infer<typeof formSchema>
  type UserInviteDialogProps (line 40) | type UserInviteDialogProps = {
  function UsersInviteDialog (line 45) | function UsersInviteDialog({

FILE: src/features/users/components/users-multi-delete-dialog.tsx
  type UserMultiDeleteDialogProps (line 13) | type UserMultiDeleteDialogProps<TData> = {
  constant CONFIRM_WORD (line 19) | const CONFIRM_WORD = 'DELETE'
  function UsersMultiDeleteDialog (line 21) | function UsersMultiDeleteDialog<TData>({

FILE: src/features/users/components/users-primary-buttons.tsx
  function UsersPrimaryButtons (line 5) | function UsersPrimaryButtons() {

FILE: src/features/users/components/users-provider.tsx
  type UsersDialogType (line 5) | type UsersDialogType = 'invite' | 'add' | 'edit' | 'delete'
  type UsersContextType (line 7) | type UsersContextType = {
  function UsersProvider (line 16) | function UsersProvider({ children }: { children: React.ReactNode }) {

FILE: src/features/users/components/users-table.tsx
  type DataTableProps (line 30) | type DataTableProps = {
  function UsersTable (line 36) | function UsersTable({ data, search, navigate }: DataTableProps) {

FILE: src/features/users/data/schema.ts
  type UserStatus (line 9) | type UserStatus = z.infer<typeof userStatusSchema>
  type User (line 30) | type User = z.infer<typeof userSchema>

FILE: src/features/users/index.tsx
  function Users (line 16) | function Users() {

FILE: src/hooks/use-dialog-state.tsx
  function useDialogState (line 9) | function useDialogState<T extends string | boolean>(

FILE: src/hooks/use-mobile.tsx
  constant MOBILE_BREAKPOINT (line 3) | const MOBILE_BREAKPOINT = 768
  constant MOBILE_QUERY (line 4) | const MOBILE_QUERY = `(max-width: ${MOBILE_BREAKPOINT - 1}px)`
  function useIsMobile (line 6) | function useIsMobile() {

FILE: src/hooks/use-table-url-state.ts
  type SearchRecord (line 8) | type SearchRecord = Record<string, unknown>
  type NavigateFn (line 10) | type NavigateFn = (opts: {
  type UseTableUrlStateParams (line 18) | type UseTableUrlStateParams = {
  type UseTableUrlStateReturn (line 51) | type UseTableUrlStateReturn = {
  function useTableUrlState (line 68) | function useTableUrlState(

FILE: src/lib/cookies.ts
  constant DEFAULT_MAX_AGE (line 6) | const DEFAULT_MAX_AGE = 60 * 60 * 24 * 7 // 7 days
  function getCookie (line 11) | function getCookie(name: string): string | undefined {
  function setCookie (line 26) | function setCookie(
  function removeCookie (line 39) | function removeCookie(name: string): void {

FILE: src/lib/handle-server-error.ts
  function handleServerError (line 4) | function handleServerError(error: unknown) {

FILE: src/lib/show-submitted-data.tsx
  function showSubmittedData (line 3) | function showSubmittedData(

FILE: src/lib/utils.ts
  function cn (line 4) | function cn(...inputs: ClassValue[]) {
  function sleep (line 8) | function sleep(ms: number = 1000) {
  function getPageNumbers (line 24) | function getPageNumbers(currentPage: number, totalPages: number) {

FILE: src/main.tsx
  type Register (line 85) | interface Register {

FILE: src/routeTree.gen.ts
  type FileRoutesByFullPath (line 200) | interface FileRoutesByFullPath {
  type FileRoutesByTo (line 229) | interface FileRoutesByTo {
  type FileRoutesById (line 257) | interface FileRoutesById {
  type FileRouteTypes (line 290) | interface FileRouteTypes {
  type RootRouteChildren (line 382) | interface RootRouteChildren {
  type FileRoutesByPath (line 398) | interface FileRoutesByPath {
  type AuthenticatedSettingsRouteRouteChildren (line 612) | interface AuthenticatedSettingsRouteRouteChildren {
  type AuthenticatedRouteRouteChildren (line 635) | interface AuthenticatedRouteRouteChildren {
  type ClerkauthRouteRouteChildren (line 660) | interface ClerkauthRouteRouteChildren {
  type ClerkAuthenticatedRouteRouteChildren (line 674) | interface ClerkAuthenticatedRouteRouteChildren {
  type ClerkRouteRouteChildren (line 689) | interface ClerkRouteRouteChildren {

FILE: src/routes/_authenticated/errors/$error.tsx
  function RouteComponent (line 18) | function RouteComponent() {

FILE: src/routes/clerk/(auth)/route.tsx
  function ClerkAuthLayout (line 11) | function ClerkAuthLayout() {

FILE: src/routes/clerk/_authenticated/user-management.tsx
  function UserManagement (line 28) | function UserManagement() {
  constant COUNTDOWN (line 104) | const COUNTDOWN = 5 // Countdown second
  function Unauthorized (line 106) | function Unauthorized() {

FILE: src/routes/clerk/route.tsx
  constant PUBLISHABLE_KEY (line 18) | const PUBLISHABLE_KEY = import.meta.env.VITE_CLERK_PUBLISHABLE_KEY
  function RouteComponent (line 20) | function RouteComponent() {
  function MissingClerkPubKey (line 39) | function MissingClerkPubKey() {

FILE: src/stores/auth-store.ts
  constant ACCESS_TOKEN (line 4) | const ACCESS_TOKEN = 'thisisjustarandomstring'
  type AuthUser (line 6) | interface AuthUser {
  type AuthState (line 13) | interface AuthState {

FILE: src/tanstack-table.d.ts
  type ColumnMeta (line 5) | interface ColumnMeta<TData, TValue> {
Condensed preview — 238 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (572K chars).
[
  {
    "path": ".github/CODE_OF_CONDUCT.md",
    "chars": 5202,
    "preview": "# Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nWe as members, contributors, and leaders pledge to make participa"
  },
  {
    "path": ".github/CONTRIBUTING.md",
    "chars": 2441,
    "preview": "# Contributing to Shadcn-Admin\n\nThank you for considering contributing to **shadcn-admin**! Every contribution is valuab"
  },
  {
    "path": ".github/FUNDING.yml",
    "chars": 790,
    "preview": "github: [satnaing]\nbuy_me_a_coffee: satnaing\n\n# patreon: # Replace with a single Patreon username\n# open_collective: # R"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/config.yml",
    "chars": 188,
    "preview": "blank_issues_enabled: false\ncontact_links:\n  - name: Shadcn-Admin Discussions\n    url: https://github.com/satnaing/shadc"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/✨-feature-request.md",
    "chars": 636,
    "preview": "---\nname: \"✨ Feature Request\"\nabout: Suggest an idea for improving Shadcn-Admin\ntitle: \"[Feature Request]: \"\nlabels: enh"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/🐞-bug-report.md",
    "chars": 573,
    "preview": "---\nname: \"\\U0001F41E Bug report\"\nabout: Report a bug or unexpected behavior in Shadcn-Admin\ntitle: \"[BUG]: \"\nlabels: bu"
  },
  {
    "path": ".github/PULL_REQUEST_TEMPLATE.md",
    "chars": 1128,
    "preview": "## Description\n\n<!-- A clear and concise description of what the pull request does. Include any relevant motivation and "
  },
  {
    "path": ".github/workflows/ci.yml",
    "chars": 744,
    "preview": "name: Continuous Integration\n\non:\n  push:\n    branches:\n      - main\n\n  pull_request:\n    branches:\n      - main\n\njobs:\n"
  },
  {
    "path": ".github/workflows/stale.yml",
    "chars": 970,
    "preview": "name: Close inactive issues/PR\n\non:\n  schedule:\n  - cron: '38 18 * * *'\n\njobs:\n  stale:\n\n    runs-on: ubuntu-latest\n    "
  },
  {
    "path": ".gitignore",
    "chars": 259,
    "preview": "# Logs\nlogs\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\npnpm-debug.log*\nlerna-debug.log*\n\nnode_modules\ndist\ndis"
  },
  {
    "path": ".prettierignore",
    "chars": 282,
    "preview": "# Ignore everything\n/*\n\n# Except these files & folders\n!/src\n!index.html\n!package.json\n!tailwind.config.js\n!tsconfig.jso"
  },
  {
    "path": ".prettierrc",
    "chars": 1118,
    "preview": "{\n  \"arrowParens\": \"always\",\n  \"semi\": false,\n  \"tabWidth\": 2,\n  \"printWidth\": 80,\n  \"singleQuote\": true,\n  \"jsxSingleQu"
  },
  {
    "path": "CHANGELOG.md",
    "chars": 8543,
    "preview": "## v2.2.1 (2025-11-06)\n\n### Fix\n\n- **style**: update data attribute class in authenticated layout (#249)\n- prevent navig"
  },
  {
    "path": "LICENSE",
    "chars": 1066,
    "preview": "MIT License\n\nCopyright (c) 2024 Sat Naing\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\n"
  },
  {
    "path": "README.md",
    "chars": 3765,
    "preview": "# Shadcn Admin Dashboard\n\nAdmin Dashboard UI crafted with Shadcn and Vite. Built with responsiveness and accessibility i"
  },
  {
    "path": "components.json",
    "chars": 431,
    "preview": "{\n  \"$schema\": \"https://ui.shadcn.com/schema.json\",\n  \"style\": \"new-york\",\n  \"rsc\": false,\n  \"tsx\": true,\n  \"tailwind\": "
  },
  {
    "path": "cz.yaml",
    "chars": 154,
    "preview": "---\ncommitizen:\n  name: cz_conventional_commits\n  tag_format: v$version\n  update_changelog_on_bump: true\n  version_provi"
  },
  {
    "path": "eslint.config.js",
    "chars": 1695,
    "preview": "import globals from 'globals'\nimport js from '@eslint/js'\nimport pluginQuery from '@tanstack/eslint-plugin-query'\nimport"
  },
  {
    "path": "index.html",
    "chars": 2359,
    "preview": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <link\n      rel=\"icon\"\n      type=\"image/svg+"
  },
  {
    "path": "knip.config.ts",
    "chars": 212,
    "preview": "import type { KnipConfig } from 'knip';\n\nconst config: KnipConfig = {\n  ignore: ['src/components/ui/**', 'src/routeTree."
  },
  {
    "path": "netlify.toml",
    "chars": 63,
    "preview": "[[redirects]]\n  from = \"/*\"\n  to = \"/index.html\"\n  status = 200"
  },
  {
    "path": "package.json",
    "chars": 2673,
    "preview": "{\n  \"name\": \"shadcn-admin\",\n  \"private\": false,\n  \"version\": \"2.2.1\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vit"
  },
  {
    "path": "src/assets/brand-icons/icon-discord.tsx",
    "chars": 1044,
    "preview": "import { type SVGProps } from 'react'\nimport { cn } from '@/lib/utils'\n\nexport function IconDiscord({ className, ...prop"
  },
  {
    "path": "src/assets/brand-icons/icon-docker.tsx",
    "chars": 1115,
    "preview": "import { type SVGProps } from 'react'\nimport { cn } from '@/lib/utils'\n\nexport function IconDocker({ className, ...props"
  },
  {
    "path": "src/assets/brand-icons/icon-facebook.tsx",
    "chars": 699,
    "preview": "import { type SVGProps } from 'react'\nimport { cn } from '@/lib/utils'\n\nexport function IconFacebook({ className, ...pro"
  },
  {
    "path": "src/assets/brand-icons/icon-figma.tsx",
    "chars": 820,
    "preview": "import { type SVGProps } from 'react'\nimport { cn } from '@/lib/utils'\n\nexport function IconFigma({ className, ...props "
  },
  {
    "path": "src/assets/brand-icons/icon-github.tsx",
    "chars": 915,
    "preview": "import { type SVGProps } from 'react'\nimport { cn } from '@/lib/utils'\n\nexport function IconGithub({ className, ...props"
  },
  {
    "path": "src/assets/brand-icons/icon-gitlab.tsx",
    "chars": 658,
    "preview": "import { type SVGProps } from 'react'\nimport { cn } from '@/lib/utils'\n\nexport function IconGitlab({ className, ...props"
  },
  {
    "path": "src/assets/brand-icons/icon-gmail.tsx",
    "chars": 813,
    "preview": "import { type SVGProps } from 'react'\nimport { cn } from '@/lib/utils'\n\nexport function IconGmail({ className, ...props "
  },
  {
    "path": "src/assets/brand-icons/icon-medium.tsx",
    "chars": 855,
    "preview": "import { type SVGProps } from 'react'\nimport { cn } from '@/lib/utils'\n\nexport function IconMedium({ className, ...props"
  },
  {
    "path": "src/assets/brand-icons/icon-notion.tsx",
    "chars": 947,
    "preview": "import { type SVGProps } from 'react'\nimport { cn } from '@/lib/utils'\n\nexport function IconNotion({ className, ...props"
  },
  {
    "path": "src/assets/brand-icons/icon-skype.tsx",
    "chars": 921,
    "preview": "import { type SVGProps } from 'react'\nimport { cn } from '@/lib/utils'\n\nexport function IconSkype({ className, ...props "
  },
  {
    "path": "src/assets/brand-icons/icon-slack.tsx",
    "chars": 871,
    "preview": "import { type SVGProps } from 'react'\nimport { cn } from '@/lib/utils'\n\nexport function IconSlack({ className, ...props "
  },
  {
    "path": "src/assets/brand-icons/icon-stripe.tsx",
    "chars": 1057,
    "preview": "import { type SVGProps } from 'react'\nimport { cn } from '@/lib/utils'\n\nexport function IconStripe({ className, ...props"
  },
  {
    "path": "src/assets/brand-icons/icon-telegram.tsx",
    "chars": 667,
    "preview": "import { type SVGProps } from 'react'\nimport { cn } from '@/lib/utils'\n\nexport function IconTelegram({ className, ...pro"
  },
  {
    "path": "src/assets/brand-icons/icon-trello.tsx",
    "chars": 768,
    "preview": "import { type SVGProps } from 'react'\nimport { cn } from '@/lib/utils'\n\nexport function IconTrello({ className, ...props"
  },
  {
    "path": "src/assets/brand-icons/icon-whatsapp.tsx",
    "chars": 784,
    "preview": "import { type SVGProps } from 'react'\nimport { cn } from '@/lib/utils'\n\nexport function IconWhatsapp({ className, ...pro"
  },
  {
    "path": "src/assets/brand-icons/icon-zoom.tsx",
    "chars": 850,
    "preview": "import { type SVGProps } from 'react'\nimport { cn } from '@/lib/utils'\n\nexport function IconZoom({ className, ...props }"
  },
  {
    "path": "src/assets/brand-icons/index.ts",
    "chars": 690,
    "preview": "export { IconDiscord } from './icon-discord'\nexport { IconDocker } from './icon-docker'\nexport { IconFacebook } from './"
  },
  {
    "path": "src/assets/clerk-full-logo.tsx",
    "chars": 2380,
    "preview": "import { type SVGProps } from 'react'\n\nexport function ClerkFullLogo(props: SVGProps<SVGSVGElement>) {\n  return (\n    <s"
  },
  {
    "path": "src/assets/clerk-logo.tsx",
    "chars": 1173,
    "preview": "import { type SVGProps } from 'react'\nimport { cn } from '@/lib/utils'\n\nexport function ClerkLogo({ className, ...props "
  },
  {
    "path": "src/assets/custom/icon-dir.tsx",
    "chars": 2615,
    "preview": "import { type SVGProps } from 'react'\nimport { cn } from '@/lib/utils'\nimport { type Direction } from '@/context/directi"
  },
  {
    "path": "src/assets/custom/icon-layout-compact.tsx",
    "chars": 3153,
    "preview": "import { type SVGProps } from 'react'\n\nexport function IconLayoutCompact(props: SVGProps<SVGSVGElement>) {\n  return (\n  "
  },
  {
    "path": "src/assets/custom/icon-layout-default.tsx",
    "chars": 3245,
    "preview": "import { type SVGProps } from 'react'\n\nexport function IconLayoutDefault(props: SVGProps<SVGSVGElement>) {\n  return (\n  "
  },
  {
    "path": "src/assets/custom/icon-layout-full.tsx",
    "chars": 2396,
    "preview": "import { type SVGProps } from 'react'\n\nexport function IconLayoutFull(props: SVGProps<SVGSVGElement>) {\n  return (\n    <"
  },
  {
    "path": "src/assets/custom/icon-sidebar-floating.tsx",
    "chars": 1886,
    "preview": "import { type SVGProps } from 'react'\n\nexport function IconSidebarFloating(props: SVGProps<SVGSVGElement>) {\n  return (\n"
  },
  {
    "path": "src/assets/custom/icon-sidebar-inset.tsx",
    "chars": 1376,
    "preview": "import { type SVGProps } from 'react'\n\nexport function IconSidebarInset(props: SVGProps<SVGSVGElement>) {\n  return (\n   "
  },
  {
    "path": "src/assets/custom/icon-sidebar-sidebar.tsx",
    "chars": 1386,
    "preview": "import { type SVGProps } from 'react'\n\nexport function IconSidebarSidebar(props: SVGProps<SVGSVGElement>) {\n  return (\n "
  },
  {
    "path": "src/assets/custom/icon-theme-dark.tsx",
    "chars": 2445,
    "preview": "import { type SVGProps } from 'react'\n\nexport function IconThemeDark(props: SVGProps<SVGSVGElement>) {\n  return (\n    <s"
  },
  {
    "path": "src/assets/custom/icon-theme-light.tsx",
    "chars": 2547,
    "preview": "import { type SVGProps } from 'react'\n\nexport function IconThemeLight(props: SVGProps<SVGSVGElement>) {\n  return (\n    <"
  },
  {
    "path": "src/assets/custom/icon-theme-system.tsx",
    "chars": 2866,
    "preview": "import { type SVGProps } from 'react'\nimport { cn } from '@/lib/utils'\n\nexport function IconThemeSystem({\n  className,\n "
  },
  {
    "path": "src/assets/logo.tsx",
    "chars": 628,
    "preview": "import { type SVGProps } from 'react'\nimport { cn } from '@/lib/utils'\n\nexport function Logo({ className, ...props }: SV"
  },
  {
    "path": "src/components/coming-soon.tsx",
    "chars": 495,
    "preview": "import { Telescope } from 'lucide-react'\n\nexport function ComingSoon() {\n  return (\n    <div className='h-svh'>\n      <d"
  },
  {
    "path": "src/components/command-menu.tsx",
    "chars": 3264,
    "preview": "import React from 'react'\nimport { useNavigate } from '@tanstack/react-router'\nimport { ArrowRight, ChevronRight, Laptop"
  },
  {
    "path": "src/components/config-drawer.tsx",
    "chars": 9742,
    "preview": "import { type SVGProps } from 'react'\nimport { Root as Radio, Item } from '@radix-ui/react-radio-group'\nimport { CircleC"
  },
  {
    "path": "src/components/confirm-dialog.tsx",
    "chars": 1715,
    "preview": "import { cn } from '@/lib/utils'\nimport {\n  AlertDialog,\n  AlertDialogCancel,\n  AlertDialogContent,\n  AlertDialogDescrip"
  },
  {
    "path": "src/components/data-table/bulk-actions.tsx",
    "chars": 6830,
    "preview": "import { useState, useEffect, useRef } from 'react'\nimport { type Table } from '@tanstack/react-table'\nimport { X } from"
  },
  {
    "path": "src/components/data-table/column-header.tsx",
    "chars": 2262,
    "preview": "import {\n  ArrowDownIcon,\n  ArrowUpIcon,\n  CaretSortIcon,\n  EyeNoneIcon,\n} from '@radix-ui/react-icons'\nimport { type Co"
  },
  {
    "path": "src/components/data-table/faceted-filter.tsx",
    "chars": 4961,
    "preview": "import * as React from 'react'\nimport { CheckIcon, PlusCircledIcon } from '@radix-ui/react-icons'\nimport { type Column }"
  },
  {
    "path": "src/components/data-table/index.ts",
    "chars": 318,
    "preview": "export { DataTablePagination } from './pagination'\nexport { DataTableColumnHeader } from './column-header'\nexport { Data"
  },
  {
    "path": "src/components/data-table/pagination.tsx",
    "chars": 4534,
    "preview": "import {\n  ChevronLeftIcon,\n  ChevronRightIcon,\n  DoubleArrowLeftIcon,\n  DoubleArrowRightIcon,\n} from '@radix-ui/react-i"
  },
  {
    "path": "src/components/data-table/toolbar.tsx",
    "chars": 2563,
    "preview": "import { Cross2Icon } from '@radix-ui/react-icons'\nimport { type Table } from '@tanstack/react-table'\nimport { Button } "
  },
  {
    "path": "src/components/data-table/view-options.tsx",
    "chars": 1657,
    "preview": "import { DropdownMenuTrigger } from '@radix-ui/react-dropdown-menu'\nimport { MixerHorizontalIcon } from '@radix-ui/react"
  },
  {
    "path": "src/components/date-picker.tsx",
    "chars": 1357,
    "preview": "import { format } from 'date-fns'\nimport { Calendar as CalendarIcon } from 'lucide-react'\nimport { Button } from '@/comp"
  },
  {
    "path": "src/components/layout/app-sidebar.tsx",
    "chars": 1108,
    "preview": "import { useLayout } from '@/context/layout-provider'\nimport {\n  Sidebar,\n  SidebarContent,\n  SidebarFooter,\n  SidebarHe"
  },
  {
    "path": "src/components/layout/app-title.tsx",
    "chars": 1624,
    "preview": "import { Link } from '@tanstack/react-router'\nimport { Menu, X } from 'lucide-react'\nimport { cn } from '@/lib/utils'\nim"
  },
  {
    "path": "src/components/layout/authenticated-layout.tsx",
    "chars": 1516,
    "preview": "import { Outlet } from '@tanstack/react-router'\nimport { getCookie } from '@/lib/cookies'\nimport { cn } from '@/lib/util"
  },
  {
    "path": "src/components/layout/data/sidebar-data.ts",
    "chars": 4254,
    "preview": "import {\n  Construction,\n  LayoutDashboard,\n  Monitor,\n  Bug,\n  ListTodo,\n  FileX,\n  HelpCircle,\n  Lock,\n  Bell,\n  Packa"
  },
  {
    "path": "src/components/layout/header.tsx",
    "chars": 1482,
    "preview": "import { useEffect, useState } from 'react'\nimport { cn } from '@/lib/utils'\nimport { Separator } from '@/components/ui/"
  },
  {
    "path": "src/components/layout/main.tsx",
    "chars": 671,
    "preview": "import { cn } from '@/lib/utils'\n\ntype MainProps = React.HTMLAttributes<HTMLElement> & {\n  fixed?: boolean\n  fluid?: boo"
  },
  {
    "path": "src/components/layout/nav-group.tsx",
    "chars": 5674,
    "preview": "import { type ReactNode } from 'react'\nimport { Link, useLocation } from '@tanstack/react-router'\nimport { ChevronRight "
  },
  {
    "path": "src/components/layout/nav-user.tsx",
    "chars": 4194,
    "preview": "import { Link } from '@tanstack/react-router'\nimport {\n  BadgeCheck,\n  Bell,\n  ChevronsUpDown,\n  CreditCard,\n  LogOut,\n "
  },
  {
    "path": "src/components/layout/team-switcher.tsx",
    "chars": 2970,
    "preview": "import * as React from 'react'\nimport { ChevronsUpDown, Plus } from 'lucide-react'\nimport {\n  DropdownMenu,\n  DropdownMe"
  },
  {
    "path": "src/components/layout/top-nav.tsx",
    "chars": 1894,
    "preview": "import { Link } from '@tanstack/react-router'\nimport { Menu } from 'lucide-react'\nimport { cn } from '@/lib/utils'\nimpor"
  },
  {
    "path": "src/components/layout/types.ts",
    "chars": 737,
    "preview": "import { type LinkProps } from '@tanstack/react-router'\n\ntype User = {\n  name: string\n  email: string\n  avatar: string\n}"
  },
  {
    "path": "src/components/learn-more.tsx",
    "chars": 1210,
    "preview": "import { type Root, type Content, type Trigger } from '@radix-ui/react-popover'\nimport { CircleQuestionMark } from 'luci"
  },
  {
    "path": "src/components/long-text.tsx",
    "chars": 2115,
    "preview": "import { useRef, useState } from 'react'\nimport { cn } from '@/lib/utils'\nimport {\n  Popover,\n  PopoverContent,\n  Popove"
  },
  {
    "path": "src/components/navigation-progress.tsx",
    "chars": 582,
    "preview": "import { useEffect, useRef } from 'react'\nimport { useRouterState } from '@tanstack/react-router'\nimport LoadingBar, { t"
  },
  {
    "path": "src/components/password-input.tsx",
    "chars": 1371,
    "preview": "import * as React from 'react'\nimport { Eye, EyeOff } from 'lucide-react'\nimport { cn } from '@/lib/utils'\nimport { Butt"
  },
  {
    "path": "src/components/profile-dropdown.tsx",
    "chars": 2636,
    "preview": "import { Link } from '@tanstack/react-router'\nimport useDialogState from '@/hooks/use-dialog-state'\nimport { Avatar, Ava"
  },
  {
    "path": "src/components/search.tsx",
    "chars": 1219,
    "preview": "import { SearchIcon } from 'lucide-react'\nimport { cn } from '@/lib/utils'\nimport { useSearch } from '@/context/search-p"
  },
  {
    "path": "src/components/select-dropdown.tsx",
    "chars": 1609,
    "preview": "import { Loader } from 'lucide-react'\nimport { cn } from '@/lib/utils'\nimport { FormControl } from '@/components/ui/form"
  },
  {
    "path": "src/components/sign-out-dialog.tsx",
    "chars": 1037,
    "preview": "import { useNavigate, useLocation } from '@tanstack/react-router'\nimport { useAuthStore } from '@/stores/auth-store'\nimp"
  },
  {
    "path": "src/components/skip-to-main.tsx",
    "chars": 384,
    "preview": "export function SkipToMain() {\n  return (\n    <a\n      className={`fixed start-44 z-999 -translate-y-52 bg-primary px-4 "
  },
  {
    "path": "src/components/theme-switch.tsx",
    "chars": 1995,
    "preview": "import { useEffect } from 'react'\nimport { Check, Moon, Sun } from 'lucide-react'\nimport { cn } from '@/lib/utils'\nimpor"
  },
  {
    "path": "src/components/ui/alert-dialog.tsx",
    "chars": 3850,
    "preview": "import * as React from 'react'\nimport * as AlertDialogPrimitive from '@radix-ui/react-alert-dialog'\nimport { cn } from '"
  },
  {
    "path": "src/components/ui/alert.tsx",
    "chars": 1613,
    "preview": "import * as React from 'react'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport { cn } from '@/l"
  },
  {
    "path": "src/components/ui/avatar.tsx",
    "chars": 1082,
    "preview": "import * as React from 'react'\nimport * as AvatarPrimitive from '@radix-ui/react-avatar'\nimport { cn } from '@/lib/utils"
  },
  {
    "path": "src/components/ui/badge.tsx",
    "chars": 1630,
    "preview": "import * as React from 'react'\nimport { Slot } from '@radix-ui/react-slot'\nimport { cva, type VariantProps } from 'class"
  },
  {
    "path": "src/components/ui/button.tsx",
    "chars": 2122,
    "preview": "import * as React from 'react'\nimport { Slot } from '@radix-ui/react-slot'\nimport { cva, type VariantProps } from 'class"
  },
  {
    "path": "src/components/ui/calendar.tsx",
    "chars": 7645,
    "preview": "import * as React from 'react'\nimport {\n  ChevronDownIcon,\n  ChevronLeftIcon,\n  ChevronRightIcon,\n} from 'lucide-react'\n"
  },
  {
    "path": "src/components/ui/card.tsx",
    "chars": 1988,
    "preview": "import * as React from 'react'\nimport { cn } from '@/lib/utils'\n\nfunction Card({ className, ...props }: React.ComponentP"
  },
  {
    "path": "src/components/ui/checkbox.tsx",
    "chars": 1211,
    "preview": "import * as React from 'react'\nimport * as CheckboxPrimitive from '@radix-ui/react-checkbox'\nimport { CheckIcon } from '"
  },
  {
    "path": "src/components/ui/collapsible.tsx",
    "chars": 786,
    "preview": "import * as CollapsiblePrimitive from '@radix-ui/react-collapsible'\n\nfunction Collapsible({\n  ...props\n}: React.Componen"
  },
  {
    "path": "src/components/ui/command.tsx",
    "chars": 4803,
    "preview": "import * as React from 'react'\nimport { Command as CommandPrimitive } from 'cmdk'\nimport { SearchIcon } from 'lucide-rea"
  },
  {
    "path": "src/components/ui/dialog.tsx",
    "chars": 3980,
    "preview": "'use client'\n\nimport * as React from 'react'\nimport * as DialogPrimitive from '@radix-ui/react-dialog'\nimport { XIcon } "
  },
  {
    "path": "src/components/ui/dropdown-menu.tsx",
    "chars": 8271,
    "preview": "import * as React from 'react'\nimport * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu'\nimport { CheckIcon"
  },
  {
    "path": "src/components/ui/form.tsx",
    "chars": 3744,
    "preview": "import * as React from 'react'\nimport {\n  Controller,\n  FormProvider,\n  useFormContext,\n  useFormState,\n  type Controlle"
  },
  {
    "path": "src/components/ui/input-otp.tsx",
    "chars": 2239,
    "preview": "import * as React from 'react'\nimport { OTPInput, OTPInputContext } from 'input-otp'\nimport { MinusIcon } from 'lucide-r"
  },
  {
    "path": "src/components/ui/input.tsx",
    "chars": 966,
    "preview": "import * as React from 'react'\nimport { cn } from '@/lib/utils'\n\nfunction Input({ className, type, ...props }: React.Com"
  },
  {
    "path": "src/components/ui/label.tsx",
    "chars": 610,
    "preview": "'use client'\n\nimport * as React from 'react'\nimport * as LabelPrimitive from '@radix-ui/react-label'\nimport { cn } from "
  },
  {
    "path": "src/components/ui/popover.tsx",
    "chars": 1620,
    "preview": "import * as React from 'react'\nimport * as PopoverPrimitive from '@radix-ui/react-popover'\nimport { cn } from '@/lib/uti"
  },
  {
    "path": "src/components/ui/radio-group.tsx",
    "chars": 1451,
    "preview": "import * as React from 'react'\nimport * as RadioGroupPrimitive from '@radix-ui/react-radio-group'\nimport { CircleIcon } "
  },
  {
    "path": "src/components/ui/scroll-area.tsx",
    "chars": 1873,
    "preview": "import * as React from 'react'\nimport * as ScrollAreaPrimitive from '@radix-ui/react-scroll-area'\nimport { cn } from '@/"
  },
  {
    "path": "src/components/ui/select.tsx",
    "chars": 6236,
    "preview": "import * as React from 'react'\nimport * as SelectPrimitive from '@radix-ui/react-select'\nimport { CheckIcon, ChevronDown"
  },
  {
    "path": "src/components/ui/separator.tsx",
    "chars": 649,
    "preview": "import * as React from 'react'\nimport * as SeparatorPrimitive from '@radix-ui/react-separator'\nimport { cn } from '@/lib"
  },
  {
    "path": "src/components/ui/sheet.tsx",
    "chars": 4070,
    "preview": "import * as React from 'react'\nimport * as SheetPrimitive from '@radix-ui/react-dialog'\nimport { XIcon } from 'lucide-re"
  },
  {
    "path": "src/components/ui/sidebar.tsx",
    "chars": 21874,
    "preview": "import * as React from 'react'\nimport { Slot } from '@radix-ui/react-slot'\nimport { VariantProps, cva } from 'class-vari"
  },
  {
    "path": "src/components/ui/skeleton.tsx",
    "chars": 276,
    "preview": "import { cn } from '@/lib/utils'\n\nfunction Skeleton({ className, ...props }: React.ComponentProps<'div'>) {\n  return (\n "
  },
  {
    "path": "src/components/ui/sonner.tsx",
    "chars": 576,
    "preview": "import { Toaster as Sonner, ToasterProps } from 'sonner'\nimport { useTheme } from '@/context/theme-provider'\n\nexport fun"
  },
  {
    "path": "src/components/ui/switch.tsx",
    "chars": 1217,
    "preview": "import * as React from 'react'\nimport * as SwitchPrimitive from '@radix-ui/react-switch'\nimport { cn } from '@/lib/utils"
  },
  {
    "path": "src/components/ui/table.tsx",
    "chars": 2374,
    "preview": "import * as React from 'react'\nimport { cn } from '@/lib/utils'\n\nfunction Table({ className, ...props }: React.Component"
  },
  {
    "path": "src/components/ui/tabs.tsx",
    "chars": 1954,
    "preview": "import * as React from 'react'\nimport * as TabsPrimitive from '@radix-ui/react-tabs'\nimport { cn } from '@/lib/utils'\n\nf"
  },
  {
    "path": "src/components/ui/textarea.tsx",
    "chars": 758,
    "preview": "import * as React from 'react'\nimport { cn } from '@/lib/utils'\n\nfunction Textarea({ className, ...props }: React.Compon"
  },
  {
    "path": "src/components/ui/tooltip.tsx",
    "chars": 1890,
    "preview": "'use client'\n\nimport * as React from 'react'\nimport * as TooltipPrimitive from '@radix-ui/react-tooltip'\nimport { cn } f"
  },
  {
    "path": "src/config/fonts.ts",
    "chars": 822,
    "preview": "/**\n * List of available font names (visit the url `/settings/appearance`).\n * This array is used to generate dynamic fo"
  },
  {
    "path": "src/context/direction-provider.tsx",
    "chars": 1664,
    "preview": "import { createContext, useContext, useEffect, useState } from 'react'\nimport { DirectionProvider as RdxDirProvider } fr"
  },
  {
    "path": "src/context/font-provider.tsx",
    "chars": 1579,
    "preview": "import { createContext, useContext, useEffect, useState } from 'react'\nimport { fonts } from '@/config/fonts'\nimport { g"
  },
  {
    "path": "src/context/layout-provider.tsx",
    "chars": 2410,
    "preview": "import { createContext, useContext, useState } from 'react'\nimport { getCookie, setCookie } from '@/lib/cookies'\n\nexport"
  },
  {
    "path": "src/context/search-provider.tsx",
    "chars": 1178,
    "preview": "import { createContext, useContext, useEffect, useState } from 'react'\nimport { CommandMenu } from '@/components/command"
  },
  {
    "path": "src/context/theme-provider.tsx",
    "chars": 2877,
    "preview": "import { createContext, useContext, useEffect, useState, useMemo } from 'react'\nimport { getCookie, setCookie, removeCoo"
  },
  {
    "path": "src/features/apps/data/apps.tsx",
    "chars": 2386,
    "preview": "import {\n  IconTelegram,\n  IconNotion,\n  IconFigma,\n  IconTrello,\n  IconSlack,\n  IconZoom,\n  IconStripe,\n  IconGmail,\n  "
  },
  {
    "path": "src/features/apps/index.tsx",
    "chars": 5792,
    "preview": "import { type ChangeEvent, useState } from 'react'\nimport { getRouteApi } from '@tanstack/react-router'\nimport { Sliders"
  },
  {
    "path": "src/features/auth/auth-layout.tsx",
    "chars": 578,
    "preview": "import { Logo } from '@/assets/logo'\n\ntype AuthLayoutProps = {\n  children: React.ReactNode\n}\n\nexport function AuthLayout"
  },
  {
    "path": "src/features/auth/forgot-password/components/forgot-password-form.tsx",
    "chars": 2153,
    "preview": "import { useState } from 'react'\nimport { z } from 'zod'\nimport { useForm } from 'react-hook-form'\nimport { zodResolver "
  },
  {
    "path": "src/features/auth/forgot-password/index.tsx",
    "chars": 1195,
    "preview": "import { Link } from '@tanstack/react-router'\nimport {\n  Card,\n  CardContent,\n  CardDescription,\n  CardFooter,\n  CardHea"
  },
  {
    "path": "src/features/auth/otp/components/otp-form.tsx",
    "chars": 2814,
    "preview": "import { useState } from 'react'\nimport { z } from 'zod'\nimport { useForm } from 'react-hook-form'\nimport { zodResolver "
  },
  {
    "path": "src/features/auth/otp/index.tsx",
    "chars": 1160,
    "preview": "import { Link } from '@tanstack/react-router'\nimport {\n  Card,\n  CardContent,\n  CardDescription,\n  CardFooter,\n  CardHea"
  },
  {
    "path": "src/features/auth/sign-in/components/user-auth-form.tsx",
    "chars": 4450,
    "preview": "import { useState } from 'react'\nimport { z } from 'zod'\nimport { useForm } from 'react-hook-form'\nimport { zodResolver "
  },
  {
    "path": "src/features/auth/sign-in/index.tsx",
    "chars": 1410,
    "preview": "import { useSearch } from '@tanstack/react-router'\nimport {\n  Card,\n  CardContent,\n  CardDescription,\n  CardFooter,\n  Ca"
  },
  {
    "path": "src/features/auth/sign-in/sign-in-2.tsx",
    "chars": 2406,
    "preview": "import { Logo } from '@/assets/logo'\nimport { cn } from '@/lib/utils'\nimport dashboardDark from './assets/dashboard-dark"
  },
  {
    "path": "src/features/auth/sign-up/components/sign-up-form.tsx",
    "chars": 3952,
    "preview": "import { useState } from 'react'\nimport { z } from 'zod'\nimport { useForm } from 'react-hook-form'\nimport { zodResolver "
  },
  {
    "path": "src/features/auth/sign-up/index.tsx",
    "chars": 1548,
    "preview": "import { Link } from '@tanstack/react-router'\nimport {\n  Card,\n  CardContent,\n  CardDescription,\n  CardFooter,\n  CardHea"
  },
  {
    "path": "src/features/chats/components/new-chat.tsx",
    "chars": 4235,
    "preview": "import { useState } from 'react'\nimport { Check, X } from 'lucide-react'\nimport { showSubmittedData } from '@/lib/show-s"
  },
  {
    "path": "src/features/chats/data/chat-types.ts",
    "chars": 154,
    "preview": "import { type conversations } from './convo.json'\n\nexport type ChatUser = (typeof conversations)[number]\nexport type Con"
  },
  {
    "path": "src/features/chats/data/convo.json",
    "chars": 9034,
    "preview": "{\n  \"conversations\": [\n    {\n      \"id\": \"conv1\",\n      \"profile\": \"https://randomuser.me/api/portraits/men/32.jpg\",\n   "
  },
  {
    "path": "src/features/chats/index.tsx",
    "chars": 14376,
    "preview": "import { useState } from 'react'\nimport { Fragment } from 'react/jsx-runtime'\nimport { format } from 'date-fns'\nimport {"
  },
  {
    "path": "src/features/dashboard/components/analytics-chart.tsx",
    "chars": 1877,
    "preview": "import { Area, AreaChart, ResponsiveContainer, XAxis, YAxis } from 'recharts'\n\nconst data = [\n  {\n    name: 'Mon',\n    c"
  },
  {
    "path": "src/features/dashboard/components/analytics.tsx",
    "chars": 6408,
    "preview": "import {\n  Card,\n  CardContent,\n  CardDescription,\n  CardHeader,\n  CardTitle,\n} from '@/components/ui/card'\nimport { Ana"
  },
  {
    "path": "src/features/dashboard/components/overview.tsx",
    "chars": 1712,
    "preview": "import { Bar, BarChart, ResponsiveContainer, XAxis, YAxis } from 'recharts'\n\nconst data = [\n  {\n    name: 'Jan',\n    tot"
  },
  {
    "path": "src/features/dashboard/components/recent-sales.tsx",
    "chars": 3253,
    "preview": "import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar'\n\nexport function RecentSales() {\n  return ("
  },
  {
    "path": "src/features/dashboard/index.tsx",
    "chars": 7931,
    "preview": "import { Button } from '@/components/ui/button'\nimport {\n  Card,\n  CardContent,\n  CardDescription,\n  CardHeader,\n  CardT"
  },
  {
    "path": "src/features/errors/forbidden.tsx",
    "chars": 908,
    "preview": "import { useNavigate, useRouter } from '@tanstack/react-router'\nimport { Button } from '@/components/ui/button'\n\nexport "
  },
  {
    "path": "src/features/errors/general-error.tsx",
    "chars": 1197,
    "preview": "import { useNavigate, useRouter } from '@tanstack/react-router'\nimport { cn } from '@/lib/utils'\nimport { Button } from "
  },
  {
    "path": "src/features/errors/maintenance-error.tsx",
    "chars": 674,
    "preview": "import { Button } from '@/components/ui/button'\n\nexport function MaintenanceError() {\n  return (\n    <div className='h-s"
  },
  {
    "path": "src/features/errors/not-found-error.tsx",
    "chars": 938,
    "preview": "import { useNavigate, useRouter } from '@tanstack/react-router'\nimport { Button } from '@/components/ui/button'\n\nexport "
  },
  {
    "path": "src/features/errors/unauthorized-error.tsx",
    "chars": 927,
    "preview": "import { useNavigate, useRouter } from '@tanstack/react-router'\nimport { Button } from '@/components/ui/button'\n\nexport "
  },
  {
    "path": "src/features/settings/account/account-form.tsx",
    "chars": 5624,
    "preview": "import { z } from 'zod'\nimport { useForm } from 'react-hook-form'\nimport { CaretSortIcon, CheckIcon } from '@radix-ui/re"
  },
  {
    "path": "src/features/settings/account/index.tsx",
    "chars": 349,
    "preview": "import { ContentSection } from '../components/content-section'\nimport { AccountForm } from './account-form'\n\nexport func"
  },
  {
    "path": "src/features/settings/appearance/appearance-form.tsx",
    "chars": 6602,
    "preview": "import { z } from 'zod'\nimport { useForm } from 'react-hook-form'\nimport { ChevronDownIcon } from '@radix-ui/react-icons"
  },
  {
    "path": "src/features/settings/appearance/index.tsx",
    "chars": 380,
    "preview": "import { ContentSection } from '../components/content-section'\nimport { AppearanceForm } from './appearance-form'\n\nexpor"
  },
  {
    "path": "src/features/settings/components/content-section.tsx",
    "chars": 687,
    "preview": "import { Separator } from '@/components/ui/separator'\n\ntype ContentSectionProps = {\n  title: string\n  desc: string\n  chi"
  },
  {
    "path": "src/features/settings/components/sidebar-nav.tsx",
    "chars": 2375,
    "preview": "import { useState, type JSX } from 'react'\nimport { useLocation, useNavigate, Link } from '@tanstack/react-router'\nimpor"
  },
  {
    "path": "src/features/settings/display/display-form.tsx",
    "chars": 3297,
    "preview": "import { z } from 'zod'\nimport { useForm } from 'react-hook-form'\nimport { zodResolver } from '@hookform/resolvers/zod'\n"
  },
  {
    "path": "src/features/settings/display/index.tsx",
    "chars": 328,
    "preview": "import { ContentSection } from '../components/content-section'\nimport { DisplayForm } from './display-form'\n\nexport func"
  },
  {
    "path": "src/features/settings/index.tsx",
    "chars": 2113,
    "preview": "import { Outlet } from '@tanstack/react-router'\nimport { Monitor, Bell, Palette, Wrench, UserCog } from 'lucide-react'\ni"
  },
  {
    "path": "src/features/settings/notifications/index.tsx",
    "chars": 338,
    "preview": "import { ContentSection } from '../components/content-section'\nimport { NotificationsForm } from './notifications-form'\n"
  },
  {
    "path": "src/features/settings/notifications/notifications-form.tsx",
    "chars": 7967,
    "preview": "import { z } from 'zod'\nimport { useForm } from 'react-hook-form'\nimport { zodResolver } from '@hookform/resolvers/zod'\n"
  },
  {
    "path": "src/features/settings/profile/index.tsx",
    "chars": 312,
    "preview": "import { ContentSection } from '../components/content-section'\nimport { ProfileForm } from './profile-form'\n\nexport func"
  },
  {
    "path": "src/features/settings/profile/profile-form.tsx",
    "chars": 5364,
    "preview": "import { z } from 'zod'\nimport { useFieldArray, useForm } from 'react-hook-form'\nimport { zodResolver } from '@hookform/"
  },
  {
    "path": "src/features/tasks/components/data-table-bulk-actions.tsx",
    "chars": 6201,
    "preview": "import { useState } from 'react'\nimport { type Table } from '@tanstack/react-table'\nimport { Trash2, CircleArrowUp, Arro"
  },
  {
    "path": "src/features/tasks/components/data-table-row-actions.tsx",
    "chars": 2491,
    "preview": "import { DotsHorizontalIcon } from '@radix-ui/react-icons'\nimport { type Row } from '@tanstack/react-table'\nimport { Tra"
  },
  {
    "path": "src/features/tasks/components/tasks-columns.tsx",
    "chars": 3429,
    "preview": "import { type ColumnDef } from '@tanstack/react-table'\nimport { Badge } from '@/components/ui/badge'\nimport { Checkbox }"
  },
  {
    "path": "src/features/tasks/components/tasks-dialogs.tsx",
    "chars": 2051,
    "preview": "import { showSubmittedData } from '@/lib/show-submitted-data'\nimport { ConfirmDialog } from '@/components/confirm-dialog"
  },
  {
    "path": "src/features/tasks/components/tasks-import-dialog.tsx",
    "chars": 2808,
    "preview": "import { z } from 'zod'\nimport { useForm } from 'react-hook-form'\nimport { zodResolver } from '@hookform/resolvers/zod'\n"
  },
  {
    "path": "src/features/tasks/components/tasks-multi-delete-dialog.tsx",
    "chars": 2654,
    "preview": "'use client'\n\nimport { useState } from 'react'\nimport { type Table } from '@tanstack/react-table'\nimport { AlertTriangle"
  },
  {
    "path": "src/features/tasks/components/tasks-mutate-drawer.tsx",
    "chars": 7182,
    "preview": "import { z } from 'zod'\nimport { useForm } from 'react-hook-form'\nimport { zodResolver } from '@hookform/resolvers/zod'\n"
  },
  {
    "path": "src/features/tasks/components/tasks-primary-buttons.tsx",
    "chars": 594,
    "preview": "import { Download, Plus } from 'lucide-react'\nimport { Button } from '@/components/ui/button'\nimport { useTasks } from '"
  },
  {
    "path": "src/features/tasks/components/tasks-provider.tsx",
    "chars": 1087,
    "preview": "import React, { useState } from 'react'\nimport useDialogState from '@/hooks/use-dialog-state'\nimport { type Task } from "
  },
  {
    "path": "src/features/tasks/components/tasks-table.tsx",
    "chars": 6346,
    "preview": "import { useEffect, useState } from 'react'\nimport { getRouteApi } from '@tanstack/react-router'\nimport {\n  type Sorting"
  },
  {
    "path": "src/features/tasks/data/data.tsx",
    "chars": 1123,
    "preview": "import {\n  ArrowDown,\n  ArrowRight,\n  ArrowUp,\n  Circle,\n  CheckCircle,\n  AlertCircle,\n  Timer,\n  HelpCircle,\n  CircleOf"
  },
  {
    "path": "src/features/tasks/data/schema.ts",
    "chars": 325,
    "preview": "import { z } from 'zod'\n\n// We're keeping a simple non-relational schema here.\n// IRL, you will have a schema for your d"
  },
  {
    "path": "src/features/tasks/data/tasks.ts",
    "chars": 883,
    "preview": "import { faker } from '@faker-js/faker'\n\n// Set a fixed seed for consistent data generation\nfaker.seed(12345)\n\nexport co"
  },
  {
    "path": "src/features/tasks/index.tsx",
    "chars": 1400,
    "preview": "import { ConfigDrawer } from '@/components/config-drawer'\nimport { Header } from '@/components/layout/header'\nimport { M"
  },
  {
    "path": "src/features/users/components/data-table-bulk-actions.tsx",
    "chars": 4479,
    "preview": "import { useState } from 'react'\nimport { type Table } from '@tanstack/react-table'\nimport { Trash2, UserX, UserCheck, M"
  },
  {
    "path": "src/features/users/components/data-table-row-actions.tsx",
    "chars": 1851,
    "preview": "import { DotsHorizontalIcon } from '@radix-ui/react-icons'\nimport { type Row } from '@tanstack/react-table'\nimport { Tra"
  },
  {
    "path": "src/features/users/components/users-action-dialog.tsx",
    "chars": 10698,
    "preview": "'use client'\n\nimport { z } from 'zod'\nimport { useForm } from 'react-hook-form'\nimport { zodResolver } from '@hookform/r"
  },
  {
    "path": "src/features/users/components/users-columns.tsx",
    "chars": 4021,
    "preview": "import { type ColumnDef } from '@tanstack/react-table'\nimport { cn } from '@/lib/utils'\nimport { Badge } from '@/compone"
  },
  {
    "path": "src/features/users/components/users-delete-dialog.tsx",
    "chars": 2326,
    "preview": "'use client'\n\nimport { useState } from 'react'\nimport { AlertTriangle } from 'lucide-react'\nimport { showSubmittedData }"
  },
  {
    "path": "src/features/users/components/users-dialogs.tsx",
    "chars": 1345,
    "preview": "import { UsersActionDialog } from './users-action-dialog'\nimport { UsersDeleteDialog } from './users-delete-dialog'\nimpo"
  },
  {
    "path": "src/features/users/components/users-invite-dialog.tsx",
    "chars": 4352,
    "preview": "import { z } from 'zod'\nimport { useForm } from 'react-hook-form'\nimport { zodResolver } from '@hookform/resolvers/zod'\n"
  },
  {
    "path": "src/features/users/components/users-multi-delete-dialog.tsx",
    "chars": 2654,
    "preview": "'use client'\n\nimport { useState } from 'react'\nimport { type Table } from '@tanstack/react-table'\nimport { AlertTriangle"
  },
  {
    "path": "src/features/users/components/users-primary-buttons.tsx",
    "chars": 606,
    "preview": "import { MailPlus, UserPlus } from 'lucide-react'\nimport { Button } from '@/components/ui/button'\nimport { useUsers } fr"
  },
  {
    "path": "src/features/users/components/users-provider.tsx",
    "chars": 1082,
    "preview": "import React, { useState } from 'react'\nimport useDialogState from '@/hooks/use-dialog-state'\nimport { type User } from "
  },
  {
    "path": "src/features/users/components/users-table.tsx",
    "chars": 6385,
    "preview": "import { useEffect, useState } from 'react'\nimport {\n  type SortingState,\n  type VisibilityState,\n  flexRender,\n  getCor"
  },
  {
    "path": "src/features/users/data/data.ts",
    "chars": 843,
    "preview": "import { Shield, UserCheck, Users, CreditCard } from 'lucide-react'\nimport { type UserStatus } from './schema'\n\nexport c"
  },
  {
    "path": "src/features/users/data/schema.ts",
    "chars": 735,
    "preview": "import { z } from 'zod'\n\nconst userStatusSchema = z.union([\n  z.literal('active'),\n  z.literal('inactive'),\n  z.literal("
  },
  {
    "path": "src/features/users/data/users.ts",
    "chars": 868,
    "preview": "import { faker } from '@faker-js/faker'\n\n// Set a fixed seed for consistent data generation\nfaker.seed(67890)\n\nexport co"
  },
  {
    "path": "src/features/users/index.tsx",
    "chars": 1612,
    "preview": "import { getRouteApi } from '@tanstack/react-router'\nimport { ConfigDrawer } from '@/components/config-drawer'\nimport { "
  },
  {
    "path": "src/hooks/use-dialog-state.tsx",
    "chars": 538,
    "preview": "import { useState } from 'react'\n\n/**\n * Custom hook for confirm dialog\n * @param initialState string | null\n * @returns"
  },
  {
    "path": "src/hooks/use-mobile.tsx",
    "chars": 455,
    "preview": "import * as React from 'react'\n\nconst MOBILE_BREAKPOINT = 768\nconst MOBILE_QUERY = `(max-width: ${MOBILE_BREAKPOINT - 1}"
  },
  {
    "path": "src/hooks/use-table-url-state.ts",
    "chars": 6719,
    "preview": "import { useMemo, useState } from 'react'\nimport type {\n  ColumnFiltersState,\n  OnChangeFn,\n  PaginationState,\n} from '@"
  },
  {
    "path": "src/lib/cookies.ts",
    "chars": 1043,
    "preview": "/**\n * Cookie utility functions using manual document.cookie approach\n * Replaces js-cookie dependency for better consis"
  },
  {
    "path": "src/lib/handle-server-error.ts",
    "chars": 484,
    "preview": "import { AxiosError } from 'axios'\nimport { toast } from 'sonner'\n\nexport function handleServerError(error: unknown) {\n "
  },
  {
    "path": "src/lib/show-submitted-data.tsx",
    "chars": 390,
    "preview": "import { toast } from 'sonner'\n\nexport function showSubmittedData(\n  data: unknown,\n  title: string = 'You submitted the"
  },
  {
    "path": "src/lib/utils.ts",
    "chars": 1798,
    "preview": "import { type ClassValue, clsx } from 'clsx'\nimport { twMerge } from 'tailwind-merge'\n\nexport function cn(...inputs: Cla"
  },
  {
    "path": "src/main.tsx",
    "chars": 3169,
    "preview": "import { StrictMode } from 'react'\nimport ReactDOM from 'react-dom/client'\nimport { AxiosError } from 'axios'\nimport {\n "
  },
  {
    "path": "src/routeTree.gen.ts",
    "chars": 26785,
    "preview": "/* eslint-disable */\n\n// @ts-nocheck\n\n// noinspection JSUnusedGlobalSymbols\n\n// This file was automatically generated by"
  },
  {
    "path": "src/routes/(auth)/forgot-password.tsx",
    "chars": 221,
    "preview": "import { createFileRoute } from '@tanstack/react-router'\nimport { ForgotPassword } from '@/features/auth/forgot-password"
  },
  {
    "path": "src/routes/(auth)/otp.tsx",
    "chars": 175,
    "preview": "import { createFileRoute } from '@tanstack/react-router'\nimport { Otp } from '@/features/auth/otp'\n\nexport const Route ="
  }
]

// ... and 38 more files (download for full content)

About this extraction

This page contains the full source code of the satnaing/shadcn-admin GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 238 files (525.1 KB), approximately 141.8k tokens, and a symbol index with 435 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!