[
  {
    "path": ".dockerignore",
    "content": "node_modules\n.github\ndist\n.env*\n*.log \n.git\n.gitignore\n"
  },
  {
    "path": ".github/CODEOWNERS",
    "content": "* @inkonchain/developers-secret\n"
  },
  {
    "path": ".github/README.md",
    "content": "<img src=\"../src/images/banner.webp\" alt=\"Ink Kit Banner\" style=\"width: 100%; border-radius: 8px; margin-bottom: 2rem;\" />\n\n# Ink Kit\n\n> **Looking for React UI components?** The ecosystem has matured significantly with excellent options like [shadcn/ui](https://ui.shadcn.com/), [Radix UI](https://www.radix-ui.com/), [Chakra UI](https://chakra-ui.com/), and [Mantine](https://mantine.dev/). For wallet connectivity specifically, check out [RainbowKit](https://www.rainbowkit.com/) or [ConnectKit](https://docs.family.co/connectkit).\n\n---\n\n## About This Project\n\nInk Kit is a React component library that provided UI components, app layouts, and themes, plus a wallet connection component built on wagmi. Modern alternatives now offer better maintained solutions for both general UI and web3-specific needs.\n\n## Installation\n\nIf you're maintaining an existing project using Ink Kit:\n\n```bash\nnpm install @inkonchain/ink-kit@0.9.1-beta.19\n# or\npnpm install @inkonchain/ink-kit@0.9.1-beta.19\n```\n\n## Usage\n\n```tsx\n// Import styles first at the root of your project (required)\nimport \"@inkonchain/ink-kit/style.css\";\n```\n\n```tsx\n// Import components as needed\nimport { Button } from \"@inkonchain/ink-kit\";\n\nfunction App() {\n  return (\n    <div>\n      <Button onClick={() => {}} size=\"md\" variant=\"secondary\">\n        Ship It\n      </Button>\n    </div>\n  );\n}\n```\n\nNote: Ink Kit classes are prefixed with `ink:` and can be customized using CSS variables instead of Tailwind classes. They should be imported first so that your own custom classes are taking precedence.\n\n## Key Features\n\n- 🎨 **Customizable app layout templates**\n- ✨ **Magical animated components**\n- 🎭 **Vibrant themes**\n- ⛓️ **Onchain-focused development**\n- 🚀 **Efficient developer experience**\n- 📱 **Polished, engaging interfaces**\n\n## Theming\n\nBy default, Ink Kit provides a couple of themes already in the stylesheet:\n\n- Light (`light-theme`)\n- Dark (`dark-theme`)\n- Contrast (`contrast-theme`)\n- Neo (`neo-theme`)\n- Morpheus (`morpheus-theme`)\n\nTo specify which theme to use, add the `ink:THEME_ID` to your document root:\n\n```tsx\n<html class=\"ink:dark-theme\">\n  ...\n```\n\nIf you want to programmatically set this value, you can use the `useInkThemeClass`:\n\n```tsx\nconst theme = getMyCurrentTheme();\nuseInkThemeClass(theme === \"light\" ? \"ink:neo-theme\" : \"ink:dark-theme\");\n```\n\n### Custom Theme\n\nTo create a custom theme, you can override CSS variables:\n\n```css\n:root {\n  --ink-button-primary: rgb(10, 55, 10);\n  ...\n}\n```\n\nTo see examples on specific colors that you can override, check the following [theme](https://github.com/inkonchain/ink-kit/tree/main/src/styles/theme) section of the Ink Kit repository.\n\n## Resources\n\n- **Storybook Documentation**: [ink-kit.inkonchain.com](https://ink-kit.inkonchain.com/)\n- **NPM Package**: [@inkonchain/ink-kit](https://www.npmjs.com/package/@inkonchain/ink-kit)\n\n---\n\nThis repository was archived in October 2025. The code remains available under the MIT license for anyone who wishes to reference or fork it.\n"
  },
  {
    "path": ".github/actions/base-setup/action.yaml",
    "content": "name: \"Basic Setup\"\ndescription: \"Basic setup with pnpm and cache restore\"\nruns:\n  using: \"composite\"\n  steps:\n    - name: Setup pnpm\n      uses: pnpm/action-setup@v4\n      with:\n        run_install: false\n\n    - name: Setup Node 22\n      uses: actions/setup-node@v4\n      with:\n        node-version: \"22.x\"\n        cache: \"pnpm\"\n\n    - name: Add pnpm store path to env var\n      id: pnpm-cache\n      shell: bash\n      run: echo \"STORE_PATH=$(pnpm store path)\" >> $GITHUB_OUTPUT\n\n    - name: Restore Cache\n      uses: actions/cache/restore@v4\n      with:\n        path: |\n          ${{ steps.pnpm-cache.outputs.STORE_PATH }}\n          **/node_modules\n        key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}\n        restore-keys: |\n          ${{ runner.os }}-pnpm-store-\n"
  },
  {
    "path": ".github/dependabot.yml",
    "content": "# To get started with Dependabot version updates, you'll need to specify which\n# package ecosystems to update and where the package manifests are located.\n# Please see the documentation for more information:\n# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates\n# https://containers.dev/guide/dependabot\n\nversion: 2\nupdates:\n - package-ecosystem: \"devcontainers\"\n   directory: \"/\"\n   schedule:\n     interval: weekly\n"
  },
  {
    "path": ".github/workflows/pull_request.yml",
    "content": "name: PR Checks\non:\n  pull_request:\n  push:\n    branches:\n      - main\n\njobs:\n  install_modules:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n      - uses: pnpm/action-setup@v4\n        with:\n          run_install: false\n      - uses: actions/setup-node@v4\n        with:\n          node-version: \"22.x\"\n          cache: \"pnpm\"\n      - name: Install dependencies\n        run: pnpm install --frozen-lockfile\n      - name: Add pnpm store path to env var\n        id: pnpm-cache\n        shell: bash\n        run: echo \"STORE_PATH=$(pnpm store path)\" >> $GITHUB_OUTPUT\n      - name: Cache node modules\n        uses: actions/cache/save@v4\n        with:\n          path: |\n            ${{ steps.pnpm-cache.outputs.STORE_PATH }}\n            **/node_modules\n          key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}\n\n  lint:\n    needs: install_modules\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n      - uses: ./.github/actions/base-setup\n        name: Base Setup\n      - name: Run linting\n        run: pnpm run lint\n\n  format:\n    needs: install_modules\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n      - uses: ./.github/actions/base-setup\n        name: Base Setup\n      - name: Run formatting\n        run: pnpm run format:check\n\n  build:\n    needs: install_modules\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n      - uses: ./.github/actions/base-setup\n        name: Base Setup\n      - name: Debug Environment Variables\n        run: env\n      - name: Building app\n        run: pnpm run build\n      - name: Cache build\n        uses: actions/cache/save@v4\n        with:\n          path: apps/web/.next\n          key: ${{ runner.os }}-build-store-${{ hashFiles('./apps/web/src') }}\n\n  docker-publish:\n    if: github.ref == 'refs/heads/main'\n    runs-on: ubuntu-latest\n    needs: build\n    steps:\n      - name: Checkout code\n        uses: actions/checkout@v4\n\n      - name: Set up Docker Buildx\n        uses: docker/setup-buildx-action@v2\n\n      - name: Log in to GitHub Container Registry\n        uses: docker/login-action@v2\n        with:\n          registry: ghcr.io\n          username: ${{ github.actor }}\n          password: ${{ secrets.GITHUB_TOKEN }}\n\n      - name: Build and push Docker image\n        uses: docker/build-push-action@v5\n        with:\n          context: .\n          push: true\n          tags: ghcr.io/inkonchain/ink-kit:latest\n\n      - name: Log out from GitHub Container Registry\n        run: docker logout ghcr.io\n"
  },
  {
    "path": ".github/workflows/securesdlc.yml",
    "content": "name: Nautilus SecureSDLC\nrun-name: \"[Nautilus SecureSDLC] Ref:${{ github.ref_name }} Event:${{ github.event_name }}\"\n\non:\n  workflow_dispatch: {}\n  workflow_call:\n    secrets:\n      SEMGREP_APP_URL:\n        required: true\n      SEMGREP_APP_TOKEN:\n        required: true\n  push:\n    branches: [ main ]\n\njobs:\n  securesdlc-umbrella:\n    permissions:\n      contents: read # for actions/checkout to fetch code\n      security-events: write # for github/codeql-action/upload-sarif to upload SARIF results\n      actions: read # only required for a private repository by github/codeql-action/upload-sarif to get the Action run status  \n    uses: nautilus-wraith/securesdlc-umbrella/.github/workflows/securesdlc-umbrella.yml@release-stable\n    secrets:\n      SEMGREP_APP_URL: ${{ secrets.SEMGREP_APP_URL }}\n      SEMGREP_APP_TOKEN: ${{ secrets.SEMGREP_APP_TOKEN }}\n"
  },
  {
    "path": ".gitignore",
    "content": ".DS_Store\ndist\nnode_modules\n*storybook.log\nstorybook-static\n"
  },
  {
    "path": ".prettierrc",
    "content": "{\n  \"trailingComma\": \"es5\",\n  \"tabWidth\": 2,\n  \"semi\": true,\n  \"singleQuote\": false\n}\n"
  },
  {
    "path": ".storybook/main.ts",
    "content": "import type { StorybookConfig } from \"@storybook/react-vite\";\n\nconst config: StorybookConfig = {\n  stories: [\"../src/**/*.mdx\", \"../src/**/*.stories.@(js|jsx|mjs|ts|tsx)\"],\n  addons: [\n    \"@storybook/addon-essentials\",\n    \"@chromatic-com/storybook\",\n    \"@storybook/addon-interactions\",\n    \"@storybook/addon-themes\",\n  ],\n  framework: {\n    name: \"@storybook/react-vite\",\n    options: {},\n  },\n  typescript: {\n    reactDocgen: \"react-docgen-typescript\",\n  },\n  staticDirs: [\"./public\"],\n};\nexport default config;\n"
  },
  {
    "path": ".storybook/preview-head.html",
    "content": "<link rel=\"icon\" type=\"image/x-icon\" href=\"favicon.ico\" />\n"
  },
  {
    "path": ".storybook/preview.ts",
    "content": "import type { Preview, ReactRenderer } from \"@storybook/react\";\nimport { withThemeByClassName } from \"@storybook/addon-themes\";\n\nimport \"../src/tailwind.css\";\nimport \"./theme.css\";\n\nconst preview: Preview = {\n  parameters: {\n    layout: \"centered\",\n    backgrounds: {\n      default: \"dark-background\",\n      values: [\n        {\n          name: \"dark-background\",\n          value: \"var(--ink-background-dark)\",\n        },\n        {\n          name: \"light-background\",\n          value: \"var(--ink-background-light)\",\n        },\n      ],\n    },\n    controls: {\n      matchers: {\n        color: /(background|color)$/i,\n        date: /Date$/i,\n      },\n    },\n    options: {\n      storySort: {\n        order: [\"Welcome\", \"*\"],\n      },\n    },\n  },\n  decorators: [\n    withThemeByClassName<ReactRenderer>({\n      themes: {\n        light: \"ink:light-theme\",\n        dark: \"ink:dark-theme\",\n        contrast: \"ink:contrast-theme\",\n        neo: \"ink:neo-theme\",\n        morpheus: \"ink:morpheus-theme\",\n      },\n      defaultTheme: \"light\",\n    }),\n  ],\n};\n\nexport default preview;\n"
  },
  {
    "path": ".storybook/theme.css",
    "content": ".docs-story,\n.sb-show-main {\n  background-color: var(--ink-background-dark);\n}\n\n.sb-main-fullscreen {\n  height: 100%;\n\n  #storybook-root {\n    height: 100%;\n  }\n}\n\nhtml,\nbody {\n  height: 100%;\n}\n"
  },
  {
    "path": ".vscode/settings.json",
    "content": "{\n  // Enables tailwind autocompletion in cva function\n  // https://cva.style/docs/getting-started/installation#tailwind-css\n  \"tailwindCSS.experimental.classRegex\": [\n    [\"cva\\\\(((?:[^()]|\\\\([^()]*\\\\))*)\\\\)\", \"[\\\"'`]([^\\\"'`]*).*?[\\\"'`]\"],\n    [\"cx\\\\(((?:[^()]|\\\\([^()]*\\\\))*)\\\\)\", \"(?:'|\\\"|`)([^']*)(?:'|\\\"|`)\"]\n  ]\n}\n"
  },
  {
    "path": "Dockerfile",
    "content": "FROM node:22-alpine\nRUN corepack enable && corepack prepare pnpm@9.3.0 --activate\nWORKDIR /app\n\n# Install Python and build dependencies\nRUN apk add --no-cache python3 make g++ gcc\n\nCOPY package.json pnpm-lock.yaml ./\nRUN pnpm install --frozen-lockfile\nCOPY . .\nRUN pnpm build-storybook\n\n# Use official Nginx image as base\nFROM nginx:alpine\n\n# Copy Storybook static files from the build stage\nCOPY --from=0 /app/storybook-static/ /usr/share/nginx/html\n\n# Expose port 80 (Nginx default)\nEXPOSE 80\n\n# Start Nginx\nCMD [\"nginx\", \"-g\", \"daemon off;\"]\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2024-2025 inkonchain\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "# Ink Kit\n\n> **Looking for React UI components?** The ecosystem has matured significantly with excellent options like [shadcn/ui](https://ui.shadcn.com/), [Radix UI](https://www.radix-ui.com/), [Chakra UI](https://chakra-ui.com/), and [Mantine](https://mantine.dev/). For wallet connectivity specifically, check out [RainbowKit](https://www.rainbowkit.com/) or [ConnectKit](https://docs.family.co/connectkit).\n\n---\n\n## About This Project\n\nInk Kit is a React component library that provided UI components, app layouts, and themes, plus a wallet connection component built on wagmi. Modern alternatives now offer better maintained solutions for both general UI and web3-specific needs.\n\n## Using This Library\n\nIf you're maintaining an existing project using Ink Kit, the package remains available:\n\n```bash\nnpm install @inkonchain/ink-kit@0.9.1-beta.19\n```\n\n**Resources:**\n\n- [Storybook Documentation](https://ink-kit.inkonchain.com/)\n- [GitHub Repository](https://github.com/inkonchain/ink-kit)\n- [NPM Package](https://www.npmjs.com/package/@inkonchain/ink-kit)\n\n---\n\nThis repository was archived in October 2025. The code remains available under the MIT license for anyone who wishes to reference or fork it.\n"
  },
  {
    "path": "amplify.yml",
    "content": "version: 1\napplications:\n  - frontend:\n      phases:\n        preBuild:\n          commands:\n            - npm install -g pnpm@9.11.0\n        build:\n          commands:\n            - pnpm install\n            - pnpm run build-storybook\n      artifacts:\n        baseDirectory: storybook-static\n        files:\n          - \"**/*\"\n      cache:\n        paths:\n          - node_modules/**/*\n          - .pnpm-store/**/*\n"
  },
  {
    "path": "eslint.config.mjs",
    "content": "import { FlatCompat } from \"@eslint/eslintrc\";\nimport js from \"@eslint/js\";\nimport importsPlugin from \"eslint-plugin-import\";\nimport eslintPluginPrettierRecommended from \"eslint-plugin-prettier/recommended\";\nimport reactHooksPlugin from \"eslint-plugin-react-hooks\";\nimport simpleImportSort from \"eslint-plugin-simple-import-sort\";\nimport unusedImports from \"eslint-plugin-unused-imports\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = path.dirname(__filename);\nconst compat = new FlatCompat({\n  baseDirectory: __dirname,\n  recommendedConfig: js.configs.recommended,\n  allConfig: js.configs.all,\n});\n\nexport default [\n  {\n    ignores: [\"dist\", \"storybook-static\"],\n  },\n  ...compat.extends(),\n  eslintPluginPrettierRecommended,\n  {\n    plugins: {\n      \"simple-import-sort\": simpleImportSort,\n      \"unused-imports\": unusedImports,\n      \"react-hooks\": reactHooksPlugin,\n      import: importsPlugin,\n    },\n\n    rules: {\n      \"react-hooks/exhaustive-deps\": \"error\",\n\n      \"import/newline-after-import\": [\n        \"error\",\n        {\n          count: 1,\n        },\n      ],\n\n      \"unused-imports/no-unused-imports\": \"error\",\n\n      \"simple-import-sort/imports\": [\n        \"error\",\n        {\n          groups: [\n            [\"^react\", \"^@?\\\\w\"],\n            [\"^(@)(/.*|$)\"],\n            [\"^\\\\u0000\"],\n            [\"^\\\\.\\\\.(?!/?$)\", \"^\\\\.\\\\./?$\"],\n            [\"^\\\\./(?=.*/)(?!/?$)\", \"^\\\\.(?!/?$)\", \"^\\\\./?$\"],\n            [\"^.+\\\\.?(css)$\"],\n          ],\n        },\n      ],\n\n      \"simple-import-sort/exports\": \"error\",\n    },\n  },\n];\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"@inkonchain/ink-kit\",\n  \"version\": \"0.9.1-beta.19\",\n  \"description\": \"React component library for onchain applications - See README for modern alternatives\",\n  \"main\": \"dist/index.cjs.js\",\n  \"module\": \"dist/index.es.js\",\n  \"types\": \"dist/index.d.ts\",\n  \"files\": [\n    \"/dist\"\n  ],\n  \"exports\": {\n    \".\": {\n      \"types\": \"./dist/index.d.ts\",\n      \"import\": \"./dist/index.es.js\",\n      \"require\": \"./dist/index.cjs.js\"\n    },\n    \"./providers.index.ts\": {\n      \"types\": \"./dist/providers.d.ts\",\n      \"import\": \"./dist/providers.es.js\",\n      \"require\": \"./dist/providers.cjs.js\"\n    },\n    \"./style.css\": \"./dist/style.css\",\n    \"./tailwind.css\": \"./dist/tailwind.css\"\n  },\n  \"scripts\": {\n    \"build\": \"tsc && vite build --mode production\",\n    \"storybook\": \"storybook dev -p 6006\",\n    \"build-storybook\": \"storybook build\",\n    \"lint\": \"eslint\",\n    \"lint:fix\": \"eslint --fix\",\n    \"format\": \"prettier --write \\\"**/*.{ts,tsx,md,mdx,css,scss}\\\"\",\n    \"format:check\": \"prettier --check \\\"**/*.{ts,tsx,md,mdx,css,scss}\\\"\",\n    \"test\": \"playwright test\",\n    \"fix:all\": \"pnpm run lint:fix && pnpm run format\",\n    \"prepublishOnly\": \"pnpm run build\",\n    \"import-svgs\": \"node scripts/import-svgs.mjs\"\n  },\n  \"keywords\": [],\n  \"author\": \"\",\n  \"license\": \"MIT\",\n  \"devDependencies\": {\n    \"@chromatic-com/storybook\": \"^3.2.2\",\n    \"@storybook/addon-essentials\": \"8.2.9\",\n    \"@storybook/addon-interactions\": \"8.2.9\",\n    \"@storybook/addon-themes\": \"8.2.9\",\n    \"@storybook/blocks\": \"8.2.9\",\n    \"@storybook/react\": \"8.2.9\",\n    \"@storybook/react-vite\": \"8.2.9\",\n    \"@storybook/test\": \"8.2.9\",\n    \"@tailwindcss/postcss\": \"4.0.0-beta.3\",\n    \"@tailwindcss/vite\": \"4.0.0-beta.3\",\n    \"@tanstack/react-query\": \"^5.60.5\",\n    \"@types/react\": \"19.0.8\",\n    \"@types/react-dom\": \"19.0.3\",\n    \"eslint\": \"^9.14.0\",\n    \"eslint-config-prettier\": \"^9.1.0\",\n    \"eslint-plugin-import\": \"^2.31.0\",\n    \"eslint-plugin-prettier\": \"^5.2.1\",\n    \"eslint-plugin-react-hooks\": \"^5.0.0\",\n    \"eslint-plugin-simple-import-sort\": \"^12.1.1\",\n    \"eslint-plugin-unused-imports\": \"^4.1.4\",\n    \"postcss\": \"^8.4.47\",\n    \"prettier\": \"^3.3.3\",\n    \"react\": \"19.0.0\",\n    \"react-dom\": \"19.0.0\",\n    \"rollup-plugin-preserve-use-client\": \"^3.0.1\",\n    \"storybook\": \"8.2.9\",\n    \"tailwindcss\": \"4.0.0-beta.3\",\n    \"tslib\": \"^2.8.1\",\n    \"typescript\": \"^5.6.3\",\n    \"viem\": \"^2.21.47\",\n    \"vite\": \"^5.4.10\",\n    \"vite-plugin-dts\": \"^4.3.0\",\n    \"vite-plugin-svgr\": \"^4.3.0\",\n    \"wagmi\": \"^2.12.33\"\n  },\n  \"peerDependencies\": {\n    \"@tanstack/react-query\": \"^5\",\n    \"react\": \"^18 || ^19\",\n    \"react-dom\": \"^18 || ^19\",\n    \"tailwindcss\": \"^3 || ^4\",\n    \"viem\": \"^2\",\n    \"wagmi\": \"^2\"\n  },\n  \"dependencies\": {\n    \"@headlessui/react\": \"^2.2.0\",\n    \"class-variance-authority\": \"^0.7.1\",\n    \"clsx\": \"^2.1.1\",\n    \"tailwind-merge\": \"^2.5.4\"\n  },\n  \"packageManager\": \"pnpm@9.3.0\"\n}\n"
  },
  {
    "path": "scripts/import-svgs.mjs",
    "content": "/** To import SVGs:\n * 1. In Figma, select one of the icons inside the Icons container and select them with CTRL+A (or ⌘+A on Mac). Export them with the SVG type.\n * 2. Unzip the downloaded file, and copy the SVGs into the \\`src/icons\\` directory.\n * 3. Run this script\n **/\n\nimport fs from \"fs/promises\";\nimport path from \"path\";\n\nconst filesToIgnore = [\"AllIcons.tsx\"];\n/** Use this to map an invalid name temporarily (until it is fixed in the Figma)  */\nconst iconNameMapping = {};\n\nfunction getIconName(svg) {\n  const result = svg.replace(\".svg\", \"\");\n  return iconNameMapping[result] ?? result;\n}\n\nasync function processSvgsInFolder(folder) {\n  // Start by renaming the files to remove the \"Type=\" or \"Property 1=\" prefix\n  await Promise.all(\n    (await fs.readdir(folder, { recursive: true })).map(async (name) => {\n      if (name.includes(\"=\")) {\n        const currentPath = name.split(\"/\").slice(0, -1).join(\"/\");\n        const newName = path.join(\n          folder,\n          currentPath + \"/\" + name.split(\"=\")[1]\n        );\n        if (await fs.access(newName).catch(() => false)) {\n          await fs.unlink(newName);\n        }\n        await fs.rename(path.join(folder, name), newName);\n      }\n    })\n  );\n\n  const svgs = await fs.readdir(folder, { recursive: true });\n  await Promise.all(\n    svgs\n      .filter((svg) => svg.endsWith(\".svg\"))\n      .map(async (svg) => {\n        console.log(path.join(folder, svg));\n        const svgContent = await fs.readFile(path.join(folder, svg), \"utf8\");\n        const result = svgContent\n          .replace(/stroke=\"#160F1F\"/g, 'stroke=\"currentColor\"')\n          .replace(/fill=\"#160F1F\"/g, 'fill=\"currentColor\"')\n          .replace(/width=\"24\"/g, 'width=\"100%\"')\n          .replace(/height=\"24\"/g, 'height=\"100%\"');\n        await fs.writeFile(path.join(folder, svg), result, \"utf8\");\n      })\n  );\n}\n\nasync function createIndexFile(folder) {\n  const header = `/**\\n * This file is auto-generated by the \\`import-svgs.mjs\\` script.\\n */`;\n  const stuffInDir = await fs.readdir(folder);\n  const foundSvgs = [];\n  const foundTsx = [];\n  const foundFolders = [];\n  await Promise.all(\n    stuffInDir.map(async (stuff) => {\n      if (filesToIgnore.includes(stuff)) {\n        return;\n      }\n\n      if (stuff.endsWith(\".svg\")) {\n        foundSvgs.push(stuff);\n      } else if (stuff.endsWith(\".tsx\")) {\n        foundTsx.push(stuff);\n      } else if ((await fs.stat(path.join(folder, stuff))).isDirectory()) {\n        foundFolders.push(stuff);\n      }\n    })\n  );\n  await Promise.all(\n    foundFolders.map(async (f) => {\n      await createIndexFile(path.join(folder, f));\n    })\n  );\n  const content = foundSvgs\n    .map(\n      (svg) =>\n        `export { default as ${getIconName(svg)} } from \"./${svg}?react\";`\n    )\n    .concat(foundTsx.map((tsx) => `export * from \"./${tsx}\";`))\n    .concat(\n      foundFolders.map(\n        (folder) => `export * as ${folder} from \"./${folder}/index.ts\";`\n      )\n    )\n    .join(\"\\n\");\n\n  await fs.writeFile(\n    path.join(folder, \"index.ts\"),\n    `${header}\\n\\n${content}\\n`,\n    \"utf8\"\n  );\n}\n\nconst currentDir = import.meta.dirname;\nconst dirToProcess = path.join(currentDir, \"../src/icons\");\nawait processSvgsInFolder(dirToProcess);\nawait createIndexFile(dirToProcess);\n"
  },
  {
    "path": "src/components/Alert/Alert.stories.tsx",
    "content": "import type { Meta, StoryObj } from \"@storybook/react\";\nimport { Alert, AlertProps } from \"./Alert\";\nimport { InkIcon } from \"../..\";\nimport { fn } from \"@storybook/test\";\n\nconst meta: Meta<AlertProps> = {\n  title: \"Components/Alert\",\n  component: Alert,\n  tags: [\"autodocs\"],\n  args: {\n    title: \"This is an alert title\",\n    description:\n      \"This is a longer description that explains more about the alert.\",\n  },\n};\n\nexport default meta;\ntype Story = StoryObj<typeof meta>;\n\nexport const Success: Story = {\n  args: {\n    variant: \"success\",\n  },\n};\n\nexport const Error: Story = {\n  args: {\n    variant: \"error\",\n  },\n};\n\nexport const Warning: Story = {\n  args: {\n    variant: \"warning\",\n  },\n};\n\nexport const Info: Story = {\n  args: {\n    variant: \"info\",\n  },\n};\n\nexport const WithCustomIcon: Story = {\n  args: {\n    variant: \"info\",\n    icon: <InkIcon.Settings />,\n  },\n};\n\nexport const TitleOnly: Story = {\n  args: {\n    title: \"Just a title\",\n    description: undefined,\n  },\n};\n\nexport const Dismissable: Story = {\n  args: {\n    variant: \"info\",\n    title: \"This alert can be dismissed\",\n    description:\n      \"Click the X to dismiss. The state will persist across refreshes.\",\n    dismissible: true,\n    id: \"example-alert\",\n    onDismiss: fn(),\n  },\n};\n"
  },
  {
    "path": "src/components/Alert/Alert.tsx",
    "content": "import React, { useEffect, useState } from \"react\";\nimport { classNames, variantClassNames } from \"../../util/classes\";\nimport { InkIcon } from \"../..\";\n\nexport interface AlertProps {\n  title: string;\n  description?: React.ReactNode;\n  variant?: \"success\" | \"error\" | \"warning\" | \"info\";\n  icon?: React.ReactNode;\n  className?: string;\n  /**\n   * Unique identifier for the alert. Required if dismissible is true.\n   */\n  id?: string;\n  /**\n   * Whether the alert can be dismissed. If true, id is required.\n   */\n  dismissible?: boolean;\n  /**\n   * Callback fired when the alert is dismissed\n   */\n  onDismiss?: () => void;\n}\n\nexport const Alert: React.FC<AlertProps> = ({\n  title,\n  description,\n  variant = \"info\",\n  icon,\n  className,\n  id,\n  dismissible,\n  onDismiss,\n}) => {\n  const [isDismissed, setIsDismissed] = useState(false);\n\n  useEffect(() => {\n    if (dismissible && id) {\n      const isDismissedStored = localStorage.getItem(`ink-alert-${id}`);\n      setIsDismissed(isDismissedStored === \"true\");\n    }\n  }, [dismissible, id]);\n\n  if (isDismissed) {\n    return null;\n  }\n\n  const defaultIcon = {\n    success: <InkIcon.Check />,\n    error: <InkIcon.Error />,\n    warning: <InkIcon.Error />,\n    info: <InkIcon.Settings />,\n  }[variant];\n\n  const handleDismiss = () => {\n    if (dismissible && id) {\n      localStorage.setItem(`ink-alert-${id}`, \"true\");\n      setIsDismissed(true);\n      onDismiss?.();\n    }\n  };\n\n  return (\n    <div\n      className={classNames(\n        \"ink:flex ink:gap-3 ink:p-3 ink:rounded-md ink:font-default\",\n        variantClassNames(variant, {\n          success: \"ink:bg-status-success-bg ink:text-status-success\",\n          error: \"ink:bg-status-error-bg ink:text-status-error\",\n          warning: \"ink:bg-status-alert-bg ink:text-status-alert\",\n          info: \"ink:bg-background-light ink:text-text-default\",\n        }),\n        className\n      )}\n    >\n      <div className=\"ink:size-4 ink:shrink-0\">{icon || defaultIcon}</div>\n      <div className=\"ink:flex ink:flex-col ink:gap-1 ink:flex-1\">\n        <div className=\"ink:text-body-2-bold\">{title}</div>\n        {description && (\n          <div className=\"ink:text-body-2-regular\">{description}</div>\n        )}\n      </div>\n      {dismissible && (\n        <button\n          onClick={handleDismiss}\n          className=\"ink:size-4 ink:shrink-0 ink:opacity-60 hover:ink:opacity-100 ink:cursor-pointer\"\n          aria-label=\"Dismiss alert\"\n        >\n          <InkIcon.Close />\n        </button>\n      )}\n    </div>\n  );\n};\n\nAlert.displayName = \"Alert\";\n"
  },
  {
    "path": "src/components/Alert/index.ts",
    "content": "export * from \"./Alert\";\n"
  },
  {
    "path": "src/components/Button/Button.stories.tsx",
    "content": "import type { Meta, StoryObj } from \"@storybook/react\";\nimport { fn } from \"@storybook/test\";\n\nimport { Button, type ButtonProps } from \"./index\";\nimport { MatrixDecorator } from \"../../decorators/MatrixDecorator\";\nimport { InkIcon } from \"../..\";\nimport Avatar from \"../../images/avatar.png?base64\";\n\nconst meta: Meta<ButtonProps> = {\n  title: \"Components/Button\",\n  decorators: [\n    MatrixDecorator<ButtonProps>({\n      first: { key: \"size\", values: [\"md\", \"lg\"] },\n      second: {\n        key: \"variant\",\n        values: [\"primary\", \"secondary\", \"transparent\"],\n      },\n    }),\n  ],\n  component: Button,\n  tags: [\"autodocs\"],\n  argTypes: {\n    variant: { control: false },\n    size: { control: false },\n  },\n  args: { onClick: fn() },\n};\n\nexport default meta;\ntype Story = StoryObj<typeof meta>;\n\nexport const Simple: Story = {\n  args: {\n    children: \"Button\",\n  },\n};\n\nexport const Disabled: Story = {\n  args: {\n    disabled: true,\n    children: \"Button\",\n  },\n};\n\nexport const WithIcon: Story = {\n  args: {\n    children: \"Button\",\n    iconLeft: <InkIcon.Deposit />,\n  },\n};\n\nexport const Rounded: Story = {\n  args: {\n    rounded: \"full\",\n    children: <InkIcon.Deposit />,\n  },\n};\n\nexport const WithMinimumWidth: Story = {\n  args: {\n    className: \"ink:min-w-[350px]\",\n    children: \"Button\",\n    iconLeft: <InkIcon.Deposit />,\n  },\n};\n\nexport const AsLink: Story = {\n  args: {\n    asChild: true,\n    children: (\n      <a href=\"https://inkonchain.com\" target=\"_blank\">\n        inkonchain.com\n      </a>\n    ),\n    iconRight: <InkIcon.Arrow className=\"ink:rotate-[225deg]\" />,\n  },\n};\n\nexport const WalletVariant: Story = {\n  decorators: [\n    (Story, { args }) => (\n      <div className=\"ink:flex ink:flex-col ink:items-center ink:justify-center ink:gap-2\">\n        <Story args={{ ...args, size: \"md\" }} />\n        <Story args={{ ...args, size: \"lg\" }} />\n      </div>\n    ),\n  ],\n  parameters: { disableMatrix: true },\n  args: {\n    variant: \"wallet\",\n    children: <div>Wallet</div>,\n    iconLeft: (\n      <img\n        src={Avatar}\n        alt=\"avatar\"\n        className=\"ink:object-cover ink:w-full ink:h-full ink:rounded-full\"\n      />\n    ),\n  },\n};\n"
  },
  {
    "path": "src/components/Button/Button.tsx",
    "content": "import React, { PropsWithChildren, forwardRef } from \"react\";\nimport { classNames, variantClassNames } from \"../../util/classes\";\nimport { Slot, Slottable } from \"../Slot/Slot\";\n\nexport interface ButtonProps\n  extends PropsWithChildren,\n    React.ButtonHTMLAttributes<HTMLButtonElement> {\n  asChild?: boolean;\n  className?: string;\n  variant?: \"primary\" | \"secondary\" | \"wallet\" | \"transparent\";\n  size?: \"md\" | \"lg\";\n  rounded?: \"full\" | \"default\";\n  iconLeft?: React.ReactNode;\n  iconRight?: React.ReactNode;\n}\n\nexport const Button = forwardRef<HTMLButtonElement, ButtonProps>(\n  function Button(\n    {\n      asChild,\n      className,\n      children,\n      variant = \"primary\",\n      size = \"md\",\n      rounded = \"default\",\n      iconLeft,\n      iconRight,\n      ...restProps\n    },\n    ref\n  ) {\n    const Component = asChild ? Slot : \"button\";\n    const iconClasses = classNames(\n      \"ink:size-3 ink:-my-1\",\n      variant === \"wallet\" &&\n        classNames(\n          \"ink:*:object-cover ink:*:w-full ink:*:h-full ink:*:rounded-full\",\n          variantClassNames(size, {\n            md: \"ink:size-4\",\n            lg: \"ink:size-6\",\n          })\n        )\n    );\n    return (\n      <Component\n        className={classNames(\n          \"ink:rounded-full ink:font-default ink:transition-colors ink:hover:cursor-pointer ink:disabled:cursor-not-allowed ink:transition-default-animation ink:box-border ink:backdrop-blur-lg\",\n          \"ink:flex ink:items-center ink:justify-center ink:gap-1 ink:shrink-0 ink:select-none ink:no-underline\",\n          variantClassNames(size, {\n            md: \"ink:px-2 ink:py-1.5 ink:text-body-3-bold ink:h-5\",\n            lg: \"ink:px-4 ink:py-3 ink:text-h5 ink:h-8\",\n          }),\n          variantClassNames(rounded, {\n            full: `ink:rounded-full ${variantClassNames(size, {\n              md: \"ink:p-1 ink:size-5\",\n              lg: \"ink:p-2 ink:size-8\",\n            })}`,\n            default: \"\",\n          }),\n          variantClassNames(variant, {\n            primary:\n              \"ink:bg-button-primary ink:text-text-on-primary ink:hover:bg-button-primary-hover ink:disabled:bg-button-primary-disabled ink:disabled:text-text-on-primary-disabled ink:active:bg-button-primary-pressed\",\n            secondary:\n              \"ink:bg-button-secondary ink:text-text-on-secondary ink:hover:bg-button-secondary-hover ink:disabled:bg-button-secondary-disabled ink:disabled:text-text-on-secondary-disabled ink:active:bg-button-secondary-pressed\",\n            wallet: classNames(\n              \"ink:bg-background-light-transparent ink:text-body-2-bold ink:text-text-default ink:hover:bg-background-light ink:disabled:bg-background-light-transparent-disabled ink:disabled:text-muted ink:active:bg-background-light\",\n              \"ink:border-background-container ink:border\",\n              iconLeft &&\n                variantClassNames(size, {\n                  md: \"ink:pl-0.5\",\n                  lg: \"ink:pl-1\",\n                }),\n              iconRight &&\n                variantClassNames(size, {\n                  md: \"ink:pr-0.5\",\n                  lg: \"ink:pr-1\",\n                })\n            ),\n            transparent:\n              \"ink:bg-transparent ink:text-text-default ink:hover:bg-background-light-transparent ink:disabled:bg-transparent ink:disabled:text-muted\",\n          }),\n          className\n        )}\n        {...restProps}\n        ref={ref}\n      >\n        <Slottable child={children}>\n          {(child) => (\n            <>\n              {iconLeft && <div className={iconClasses}>{iconLeft}</div>}\n              {child}\n              {iconRight && <div className={iconClasses}>{iconRight}</div>}\n            </>\n          )}\n        </Slottable>\n      </Component>\n    );\n  }\n);\n\nButton.displayName = \"Button\";\n"
  },
  {
    "path": "src/components/Button/index.ts",
    "content": "export * from \"./Button\";\n"
  },
  {
    "path": "src/components/Card/Card.stories.tsx",
    "content": "import type { Meta, StoryObj } from \"@storybook/react\";\nimport { Card, type CardProps, CardContent } from \"./index\";\nimport { Tag } from \"../Tag\";\nimport { Button } from \"../Button\";\nimport { InkIcon } from \"../..\";\nimport { TitleAndDescription } from \"./Content\";\n\nconst meta: Meta<CardProps> = {\n  title: \"Components/Card\",\n  component: Card,\n  tags: [\"autodocs\"],\n  argTypes: {},\n  args: {\n    children: (\n      <CardContent.CallToAction\n        title=\"Card Example\"\n        description=\"Ever wondered why keyboards aren't arranged in alphabetical order? Probably because someone in the 1870s had a really good time watching people hunt and peck for letters. QWERTY layout: the original practical joke that became a global standard.\"\n        button={\n          <Button variant=\"primary\" size=\"lg\">\n            Button\n          </Button>\n        }\n      />\n    ),\n    image: (\n      <CardContent.Image\n        mainLabels={\n          <>\n            <Tag variant=\"event\">Tag 1</Tag>\n            <Tag variant=\"event\">Tag 2</Tag>\n          </>\n        }\n      >\n        <img\n          src=\"https://picsum.photos/1024/576\"\n          alt=\"Card Image\"\n          width={1024}\n          height={580}\n        />\n      </CardContent.Image>\n    ),\n    imageLocation: \"left\",\n  },\n};\n\nexport default meta;\ntype Story = StoryObj<typeof meta>;\n\nexport const Basic: Story = {\n  args: {},\n};\n\nexport const ImageOnTheRight: Story = {\n  args: {\n    children: (\n      <TitleAndDescription\n        title=\"Image on the right\"\n        description=\"Why did the image move to the right? Because it was tired of being left out! Now it can finally see what's happening on the other side of the card. Some say it's getting a better view of the content this way.\"\n      />\n    ),\n    imageLocation: \"right\",\n  },\n};\n\nexport const ImageOnTheTop: Story = {\n  args: {\n    children: (\n      <TitleAndDescription\n        title=\"Image on the top\"\n        description=\"After enjoying the view from the right side, our adventurous image decided to aim even higher! Now it's living the high life at the top of the card, looking down on all the content below. Talk about a promotion in position!\"\n      />\n    ),\n    imageLocation: \"top\",\n  },\n};\n\nexport const ImageWithMainAndSecondaryLabels: Story = {\n  args: {\n    children: (\n      <TitleAndDescription\n        title=\"Image with main and secondary labels\"\n        description=\"After exploring different positions, our image decided it needed some accessories! Now it's showing off its fancy collection of labels - both main and secondary ones. Like a fashionista with a new wardrobe, it's strutting its stuff with tags that make it stand out from the crowd!\"\n      />\n    ),\n    image: (\n      <CardContent.Image\n        mainLabels={\n          <>\n            <Tag variant=\"event\">Tag 1</Tag>\n            <Tag variant=\"event\">Tag 2</Tag>\n          </>\n        }\n        secondaryLabels={\n          <>\n            <Tag variant=\"event\">Tag 3</Tag>\n            <Tag variant=\"event\">Tag 4</Tag>\n          </>\n        }\n      >\n        <img\n          src=\"https://picsum.photos/1024/576\"\n          alt=\"Card Image\"\n          width={1024}\n          height={580}\n        />\n      </CardContent.Image>\n    ),\n  },\n};\n\n/** This variant has a color independent of the theme. */\nexport const PurpleLightVariant: Story = {\n  args: {\n    variant: \"light-purple\",\n  },\n};\n\n/** For a Tagline card, use `CardContent.Tagline` and no image. */\nexport const WithTagline: Story = {\n  args: {\n    image: undefined,\n    imageLocation: undefined,\n    children: (\n      <CardContent.Tagline\n        title=\"Do something now!\"\n        buttons={\n          <>\n            <Button variant=\"primary\" size=\"lg\">\n              Button\n            </Button>\n            <Button variant=\"secondary\" size=\"lg\">\n              Second Button\n            </Button>\n          </>\n        }\n      />\n    ),\n  },\n};\n\n/** Set the \"secondary\" variant and \"clickable\" to get a hover, use `asChild` to have an `a` tag as the root element, then use `CardContent.Link` to render the content. */\nexport const Link: Story = {\n  args: {\n    variant: \"secondary\",\n    clickable: true,\n    asChild: true,\n    image: undefined,\n    children: (\n      <a href=\"#something\" target=\"_self\" className=\"ink:no-underline\">\n        <CardContent.Link\n          icon={<InkIcon.Logo.Ink />}\n          title=\"Join the Ink Revolution!\"\n          description=\"Did you know that Ink's design system is like a chameleon for your UI? Just like these color-changing lizards adapt to their environment, Ink components seamlessly blend into any design while maintaining their unique personality. Just fabulous, adaptable UI!\"\n        />\n      </a>\n    ),\n  },\n};\n\nexport const LargeLinks: Story = {\n  args: {\n    image: (\n      <CardContent.Image mainLabels={<Tag variant=\"event\">Main Label</Tag>}>\n        <img\n          src=\"https://picsum.photos/1024/576\"\n          alt=\"Card Image\"\n          width={1024}\n          height={1024}\n        />\n      </CardContent.Image>\n    ),\n    children: (\n      <>\n        <TitleAndDescription\n          title=\"Links Galore\"\n          description=\"Links are the backbone of the web! They connect us, guide us, and make the internet what it is today. At Ink, we love links so much we've made them beautiful, accessible, and a joy to use. Click around and experience the magic of web navigation!\"\n        />\n        <CardContent.LargeLinks>\n          <CardContent.LargeLink asChild>\n            <a href=\"#design-tips\" target=\"_self\" className=\"ink:no-underline\">\n              Design Tips & Tricks\n            </a>\n          </CardContent.LargeLink>\n          <CardContent.LargeLink asChild>\n            <a href=\"#color-theory\" target=\"_self\" className=\"ink:no-underline\">\n              Color Theory 101\n            </a>\n          </CardContent.LargeLink>\n          <CardContent.LargeLink asChild>\n            <a href=\"#typography\" target=\"_self\" className=\"ink:no-underline\">\n              Typography Essentials\n            </a>\n          </CardContent.LargeLink>\n          <CardContent.LargeLink asChild>\n            <a\n              href=\"#accessibility\"\n              target=\"_self\"\n              className=\"ink:no-underline\"\n            >\n              Accessibility Best Practices\n            </a>\n          </CardContent.LargeLink>\n          <CardContent.LargeLink asChild>\n            <a href=\"#animations\" target=\"_self\" className=\"ink:no-underline\">\n              Animation Fundamentals\n            </a>\n          </CardContent.LargeLink>\n          <CardContent.LargeLink asChild>\n            <a href=\"#responsive\" target=\"_self\" className=\"ink:no-underline\">\n              Responsive Design Guide\n            </a>\n          </CardContent.LargeLink>\n        </CardContent.LargeLinks>\n      </>\n    ),\n  },\n};\n\nexport const LargeCardInfo: Story = {\n  args: {\n    image: (\n      <CardContent.Image mainLabels={<Tag variant=\"event\">Main Label</Tag>}>\n        <img\n          src=\"https://picsum.photos/1024/576\"\n          alt=\"Card Image\"\n          width={1024}\n          height={1024}\n        />\n      </CardContent.Image>\n    ),\n    children: (\n      <>\n        <TitleAndDescription title=\"Fun Activities Around Town\" />\n        <CardContent.CardInfos>\n          <CardContent.CardInfo\n            icon={<InkIcon.Apps className=\"ink:size-3\" />}\n            title=\"Pizza Making Class\"\n            description=\"Learn to toss dough and create your perfect pizza with our expert chefs.\"\n          />\n          <CardContent.CardInfo\n            icon={<InkIcon.Bridge className=\"ink:size-3\" />}\n            title=\"Paint & Sip Night\"\n            description=\"Enjoy wine while creating your masterpiece in this relaxing art class.\"\n          />\n          <CardContent.CardInfo\n            icon={<InkIcon.Social.Telegram className=\"ink:size-3\" />}\n            title=\"Live Jazz Night\"\n            description=\"Swing by for smooth tunes and great vibes at our local jazz club.\"\n          />\n          <CardContent.CardInfo\n            icon={<InkIcon.Deposit className=\"ink:size-3\" />}\n            title=\"Community Garden\"\n            description=\"Get your hands dirty and learn about urban farming with neighbors.\"\n          />\n\n          <CardContent.CardInfo\n            className=\"ink:lg:col-span-2\"\n            icon={<InkIcon.Sun className=\"ink:size-3\" />}\n            title=\"Weekend Food Festival\"\n            description=\"Sample delicious treats from local vendors and enjoy live entertainment all weekend long.\"\n          />\n        </CardContent.CardInfos>\n      </>\n    ),\n  },\n};\n\nexport const FullCard: Story = {\n  args: {\n    size: \"noPadding\",\n    image: (\n      <CardContent.Image>\n        <img\n          src=\"https://picsum.photos/1024/576\"\n          alt=\"Card Image\"\n          width={1024}\n          height={580}\n        />\n      </CardContent.Image>\n    ),\n  },\n};\n\nexport const FullCardWithImageOnTheRight: Story = {\n  args: {\n    size: \"noPadding\",\n    imageLocation: \"right\",\n    image: (\n      <CardContent.Image>\n        <img\n          src=\"https://picsum.photos/1024/576\"\n          alt=\"Card Image\"\n          width={1024}\n          height={580}\n        />\n      </CardContent.Image>\n    ),\n  },\n};\n\nexport const CardWithSmallImage: Story = {\n  args: {\n    size: \"small\",\n    children: (\n      <TitleAndDescription\n        title=\"Card with small image\"\n        description=\"This is a card with a small image.\"\n        size=\"small\"\n      />\n    ),\n    image: (\n      <CardContent.Image variant=\"square\">\n        <img\n          src=\"https://picsum.photos/1024/576\"\n          alt=\"Card Image\"\n          width={128}\n          height={128}\n        />\n      </CardContent.Image>\n    ),\n  },\n};\n"
  },
  {
    "path": "src/components/Card/Card.tsx",
    "content": "import React, { forwardRef } from \"react\";\nimport { classNames, variantClassNames } from \"../../util/classes\";\nimport { Slot, Slottable } from \"../Slot\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\n\nexport interface CardProps extends VariantProps<typeof cardVariants> {\n  className?: string;\n  children: React.ReactNode;\n  image?: React.ReactNode;\n  clickable?: boolean;\n  asChild?: boolean;\n}\n\nconst cardVariants = cva(\n  `\nink:grid ink:grid-cols-1\nink:gap-3\nink:relative \nink:bg-background-container \nink:font-default\nink:box-border\nink:overflow-hidden\n`,\n  {\n    variants: {\n      variant: {\n        default: \"ink:bg-background-container\",\n        \"light-purple\": \"ink:bg-ink-light-purple\",\n        secondary: \"ink:bg-button-secondary\",\n      },\n      imageLocation: {\n        left: \"ink:sm:grid-cols-2\",\n        right: \"ink:sm:grid-cols-2\",\n        top: \"ink:sm:grid-cols-1\",\n      },\n      clickable: {\n        true: \"ink:cursor-pointer\",\n        false: \"\",\n      },\n      size: {\n        noPadding: \"ink:rounded-lg\",\n        small: \"ink:p-2 ink:pb-3 ink:sm:p-3 ink:rounded-lg\",\n        default: \"ink:p-2 ink:pb-3 ink:sm:p-3 ink:rounded-xl\",\n      },\n    },\n    compoundVariants: [\n      {\n        variant: \"secondary\",\n        clickable: true,\n        className: \"ink:hover:bg-button-secondary-hover\",\n      },\n      {\n        size: \"small\",\n        imageLocation: \"left\",\n        className: \"ink:grid-cols-[128px_1fr] ink:sm:grid-cols-[128px_1fr]\",\n      },\n    ],\n    defaultVariants: {\n      size: \"default\",\n    },\n  }\n);\n\nexport const Card = forwardRef<HTMLDivElement, CardProps>(function Card(\n  {\n    children,\n    className,\n    image,\n    imageLocation,\n    asChild,\n    variant,\n    clickable,\n    size,\n  },\n  ref\n) {\n  const Component = asChild ? Slot : \"div\";\n  return (\n    <Component\n      ref={ref}\n      className={classNames(\n        cardVariants({\n          variant,\n          imageLocation: image ? imageLocation : undefined,\n          clickable,\n          size: size || (image ? \"default\" : \"small\"),\n          className,\n        }),\n        className\n      )}\n      style={\n        {\n          \"--ink-card-default-color\":\n            variant === \"light-purple\"\n              ? \"var(--ink-background-light)\"\n              : \"var(--ink-text-default)\",\n          \"--ink-card-muted-color\":\n            variant === \"light-purple\"\n              ? \"var(--ink-background-light)\"\n              : \"var(--ink-text-muted)\",\n          \"--ink-card-rounded\": variantClassNames(size || \"default\", {\n            noPadding: \"\",\n            small: \"var(--ink-base-radius-sm)\",\n            default: \"var(--ink-base-radius-lg)\",\n          }),\n        } as React.CSSProperties\n      }\n    >\n      <Slottable child={children}>\n        {(child) => (\n          <>\n            {image}\n            <div\n              className={classNames(\n                \"ink:flex ink:flex-col ink:gap-2 ink:sm:gap-6 ink:justify-center\",\n                \"ink:text-text-default ink:box-border\",\n                !!image && \"ink:p-2 ink:sm:p-3\",\n                imageLocation === \"right\" && \"ink:sm:-order-1\",\n                imageLocation !== \"top\" &&\n                  !!image &&\n                  variantClassNames(size || \"default\", {\n                    default: \"ink:sm:py-[100px]\",\n                    noPadding: \"ink:sm:py-[100px]\",\n                    small: \"\",\n                  })\n              )}\n            >\n              {child}\n            </div>\n          </>\n        )}\n      </Slottable>\n    </Component>\n  );\n});\n\nCard.displayName = \"Card\";\n"
  },
  {
    "path": "src/components/Card/Content/CallToAction.tsx",
    "content": "import { classNames } from \"../../../util/classes\";\nimport { TitleAndDescription } from \"./TitleAndDescription\";\n\ninterface CallToActionProps {\n  title: React.ReactNode;\n  description: React.ReactNode;\n  button: React.ReactNode;\n  className?: string;\n}\n\nexport const CallToAction: React.FC<CallToActionProps> = ({\n  title,\n  description,\n  button,\n  className,\n}) => {\n  return (\n    <div className={classNames(\"ink:flex ink:flex-col ink:gap-3\", className)}>\n      <TitleAndDescription title={title} description={description} />\n      <div className=\"ink:flex ink:gap-2 ink:box-border\">{button}</div>\n    </div>\n  );\n};\n\nCallToAction.displayName = \"CallToAction\";\n"
  },
  {
    "path": "src/components/Card/Content/CardInfo.tsx",
    "content": "import { PropsWithChildren } from \"react\";\nimport { classNames } from \"../../../util/classes\";\nimport { TitleAndDescription } from \"./TitleAndDescription\";\nimport { Card } from \"../Card\";\n\nexport interface CardInfoProps extends PropsWithChildren {\n  className?: string;\n  icon?: React.ReactNode;\n  title: string;\n  description: string;\n}\nexport const CardInfo = ({\n  className,\n  icon,\n  title,\n  description,\n  children,\n}: CardInfoProps) => {\n  return (\n    <Card variant=\"secondary\" className={className}>\n      <div\n        className={classNames(\n          \"ink:flex ink:flex-col ink:justify-start ink:gap-3 ink:box-border ink:flex-1\",\n          className\n        )}\n      >\n        {icon}\n        <TitleAndDescription\n          title={title}\n          description={description}\n          size=\"cardInfo\"\n        />\n        {children}\n      </div>\n    </Card>\n  );\n};\n\nCardInfo.displayName = \"CardInfo\";\n"
  },
  {
    "path": "src/components/Card/Content/CardInfos.tsx",
    "content": "import { PropsWithChildren } from \"react\";\nimport { classNames } from \"../../../util/classes\";\n\nexport interface CardInfosProps extends PropsWithChildren {\n  className?: string;\n  children: React.ReactNode;\n}\n\nexport const CardInfos = ({ children, className }: CardInfosProps) => {\n  return (\n    <div\n      className={classNames(\n        \"ink:grid ink:grid-cols-[repeat(auto-fit,minmax(max(200px,calc(100%/3)),1fr))] ink:gap-1 ink:box-border\",\n        className\n      )}\n    >\n      {children}\n    </div>\n  );\n};\n\nCardInfos.displayName = \"CardInfos\";\n"
  },
  {
    "path": "src/components/Card/Content/Image.tsx",
    "content": "import * as React from \"react\";\nimport { classNames } from \"../../../util/classes\";\nimport { Slot } from \"../../Slot\";\n\nexport interface ImageProps extends React.PropsWithChildren {\n  variant?: \"default\" | \"square\";\n  className?: string;\n  mainLabels?: React.ReactNode;\n  secondaryLabels?: React.ReactNode;\n}\n\nexport const Image: React.FC<ImageProps> = ({\n  className,\n  variant,\n  mainLabels,\n  secondaryLabels,\n  children,\n}) => {\n  return (\n    <div\n      className={classNames(\n        \"ink:rounded-(--ink-card-rounded) ink:overflow-hidden ink:box-border ink:relative\",\n        className\n      )}\n    >\n      {(mainLabels || secondaryLabels) && (\n        <div\n          className={classNames(\n            \"ink:absolute ink:top-0 ink:left-0 ink:right-0\",\n            \"ink:px-2 sm:ink:px-3 md:ink:px-4 ink:pt-2 sm:ink:pt-2 md:ink:pt-4\",\n            \"ink:flex ink:justify-between ink:items-start ink:gap-1 ink:z-10 ink:flex-wrap\",\n            \"ink:whitespace-nowrap\"\n          )}\n        >\n          <div className=\"ink:flex ink:gap-1 ink:flex-wrap ink:flex-1 ink:justify-start\">\n            {mainLabels}\n          </div>\n          {secondaryLabels && (\n            <div className=\"ink:flex ink:gap-1 ink:flex-wrap ink:flex-0 ink:justify-start\">\n              {secondaryLabels}\n            </div>\n          )}\n        </div>\n      )}\n      <Slot\n        className={classNames(\n          \"ink:object-cover ink:object-center ink:w-full ink:h-full\",\n          variant === \"square\" && \"ink:aspect-square\"\n        )}\n      >\n        {children}\n      </Slot>\n    </div>\n  );\n};\n\nImage.displayName = \"Image\";\n"
  },
  {
    "path": "src/components/Card/Content/LargeLink.tsx",
    "content": "import { PropsWithChildren } from \"react\";\nimport { classNames } from \"../../../util/classes\";\nimport { Slot, Slottable } from \"../../Slot\";\nimport { InkIcon } from \"../../..\";\n\nexport interface LargeLinkProps extends PropsWithChildren {\n  className?: string;\n  asChild?: boolean;\n  linkIcon?: React.ReactNode;\n  href?: string;\n  target?: string;\n}\n\nexport const LargeLink = ({\n  children,\n  className,\n  asChild,\n  linkIcon = (\n    <InkIcon.Arrow className=\"ink:size-3 ink:rotate-270 ink:shrink-0\" />\n  ),\n  href,\n  target,\n}: LargeLinkProps) => {\n  const Component = asChild ? Slot : \"a\";\n  return (\n    <Component\n      href={href}\n      target={target}\n      className={classNames(\n        \"ink:p-3 ink:bg-button-secondary ink:text-(--ink-card-default-color) ink:text-h5 ink:rounded-lg ink:box-border\",\n        \"ink:flex ink:justify-between ink:items-center ink:gap-0.5\",\n        \"ink:min-w-[200px]\",\n        href && \"ink:cursor-pointer ink:hover:bg-button-secondary-hover\",\n        className\n      )}\n    >\n      <Slottable child={children}>\n        {(child) => (\n          <>\n            <div className=\"ink:overflow-ellipsis ink:overflow-hidden ink:whitespace-nowrap\">\n              {child}\n            </div>\n            {linkIcon}\n          </>\n        )}\n      </Slottable>\n    </Component>\n  );\n};\n\nLargeLink.displayName = \"LargeLink\";\n"
  },
  {
    "path": "src/components/Card/Content/LargeLinks.tsx",
    "content": "import { PropsWithChildren } from \"react\";\nimport { classNames } from \"../../../util/classes\";\n\nexport interface LargeLinksProps extends PropsWithChildren {\n  className?: string;\n  children: React.ReactNode;\n}\n\nexport const LargeLinks = ({ children, className }: LargeLinksProps) => {\n  return (\n    <div\n      className={classNames(\n        \"ink:grid ink:grid-cols-[repeat(auto-fit,minmax(max(200px,calc(100%/3)),1fr))] ink:gap-1 ink:box-border\",\n        className\n      )}\n    >\n      {children}\n    </div>\n  );\n};\n\nLargeLinks.displayName = \"LargeLinks\";\n"
  },
  {
    "path": "src/components/Card/Content/Link.tsx",
    "content": "import { InkIcon } from \"../../..\";\nimport { Tiny } from \"./Tiny\";\n\ninterface LinkProps {\n  className?: string;\n  title: string;\n  description: string;\n  icon?: React.ReactNode;\n  linkIcon?: React.ReactNode;\n}\n\nexport const Link = ({\n  className,\n  title,\n  description,\n  icon,\n  linkIcon = <InkIcon.Arrow className=\"ink:size-2 ink:rotate-225\" />,\n}: LinkProps) => {\n  return (\n    <Tiny\n      className={className}\n      icon={\n        icon ? (\n          <div className=\"ink:size-6 ink:text-(--ink-card-muted-color)\">\n            {icon}\n          </div>\n        ) : undefined\n      }\n      title={title}\n      description={description}\n    >\n      {linkIcon && (\n        <div className=\"ink:absolute ink:top-3 ink:right-3 ink:text-(--ink-card-muted-color)\">\n          {linkIcon}\n        </div>\n      )}\n    </Tiny>\n  );\n};\n\nLink.displayName = \"Link\";\n"
  },
  {
    "path": "src/components/Card/Content/Tagline.tsx",
    "content": "import { classNames } from \"../../../util/classes\";\n\ninterface TaglineProps {\n  title: React.ReactNode;\n  buttons: React.ReactNode;\n  className?: string;\n}\n\nexport const Tagline: React.FC<TaglineProps> = ({\n  title,\n  buttons,\n  className,\n}) => {\n  return (\n    <div\n      className={classNames(\n        \"ink:flex ink:flex-col ink:gap-4 sm:gap-8 ink:text-(--ink-card-default-color) ink:px-0 ink:py-6 ink:sm:px-16 ink:sm:py-12 ink:justify-between\",\n        className\n      )}\n    >\n      <h3 className=\"ink:text-h2 ink:sm:text-h1 ink:m-0 ink:box-border ink:text-center\">\n        {title}\n      </h3>\n\n      <div className=\"ink:flex ink:justify-center ink:flex-wrap ink:gap-2 ink:m-0 ink:box-border\">\n        {buttons}\n      </div>\n    </div>\n  );\n};\n\nTagline.displayName = \"Tagline\";\n"
  },
  {
    "path": "src/components/Card/Content/Tiny.tsx",
    "content": "import { PropsWithChildren } from \"react\";\nimport { classNames } from \"../../../util/classes\";\nimport { TitleAndDescription } from \"./TitleAndDescription\";\n\nexport interface TinyProps extends PropsWithChildren {\n  className?: string;\n  icon?: React.ReactNode;\n  title: string;\n  description: string;\n}\nexport const Tiny = ({\n  className,\n  icon,\n  title,\n  description,\n  children,\n}: TinyProps) => {\n  return (\n    <div\n      className={classNames(\n        \"ink:flex ink:flex-col ink:justify-start ink:gap-3 ink:box-border\",\n        className\n      )}\n    >\n      {icon}\n      <TitleAndDescription\n        title={title}\n        description={description}\n        size=\"small\"\n      />\n      {children}\n    </div>\n  );\n};\n\nTiny.displayName = \"Tiny\";\n"
  },
  {
    "path": "src/components/Card/Content/TitleAndDescription.tsx",
    "content": "import { classNames, variantClassNames } from \"../../../util/classes\";\n\nexport interface TitleAndDescriptionProps {\n  title: React.ReactNode;\n  description?: React.ReactNode;\n  size?: \"default\" | \"small\" | \"cardInfo\";\n}\n\nexport const TitleAndDescription = ({\n  title,\n  description,\n  size = \"default\",\n}: TitleAndDescriptionProps) => {\n  return (\n    <div className=\"ink:flex ink:flex-col ink:gap-2\">\n      <h3\n        className={classNames(\n          \"ink:text-body-1-bold ink:text-(--ink-card-default-color) ink:box-border ink:m-0 ink:-my-px\",\n          variantClassNames(size, {\n            default: \"ink:text-h3\",\n            small: \"ink:text-body-1-regular\",\n            cardInfo: \"ink:text-h5\",\n          })\n        )}\n      >\n        {title}\n      </h3>\n      {description && (\n        <div\n          className={classNames(\n            \"ink:text-body-3-regular ink:text-(--ink-card-muted-color) ink:box-border ink:m-0\",\n            variantClassNames(size, {\n              default: \"ink:text-body-1-regular\",\n              small: \"ink:text-body-3-regular\",\n              cardInfo: \"ink:text-body-2-regular\",\n            })\n          )}\n        >\n          {description}\n        </div>\n      )}\n    </div>\n  );\n};\n\nTitleAndDescription.displayName = \"TitleAndDescription\";\n"
  },
  {
    "path": "src/components/Card/Content/index.ts",
    "content": "export * from \"./CallToAction\";\nexport * from \"./CardInfo\";\nexport * from \"./CardInfos\";\nexport * from \"./Image\";\nexport * from \"./LargeLink\";\nexport * from \"./LargeLinks\";\nexport * from \"./Link\";\nexport * from \"./Tagline\";\nexport * from \"./Tiny\";\nexport * from \"./TitleAndDescription\";\n"
  },
  {
    "path": "src/components/Card/index.ts",
    "content": "export * from \"./Card\";\nexport * as CardContent from \"./Content\";\n"
  },
  {
    "path": "src/components/Checkbox/Checkbox.stories.tsx",
    "content": "import type { Meta, StoryObj } from \"@storybook/react\";\nimport { Checkbox, CheckboxProps, CheckboxLabel } from \"./index\";\nimport { fn } from \"@storybook/test\";\nimport { useEffect, useMemo, useState } from \"react\";\nimport { ListItem } from \"../ListItem\";\nconst meta: Meta<CheckboxProps> = {\n  title: \"Components/Checkbox\",\n  component: Checkbox,\n  tags: [\"autodocs\"],\n  args: {\n    checked: false,\n    indeterminate: false,\n    onChange: fn(),\n  },\n};\n\nexport default meta;\ntype Story = StoryObj<typeof meta>;\n\nexport const Interactive: Story = {\n  args: {},\n  render: (args) => {\n    const [checked, setChecked] = useState(args.checked);\n    useEffect(() => {\n      setChecked(args.checked);\n    }, [args.checked]);\n    return <Checkbox {...args} checked={checked} onChange={setChecked} />;\n  },\n};\n\nexport const WithLabel: Story = {\n  args: {},\n  render: (args) => {\n    const [checked, setChecked] = useState(args.checked);\n    useEffect(() => {\n      setChecked(args.checked);\n    }, [args.checked]);\n    return (\n      <CheckboxLabel label=\"Checkbox\">\n        <Checkbox {...args} checked={checked} onChange={setChecked} />\n      </CheckboxLabel>\n    );\n  },\n};\n\nexport const WithLabelAndDescription: Story = {\n  args: {},\n  render: (args) => {\n    const [checked, setChecked] = useState(args.checked);\n    useEffect(() => {\n      setChecked(args.checked);\n    }, [args.checked]);\n    return (\n      <CheckboxLabel\n        label=\"Checkbox\"\n        description=\"Some description of the checkbox\"\n      >\n        <Checkbox {...args} checked={checked} onChange={setChecked} />\n      </CheckboxLabel>\n    );\n  },\n};\n\nexport const NestingWithIndeterminateState: Story = {\n  args: {\n    indeterminate: false,\n  },\n  render: (args) => {\n    const [firstChildChecked, setFirstChildChecked] = useState(args.checked);\n    const [secondChildChecked, setSecondChildChecked] = useState(args.checked);\n\n    useEffect(() => {\n      setFirstChildChecked(true);\n      setSecondChildChecked(true);\n    }, [args.checked]);\n\n    const checked = useMemo(() => {\n      return firstChildChecked && secondChildChecked;\n    }, [firstChildChecked, secondChildChecked]);\n    const indeterminate = useMemo(() => {\n      return firstChildChecked || secondChildChecked;\n    }, [checked, firstChildChecked, secondChildChecked]);\n\n    return (\n      <div className=\"ink:flex ink:flex-col ink:gap-1\">\n        <CheckboxLabel label=\"Top Level\">\n          <Checkbox\n            {...args}\n            indeterminate={indeterminate}\n            checked={checked}\n            onChange={() => {\n              if (checked || indeterminate) {\n                setFirstChildChecked(false);\n                setSecondChildChecked(false);\n              } else {\n                setFirstChildChecked(true);\n                setSecondChildChecked(true);\n              }\n            }}\n          />\n        </CheckboxLabel>\n        <div className=\"ink:flex ink:flex-col ink:pl-2 ink:gap-1\">\n          <CheckboxLabel label=\"First Child\">\n            <Checkbox\n              {...args}\n              checked={firstChildChecked || checked}\n              onChange={setFirstChildChecked}\n            />\n          </CheckboxLabel>\n          <CheckboxLabel label=\"Second Child\">\n            <Checkbox\n              {...args}\n              checked={secondChildChecked || checked}\n              onChange={setSecondChildChecked}\n            />\n          </CheckboxLabel>\n        </div>\n      </div>\n    );\n  },\n};\n\n/** If you want to use the Checkbox without its own managed state, set checked={undefined} and onChange={undefined}, and add `data-checked={value}` to the parent item. */\nexport const ManagedByAParentItem: Story = {\n  argTypes: {\n    onChange: {\n      control: false,\n    },\n  },\n  args: {},\n  render: (args) => {\n    const [checked, setChecked] = useState(args.checked);\n    useEffect(() => {\n      setChecked(args.checked);\n    }, [args.checked]);\n    return (\n      <ListItem\n        onClick={() => setChecked(!checked)}\n        data-checked={checked ? \"true\" : undefined}\n        iconLeft={\n          <Checkbox {...args} checked={undefined} onChange={undefined} />\n        }\n      >\n        <div>Checkbox</div>\n      </ListItem>\n    );\n  },\n};\n"
  },
  {
    "path": "src/components/Checkbox/Checkbox.tsx",
    "content": "import { Checkbox as HeadlessCheckbox } from \"@headlessui/react\";\nimport { classNames } from \"../../util/classes\";\nimport { InkIcon } from \"../..\";\n\nexport interface CheckboxProps\n  extends Omit<React.InputHTMLAttributes<HTMLInputElement>, \"onChange\"> {\n  checked?: boolean;\n  indeterminate?: boolean;\n  onChange?: (enabled: boolean) => void;\n}\n\nexport const Checkbox: React.FC<CheckboxProps> = ({\n  checked,\n  indeterminate,\n  onChange,\n  className,\n  ...props\n}) => {\n  const Component = onChange ? HeadlessCheckbox : \"span\";\n  return (\n    <Component\n      checked={checked}\n      indeterminate={!checked && indeterminate}\n      onChange={(eventOrValue) => {\n        /* Only happens when we're using the HeadlessCheckbox component. If we are not, then we don't track changes. */\n        if (typeof eventOrValue === \"boolean\") {\n          onChange?.(eventOrValue);\n        }\n      }}\n      className={classNames(\n        \"ink:group ink:relative ink:flex ink:items-center ink:justify-center ink:size-3 ink:shrink-0 ink:rounded-xs ink:box-border\",\n        \"ink:transition-colors ink:transition-default-animation\",\n        \"ink:bg-button-secondary ink:shadow-xs\",\n        \"ink:ring-text-on-secondary ink:focus-visible:outline-none ink:focus-visible:text-on-primary ink:focus-visible:ring-2 ink:focus-visible:ring-offset-2\",\n        \"ink:data-checked:bg-button-primary ink:group-data-checked:bg-button-primary\",\n        \"ink:data-indeterminate:bg-button-primary ink:group-data-indeterminate:bg-button-primary\",\n        \"ink:data-selected:bg-button-primary ink:group-data-selected:bg-button-primary\",\n        \"ink:flex ink:items-center\",\n        \"ink:text-button-primary ink:data-checked:text-text-on-primary ink:data-indeterminate:text-text-on-primary\",\n        \"ink:group-data-checked:text-text-on-primary ink:group-data-indeterminate:text-text-on-primary\",\n        \"ink:group-data-selected:text-text-on-primary\",\n        \"ink:cursor-pointer\",\n        className\n      )}\n      data-checked={checked ? \"true\" : undefined}\n      data-indeterminate={indeterminate ? \"true\" : undefined}\n      {...props}\n    >\n      <div className=\"ink:absolute ink:inset-0 ink:flex ink:items-center ink:justify-center ink:box-border\">\n        <InkIcon.Check\n          className={classNames(\n            \"ink:size-3\",\n            \"ink:animate-svg-path ink:group-data-checked:not-in-data-indeterminate:animate-svg-path-start\",\n            \"ink:group-data-selected:animate-svg-path-start\"\n          )}\n        />\n      </div>\n\n      <InkIcon.Minus\n        className={classNames(\n          \"ink:size-3\",\n          \"ink:animate-svg-path ink:group-data-indeterminate:animate-svg-path-start\"\n        )}\n      />\n    </Component>\n  );\n};\n"
  },
  {
    "path": "src/components/Checkbox/CheckboxLabel.tsx",
    "content": "import { FieldLabel, FieldLabelProps } from \"../FieldLabel\";\n\nexport interface CheckboxLabelProps extends FieldLabelProps {}\n\nexport const CheckboxLabel: React.FC<CheckboxLabelProps> = (props) => {\n  return <FieldLabel {...props} />;\n};\n"
  },
  {
    "path": "src/components/Checkbox/index.ts",
    "content": "export * from \"./Checkbox\";\nexport * from \"./CheckboxLabel\";\n"
  },
  {
    "path": "src/components/Effects/PlaceholderUntilLoaded.tsx",
    "content": "import { PropsWithChildren } from \"react\";\nimport { classNames } from \"../../util/classes\";\nimport { Slot } from \"../Slot\";\n\nexport interface PlaceholderUntilLoadedProps extends PropsWithChildren {\n  placeholder: React.ReactNode;\n  isLoading: boolean;\n  className?: string;\n  asChild?: boolean;\n}\n\nexport const PlaceholderUntilLoaded: React.FC<PlaceholderUntilLoadedProps> = ({\n  placeholder,\n  children,\n  isLoading,\n  className = \"\",\n  asChild,\n}) => {\n  const Component = asChild ? Slot : \"div\";\n  return (\n    <Component className={classNames(\"ink:relative\", className)}>\n      <div\n        className={classNames(\n          \"ink:absolute ink:inset-0\",\n          \"ink:transition-opacity ink:duration-100 ink:ease-in-out ink:opacity-100\",\n          !isLoading && \"ink:opacity-0 ink:pointer-events-none ink:select-none\"\n        )}\n      >\n        {placeholder}\n      </div>\n      {/** This placeholder is used to ensure the content is visible when the fade out is active */}\n      <div className={`${isLoading ? \"ink:opacity-0\" : \"ink:hidden\"}`}>\n        {placeholder}\n      </div>\n      <span className={isLoading ? \"ink:hidden\" : \"\"}>{children}</span>\n    </Component>\n  );\n};\n"
  },
  {
    "path": "src/components/Effects/index.ts",
    "content": "export * from \"./PlaceholderUntilLoaded\";\n"
  },
  {
    "path": "src/components/FieldLabel/FieldLabel.tsx",
    "content": "import { Description, Field, Label } from \"@headlessui/react\";\nimport { PropsWithChildren } from \"react\";\n\nexport interface FieldLabelProps extends PropsWithChildren {\n  label: React.ReactNode;\n  description?: React.ReactNode;\n}\n\nexport const FieldLabel: React.FC<FieldLabelProps> = ({\n  label,\n  description,\n  children,\n}) => {\n  return (\n    <Field className=\"ink:flex ink:flex-col ink:font-default ink:group\">\n      <div className=\"ink:flex ink:items-center ink:gap-1\">\n        {children}\n        <Label className=\"ink:cursor-pointer ink:h-3 ink:flex ink:items-center ink:justify-center ink:text-body-2-bold ink:text-text-default\">\n          {label}\n        </Label>\n      </div>\n\n      {description && (\n        <Description className=\"ink:text-body-3-regular ink:text-text-default\">\n          {description}\n        </Description>\n      )}\n    </Field>\n  );\n};\n\nFieldLabel.displayName = \"FieldLabel\";\n"
  },
  {
    "path": "src/components/FieldLabel/index.ts",
    "content": "export * from \"./FieldLabel\";\n"
  },
  {
    "path": "src/components/Input/Input.stories.tsx",
    "content": "import type { Meta, StoryObj } from \"@storybook/react\";\nimport { Input, type InputProps } from \"./index\";\nimport { InkIcon } from \"../..\";\n\nconst meta: Meta<InputProps> = {\n  title: \"Components/Input\",\n  component: Input,\n  tags: [\"autodocs\"],\n  args: {\n    placeholder: \"Placeholder\",\n    type: \"text\",\n  },\n};\n\nexport default meta;\ntype Story = StoryObj<typeof meta>;\n\nexport const Simple: Story = {\n  args: {},\n};\n\nexport const WithIconLeft: Story = {\n  args: {\n    iconLeft: <InkIcon.Search />,\n  },\n};\n\nexport const WithIconRight: Story = {\n  args: {\n    iconRight: <InkIcon.Deposit />,\n  },\n};\n"
  },
  {
    "path": "src/components/Input/Input.tsx",
    "content": "import React, { forwardRef } from \"react\";\nimport { classNames } from \"../../util/classes\";\n\nexport interface InputProps\n  extends React.InputHTMLAttributes<HTMLInputElement> {\n  className?: string;\n  iconLeft?: React.ReactNode;\n  iconRight?: React.ReactNode;\n}\n\nexport const Input = forwardRef<HTMLInputElement, InputProps>(\n  ({ className, iconLeft, iconRight, ...props }, ref) => {\n    const iconClasses =\n      \"ink:shrink-0 ink:size-3 ink:-my-1 ink:flex ink:items-center ink:justify-center ink:text-text-muted ink:group-focus-within:text-text-on-secondary ink:transition-colors ink:transition-default-animation\";\n    return (\n      <label\n        className={classNames(\n          \"ink:w-full ink:flex ink:items-center ink:justify-center ink:gap-1 ink:box-border ink:group\",\n          \"ink:p-2 ink:h-5\",\n          \"ink:font-default ink:rounded-xs ink:bg-button-secondary ink:text-body-3-regular ink:text-text-default\",\n          \"ink:border-1 ink:border-transparent ink:focus-within:border-text-on-secondary ink:transition-colors ink:transition-default-animation\",\n          className\n        )}\n      >\n        {iconLeft && <div className={iconClasses}>{iconLeft}</div>}\n        <input\n          className=\"ink:w-full ink:outline-none ink:box-border ink:-my-1 ink:placeholder:font-default ink:placeholder:text-body-3-regular ink:placeholder:text-text-muted\"\n          ref={ref}\n          {...props}\n        />\n        {iconRight && <div className={iconClasses}>{iconRight}</div>}\n      </label>\n    );\n  }\n);\n\nInput.displayName = \"Input\";\n"
  },
  {
    "path": "src/components/Input/index.ts",
    "content": "export * from \"./Input\";\n"
  },
  {
    "path": "src/components/ListItem/ListItem.tsx",
    "content": "import { ButtonHTMLAttributes, PropsWithChildren } from \"react\";\nimport { Slot, Slottable } from \"../Slot\";\nimport { classNames, variantClassNames } from \"../../util/classes\";\n\nexport interface ListItemProps\n  extends PropsWithChildren<ButtonHTMLAttributes<HTMLButtonElement>> {\n  variant?: \"default\" | \"secondary\" | \"error\" | \"muted\";\n  disabled?: boolean;\n  asChild?: boolean;\n  className?: string;\n  iconLeft?: React.ReactNode;\n  iconRight?: React.ReactNode;\n}\n\nexport const ListItem: React.FC<ListItemProps> = ({\n  children,\n  className,\n  asChild,\n  iconLeft,\n  iconRight,\n  variant = \"default\",\n  disabled,\n  ...props\n}) => {\n  const Component = asChild ? Slot : \"button\";\n  return (\n    <Component\n      disabled={disabled}\n      className={classNames(\n        \"ink:group ink:font-default ink:text-body-2-bold ink:cursor-pointer ink:box-border ink:no-underline\",\n        \"ink:bg-background-light-invisible ink:px-1.5 ink:py-2 ink:rounded-md ink:text-body-3-bold ink:text-text-default ink:hover:bg-background-container ink:disabled:bg-background-light-transparent-disabled ink:disabled:text-muted ink:active:bg-background-container/80 ink:data-active:bg-background-container/80\",\n        \"ink:w-full ink:flex ink:items-center ink:justify-start ink:gap-1.5 ink:h-5\",\n        variantClassNames(variant, {\n          default: \"\",\n          secondary:\n            \"ink:bg-button-secondary ink:hover:bg-button-secondary-hover ink:active:bg-button-secondary-pressed ink:data-active:bg-button-secondary-pressed ink:text-button-secondary-text\",\n          error: \"ink:text-status-error ink:hover:bg-status-error-bg\",\n          muted:\n            \"ink:bg-background-container ink:text-text-muted ink:border-1 ink:border-transparent ink:focus:border-text-on-secondary ink:transition-colors ink:transition-default-animation\",\n        }),\n        \"ink:data-disabled:text-text-muted ink:data-disabled:cursor-not-allowed\",\n        className\n      )}\n      {...props}\n    >\n      <Slottable child={children}>\n        {(child) => (\n          <>\n            {iconLeft && (\n              <div\n                className={classNames(\n                  \"ink:flex ink:items-center ink:justify-center ink:size-3 ink:-my-1.5\"\n                )}\n              >\n                {iconLeft}\n              </div>\n            )}\n            <div className=\"ink:flex-1 ink:flex ink:items-center ink:justify-start\">\n              {child}\n            </div>\n            {iconRight && (\n              <div\n                className={classNames(\n                  \"ink:flex ink:items-center ink:justify-center ink:size-3 ink:-my-1.5\"\n                )}\n              >\n                {iconRight}\n              </div>\n            )}\n          </>\n        )}\n      </Slottable>\n    </Component>\n  );\n};\n\nListItem.displayName = \"ListItem\";\n"
  },
  {
    "path": "src/components/ListItem/index.ts",
    "content": "export * from \"./ListItem\";\n"
  },
  {
    "path": "src/components/Listbox/Listbox.stories.tsx",
    "content": "import type { Meta, StoryObj } from \"@storybook/react\";\nimport {\n  Listbox,\n  ListboxButton,\n  ListboxOption,\n  ListboxOptions,\n  ListboxProps,\n} from \"./index\";\nimport { useState } from \"react\";\nimport { InkIcon } from \"../..\";\n\ninterface ListboxStoryItem {\n  value: string;\n  label: string;\n  iconLeft?: React.ReactNode;\n}\n\nconst defaultItems: ListboxStoryItem[] = [\n  { value: \"1\", label: \"Option 1\", iconLeft: <InkIcon.Home /> },\n  { value: \"2\", label: \"Option 2\", iconLeft: <InkIcon.Settings /> },\n  { value: \"3\", label: \"Option 3\", iconLeft: <InkIcon.Deposit /> },\n];\n\nconst meta: Meta<ListboxProps<ListboxStoryItem>> = {\n  title: \"Components/Listbox\",\n  component: Listbox,\n  tags: [\"autodocs\"],\n  argTypes: {},\n  args: {\n    children: (\n      <ListboxOptions>\n        {defaultItems.map((item) => (\n          <ListboxOption key={item.value} value={item}>\n            {item.label}\n          </ListboxOption>\n        ))}\n      </ListboxOptions>\n    ),\n  },\n};\n\nexport default meta;\ntype Story = StoryObj<typeof meta>;\n\nexport const Interactive: Story = {\n  args: {},\n  render: (args) => {\n    const [item, setValue] = useState<ListboxStoryItem>(defaultItems[0]);\n    return (\n      <Listbox value={item} onChange={setValue}>\n        <ListboxButton>Selected: {item.label}</ListboxButton>\n        {args.children}\n      </Listbox>\n    );\n  },\n};\n\nexport const WithOneDisabledOption: Story = {\n  args: {\n    children: (\n      <ListboxOptions>\n        {defaultItems.map((item, index) => (\n          <ListboxOption key={item.value} value={item} disabled={index === 1}>\n            {item.label}\n          </ListboxOption>\n        ))}\n      </ListboxOptions>\n    ),\n  },\n  render: (args) => {\n    const [item, setValue] = useState<ListboxStoryItem>(defaultItems[0]);\n    return (\n      <Listbox value={item} onChange={setValue}>\n        <ListboxButton>Selected: {item.label}</ListboxButton>\n        {args.children}\n      </Listbox>\n    );\n  },\n};\n\nexport const MultipleValues: Story = {\n  args: {\n    multiple: true,\n  },\n  render: (args) => {\n    const [items, setValues] = useState<ListboxStoryItem[]>([\n      defaultItems[0],\n      defaultItems[1],\n    ]);\n    return (\n      <Listbox {...args} value={items} onChange={setValues}>\n        <ListboxButton>\n          Selected:{\" \"}\n          {items.length ? items.map((item) => item.label).join(\", \") : \"None\"}\n        </ListboxButton>\n        {args.children}\n      </Listbox>\n    );\n  },\n};\n\nexport const WithIconsOnTheLeft: Story = {\n  args: {\n    children: (\n      <ListboxOptions>\n        {defaultItems.map((item) => (\n          <ListboxOption key={item.value} value={item} iconLeft={item.iconLeft}>\n            {item.label}\n          </ListboxOption>\n        ))}\n      </ListboxOptions>\n    ),\n  },\n  render: (args) => {\n    const [item, setValue] = useState<ListboxStoryItem>(defaultItems[0]);\n    return (\n      <Listbox value={item} onChange={setValue}>\n        <ListboxButton iconLeft={item.iconLeft}>\n          Selected: {item.label}\n        </ListboxButton>\n        {args.children}\n      </Listbox>\n    );\n  },\n};\n\nexport const MultipleValuesWithIconsOnTheRight: Story = {\n  args: {\n    multiple: true,\n    children: (\n      <ListboxOptions>\n        {defaultItems.map((item) => (\n          <ListboxOption\n            key={item.value}\n            value={item}\n            iconRight={item.iconLeft}\n          >\n            {item.label}\n          </ListboxOption>\n        ))}\n      </ListboxOptions>\n    ),\n  },\n  render: (args) => {\n    const [items, setValues] = useState<ListboxStoryItem[]>([\n      defaultItems[0],\n      defaultItems[1],\n    ]);\n    return (\n      <Listbox {...args} value={items} onChange={setValues}>\n        <ListboxButton>\n          Selected:{\" \"}\n          {items.length ? (\n            <div className=\"ink:flex ink:items-center ink:gap-1 ink:mx-0.5\">\n              {items.map((item) => (\n                <div className=\"ink:size-3\">{item.iconLeft}</div>\n              ))}\n            </div>\n          ) : (\n            \"None\"\n          )}\n        </ListboxButton>\n        {args.children}\n      </Listbox>\n    );\n  },\n};\n\nconst moreItems: ListboxStoryItem[] = [\n  { value: \"4\", label: \"Option 4\", iconLeft: <InkIcon.Home /> },\n  { value: \"5\", label: \"Option 5\", iconLeft: <InkIcon.Settings /> },\n  { value: \"6\", label: \"Option 6\", iconLeft: <InkIcon.Deposit /> },\n  { value: \"7\", label: \"Option 7\", iconLeft: <InkIcon.Home /> },\n  { value: \"8\", label: \"Option 8\", iconLeft: <InkIcon.Settings /> },\n  { value: \"9\", label: \"Option 9\", iconLeft: <InkIcon.Deposit /> },\n];\n\nexport const WithManyOptions: Story = {\n  args: {\n    children: (\n      <ListboxOptions>\n        {[...defaultItems, ...moreItems].map((item) => (\n          <ListboxOption key={item.value} value={item}>\n            {item.label}\n          </ListboxOption>\n        ))}\n      </ListboxOptions>\n    ),\n  },\n  render: (args) => {\n    const [item, setValue] = useState<ListboxStoryItem>(defaultItems[0]);\n    return (\n      <Listbox value={item} onChange={setValue}>\n        <ListboxButton>Selected: {item.label}</ListboxButton>\n        {args.children}\n      </Listbox>\n    );\n  },\n};\n\nexport const WithADifferentButtonVariant: Story = {\n  args: {\n    children: (\n      <ListboxOptions>\n        {[...defaultItems, ...moreItems].map((item) => (\n          <ListboxOption key={item.value} value={item}>\n            {item.label}\n          </ListboxOption>\n        ))}\n      </ListboxOptions>\n    ),\n  },\n  render: (args) => {\n    const [item, setValue] = useState<ListboxStoryItem>(defaultItems[0]);\n    return (\n      <Listbox value={item} onChange={setValue}>\n        <ListboxButton variant=\"muted\">Selected: {item.label}</ListboxButton>\n        {args.children}\n      </Listbox>\n    );\n  },\n};\n"
  },
  {
    "path": "src/components/Listbox/Listbox.tsx",
    "content": "import { Listbox as HeadlessListbox } from \"@headlessui/react\";\nimport { PropsWithChildren } from \"react\";\n\nexport interface ListboxProps<T> extends PropsWithChildren {\n  value: T;\n  onChange: (value: T) => void;\n  /** If you provide `multiple`, then `value` and `onChange` must use an array. */\n  multiple?: boolean;\n}\n\nexport const Listbox = <T extends object>({\n  children,\n  value,\n  onChange,\n  multiple,\n}: ListboxProps<T>) => {\n  return (\n    <HeadlessListbox multiple={multiple} value={value} onChange={onChange}>\n      {children}\n    </HeadlessListbox>\n  );\n};\n\nListbox.displayName = \"Listbox\";\n"
  },
  {
    "path": "src/components/Listbox/ListboxButton.tsx",
    "content": "import { ListboxButton as HeadlessListboxButton } from \"@headlessui/react\";\nimport { forwardRef } from \"react\";\nimport { InkIcon } from \"../..\";\nimport { ListItem, ListItemProps } from \"../ListItem\";\nimport { classNames } from \"../../util/classes\";\n\ninterface ListboxButtonProps extends ListItemProps {\n  className?: string;\n}\n\nexport const ListboxButton = forwardRef<HTMLButtonElement, ListboxButtonProps>(\n  ({ className, children, variant = \"secondary\", ...props }, ref) => {\n    return (\n      <HeadlessListboxButton\n        className={classNames(\n          className,\n          \"ink:focus-visible:outline-none ink:data-active:border-text-on-secondary ink:rounded-full ink:text-body-3-bold ink:text-text-muted ink:hover:text-text-default\"\n        )}\n        ref={ref}\n        as={ListItem}\n        variant={variant}\n        iconRight={<InkIcon.Chevron />}\n        {...props}\n      >\n        {children}\n      </HeadlessListboxButton>\n    );\n  }\n);\n\nListboxButton.displayName = \"ListboxButton\";\n"
  },
  {
    "path": "src/components/Listbox/ListboxOption.tsx",
    "content": "import { ListboxOption as HeadlessListboxOption } from \"@headlessui/react\";\nimport { classNames } from \"../../util/classes\";\nimport { ListItem, ListItemProps } from \"../ListItem\";\nimport { Checkbox, InkIcon } from \"../..\";\n\ninterface ListboxOptionProps<T> extends Omit<ListItemProps, \"value\"> {\n  value: T;\n  disabled?: boolean;\n}\n\nexport const ListboxOption = <T,>({\n  children,\n  disabled,\n  iconLeft,\n  iconRight,\n  ...props\n}: ListboxOptionProps<T>) => {\n  return (\n    <HeadlessListboxOption\n      className={classNames(\n        \"ink:flex ink:items-center ink:px-3 ink:py-2 ink:text-sm ink:cursor-pointer\"\n      )}\n      disabled={disabled}\n      as={ListItem}\n      iconLeft={iconLeft || (iconRight ? <Checkbox /> : undefined)}\n      iconRight={\n        <div className=\"ink:flex ink:items-center ink:justify-center ink:gap-1.5\">\n          {iconRight || (\n            <InkIcon.Check className=\"ink:not-in-data-selected:hidden\" />\n          )}\n        </div>\n      }\n      {...props}\n    >\n      {children}\n    </HeadlessListboxOption>\n  );\n};\n\nListboxOption.displayName = \"ListboxOption\";\n"
  },
  {
    "path": "src/components/Listbox/ListboxOptions.tsx",
    "content": "import { ListboxOptions as HeadlessListboxOptions } from \"@headlessui/react\";\nimport { PropsWithChildren } from \"react\";\nimport { Panel } from \"../Panel\";\nimport { classNames } from \"../../util/classes\";\n\nexport interface ListboxOptionsProps extends PropsWithChildren {\n  className?: string;\n}\n\nexport const ListboxOptions = ({\n  className,\n  children,\n}: ListboxOptionsProps) => {\n  return (\n    <HeadlessListboxOptions\n      className={classNames(\"ink:absolute ink:z-10 ink:box-border\", className)}\n      anchor=\"bottom end\"\n    >\n      <Panel className=\"ink:max-h-[300px] ink:gap-px\">{children}</Panel>\n    </HeadlessListboxOptions>\n  );\n};\n\nListboxOptions.displayName = \"ListboxOptions\";\n"
  },
  {
    "path": "src/components/Listbox/index.ts",
    "content": "export * from \"./Listbox\";\nexport * from \"./ListboxButton\";\nexport * from \"./ListboxOption\";\nexport * from \"./ListboxOptions\";\n"
  },
  {
    "path": "src/components/Modal/Layouts/CallToActionModalContent.tsx",
    "content": "export interface CallToActionModalContentProps {\n  title: React.ReactNode;\n  content: React.ReactNode;\n  button: React.ReactNode;\n}\n\nexport const CallToActionModalContent = ({\n  title,\n  content,\n  button,\n}: CallToActionModalContentProps) => {\n  return (\n    <div className=\"ink:flex ink:flex-col ink:justify-center ink:items-center ink:gap-5 ink:max-w-sm\">\n      <div className=\"ink:flex ink:flex-col ink:items-center ink:gap-2\">\n        <div className=\"ink:text-h4\">{title}</div>\n        <div className=\"ink:text-body-2-regular ink:text-center\">{content}</div>\n      </div>\n      {button}\n    </div>\n  );\n};\n"
  },
  {
    "path": "src/components/Modal/Layouts/index.ts",
    "content": "export {\n  CallToActionModalContent as CallToAction,\n  type CallToActionModalContentProps as CallToActionProps,\n} from \"./CallToActionModalContent\";\n"
  },
  {
    "path": "src/components/Modal/Modal.stories.tsx",
    "content": "import type { Meta, StoryObj } from \"@storybook/react\";\n\nimport { Button } from \"../Button\";\nimport {\n  ModalProvider,\n  useModalContext,\n  Modal,\n  type ModalProps,\n} from \"./index\";\nimport { fn } from \"@storybook/test\";\nimport { ModalLayout } from \".\";\n\nconst meta: Meta<ModalProps> = {\n  title: \"Components/Modal\",\n  decorators: [\n    (Story, { args }) => {\n      function ModalContent() {\n        const { isModalOpen, openModal } = useModalContext(args.id);\n        return (\n          <div className=\"ink:p-4\">\n            <Button variant=\"primary\" size=\"md\" onClick={openModal}>\n              {isModalOpen ? \"Close Modal\" : \"Open Modal\"}\n            </Button>\n            <Story />\n          </div>\n        );\n      }\n\n      return (\n        <ModalProvider>\n          <ModalContent />\n        </ModalProvider>\n      );\n    },\n  ],\n  component: Modal,\n  tags: [\"autodocs\"],\n  argTypes: {},\n  args: {\n    id: \"modal\",\n    title: \"Example modal\",\n    hasBackdrop: false,\n    onClose: fn(),\n  },\n};\n\nexport default meta;\ntype Story = StoryObj<typeof meta>;\n\nconst ModalContent = ({\n  closeModal,\n}: {\n  closeModal: (success: boolean) => void;\n}) => {\n  return (\n    <ModalLayout.CallToAction\n      title=\"Get started\"\n      content=\"Keep it simple, keep it actionable, give them a goal and they will come\"\n      button={\n        <Button\n          className=\"ink:w-full\"\n          variant=\"primary\"\n          size=\"lg\"\n          onClick={() => closeModal(true)}\n        >\n          Let's go\n        </Button>\n      }\n    />\n  );\n};\n\nexport const Simple: Story = {\n  args: {\n    children: ModalContent,\n  },\n};\n\nexport const Nested: Story = {\n  decorators: [\n    (Story) => {\n      return (\n        <>\n          <Story />\n          <Modal id=\"nested\" title=\"Nested modal\" size=\"md\" hasBackdrop>\n            {({ closeModal }) => (\n              <ModalLayout.CallToAction\n                title=\"A nested modal example\"\n                content=\"This one uses the backdrop and size='md'\"\n                button={\n                  <Button\n                    variant=\"primary\"\n                    size=\"lg\"\n                    onClick={() => closeModal()}\n                  >\n                    Close Nested\n                  </Button>\n                }\n              />\n            )}\n          </Modal>\n        </>\n      );\n    },\n  ],\n  args: {\n    children: () => {\n      const { openModal } = useModalContext(\"nested\");\n      return (\n        <div>\n          <Button\n            className=\"ink:w-full\"\n            variant=\"primary\"\n            size=\"lg\"\n            onClick={openModal}\n          >\n            Open Nested\n          </Button>\n        </div>\n      );\n    },\n  },\n};\n"
  },
  {
    "path": "src/components/Modal/Modal.tsx",
    "content": "import {\n  Dialog,\n  DialogBackdrop,\n  DialogPanel,\n  DialogTitle,\n} from \"@headlessui/react\";\nimport { useModalContext } from \"./ModalContext\";\nimport { classNames } from \"../../util/classes\";\nimport { InkIcon } from \"../..\";\nimport { useEffect, useRef } from \"react\";\nimport { InkHeader } from \"../../layout/InkParts\";\nimport { InkPanel } from \"../../layout/InkParts/InkPanel\";\n\nexport interface ModalProps<TOnCloseProps = boolean> {\n  id: string;\n  title?: string;\n  size?: \"lg\" | \"md\";\n  hasBackdrop?: boolean;\n  openOnMount?: boolean;\n  onClose?: (props?: TOnCloseProps) => void;\n  children: ({\n    closeModal,\n  }: {\n    closeModal: (props?: TOnCloseProps) => void;\n  }) => React.ReactNode;\n}\n\nexport const Modal = <TOnCloseProps,>({\n  id,\n  title,\n  size = \"lg\",\n  hasBackdrop,\n  openOnMount,\n  onClose,\n  children,\n}: ModalProps<TOnCloseProps>) => {\n  const { isModalOpen, closeModal, modalIndex, openModal } =\n    useModalContext(id);\n\n  const wasOpenedOnMount = useRef(false);\n  useEffect(() => {\n    if (openOnMount && !wasOpenedOnMount.current) {\n      openModal();\n      wasOpenedOnMount.current = true;\n    }\n  }, [openModal, openOnMount]);\n\n  const handleClose = (props?: TOnCloseProps) => {\n    closeModal();\n    onClose?.(props);\n  };\n\n  return (\n    <>\n      <Dialog\n        open={isModalOpen}\n        onClose={() => handleClose()}\n        transition\n        className=\"ink:relative ink:font-default ink:text-text-default\"\n        style={{ zIndex: 15 + modalIndex }}\n      >\n        {hasBackdrop && (\n          <DialogBackdrop\n            transition\n            className=\"ink:fixed ink:inset-0 ink:transition-opacity ink:transition-default-animation ink:backdrop-blur-lg ink:data-closed:opacity-0\"\n          />\n        )}\n        <div\n          className={classNames(\n            \"ink:fixed ink:inset-0 ink:p-4\",\n            \"ink:flex ink:items-center ink:justify-center\"\n          )}\n        >\n          <DialogPanel transition>\n            <InkPanel size={size} centered shadow>\n              <DialogTitle\n                as={InkHeader}\n                title={title}\n                icon={\n                  <InkIcon.Close\n                    className=\"ink:cursor-pointer ink:size-3\"\n                    onClick={() => handleClose()}\n                  />\n                }\n              />\n              <div className=\"ink:flex-1 ink:flex ink:flex-col ink:justify-center ink:items-center\">\n                {children({ closeModal: handleClose })}\n              </div>\n            </InkPanel>\n          </DialogPanel>\n        </div>\n      </Dialog>\n    </>\n  );\n};\n\nModal.displayName = \"Modal\";\n"
  },
  {
    "path": "src/components/Modal/ModalContext.tsx",
    "content": "\"use client\";\n\nimport { createContext, useContext, useMemo, useState } from \"react\";\n\nexport interface ModalManagementContextProps {\n  openModals: string[];\n  openModal: (id: string) => void;\n  closeModal: (id: string) => void;\n  isModalOpen: (id: string) => boolean;\n  closeAllModals: () => void;\n  getModalIndex: (id: string) => number;\n}\n\nexport const ModalManagementContext =\n  createContext<ModalManagementContextProps>({\n    openModals: [],\n    openModal: () => {},\n    closeModal: () => {},\n    isModalOpen: () => false,\n    closeAllModals: () => {},\n    getModalIndex: () => 0,\n  });\n\nexport interface ModalContextProps {\n  openModal: () => void;\n  closeModal: () => void;\n  isModalOpen: boolean;\n  modalIndex: number;\n}\n\nexport const useModalContext = (id: string): ModalContextProps => {\n  const { openModals, openModal, closeModal, isModalOpen, getModalIndex } =\n    useContext(ModalManagementContext);\n  return useMemo(\n    () => ({\n      openModal: () => openModal(id),\n      closeModal: () => closeModal(id),\n      isModalOpen: isModalOpen(id),\n      modalIndex: getModalIndex(id),\n    }),\n    [id, openModals]\n  );\n};\n\nexport const useModalManagementContext = (): ModalManagementContextProps => {\n  return useContext(ModalManagementContext);\n};\n\nexport const ModalProvider = ({ children }: { children: React.ReactNode }) => {\n  const [openModals, setOpenModals] = useState<string[]>([]);\n\n  const modalManagementContext: ModalManagementContextProps = useMemo(\n    () => ({\n      openModals,\n      openModal: (id: string) => {\n        setOpenModals((prev) => (prev.includes(id) ? prev : [...prev, id]));\n      },\n      closeModal: (id: string) => {\n        setOpenModals((prev) => prev.filter((modalId) => modalId !== id));\n      },\n      isModalOpen: (id: string) => openModals.includes(id),\n      closeAllModals: () => {\n        setOpenModals([]);\n      },\n      getModalIndex: (id: string) => openModals.indexOf(id),\n    }),\n    [openModals, setOpenModals]\n  );\n\n  return (\n    <ModalManagementContext.Provider value={modalManagementContext}>\n      {children}\n    </ModalManagementContext.Provider>\n  );\n};\n\nModalProvider.displayName = \"ModalProvider\";\n"
  },
  {
    "path": "src/components/Modal/index.ts",
    "content": "export * as ModalLayout from \"./Layouts\";\nexport * from \"./Modal\";\nexport * from \"./ModalContext\";\n"
  },
  {
    "path": "src/components/Panel/Panel.tsx",
    "content": "import { classNames } from \"../../util/classes\";\nimport { PropsWithChildren } from \"react\";\n\nexport interface PanelProps extends PropsWithChildren {\n  className?: string;\n}\n\nexport const Panel: React.FC<PanelProps> = ({ children, className }) => {\n  return (\n    <div\n      className={classNames(\n        \"ink:min-w-[240px] ink:mt-1 ink:p-1 ink:box-border\",\n        \"ink:rounded-lg ink:bg-background-light\",\n        \"ink:flex ink:flex-col ink:gap-1.5\",\n        \"ink:transition-opacity ink:transition-default-animation ink:opacity-100 ink:starting:opacity-0\",\n        \"ink:overflow-y-auto ink:h-full\",\n        className\n      )}\n    >\n      {children}\n    </div>\n  );\n};\n\nPanel.displayName = \"Panel\";\n"
  },
  {
    "path": "src/components/Panel/index.ts",
    "content": "export * from \"./Panel\";\n"
  },
  {
    "path": "src/components/Popover/Content/PopoverContentInfo.tsx",
    "content": "import React from \"react\";\n\nexport interface PopoverContentInfoProps {\n  title: string;\n  content?: React.ReactNode;\n  icon?: React.ReactNode;\n}\n\nexport const PopoverContentInfo: React.FC<PopoverContentInfoProps> = ({\n  title,\n  content,\n  icon,\n}) => {\n  return (\n    <div className=\"ink:text-body-2-bold ink:p-1.5 ink:bg-background-container ink:rounded-md ink:flex ink:gap-1.5 ink:font-default\">\n      <div className=\"ink:flex ink:flex-col ink:flex-1\">\n        <div className=\"ink:text-text-muted ink:text-caption-1-bold\">\n          {title}\n        </div>\n        <div className=\"ink:text-h4 ink:text-text-default\">{content}</div>\n      </div>\n      {icon && <div>{icon}</div>}\n    </div>\n  );\n};\n"
  },
  {
    "path": "src/components/Popover/Content/index.ts",
    "content": "export {\n  PopoverContentInfo as Info,\n  type PopoverContentInfoProps as InfoProps,\n} from \"./PopoverContentInfo\";\nexport * from \"../../ListItem\";\n"
  },
  {
    "path": "src/components/Popover/Popover.stories.tsx",
    "content": "import type { Meta, StoryObj } from \"@storybook/react\";\nimport {\n  Popover,\n  PopoverButton,\n  PopoverContent,\n  PopoverPanel,\n  type PopoverProps,\n} from \"./index\";\nimport { InkIcon } from \"../..\";\n\nconst meta: Meta<PopoverProps> = {\n  title: \"Components/Popover\",\n  component: Popover,\n  tags: [\"autodocs\"],\n  argTypes: {},\n  args: {\n    children: (\n      <>\n        <PopoverButton>Click Me</PopoverButton>\n        <PopoverPanel\n          headerContent={\n            <PopoverContent.Info title=\"Info\" content=\"Some content\" />\n          }\n        >\n          <PopoverContent.ListItem iconLeft={<InkIcon.Profile />}>\n            Item 1\n          </PopoverContent.ListItem>\n          <PopoverContent.ListItem iconLeft={<InkIcon.Settings />}>\n            Item 2\n          </PopoverContent.ListItem>\n          <PopoverContent.ListItem\n            iconLeft={<InkIcon.Copy />}\n            onClick={() =>\n              navigator.clipboard.writeText(\"You are a nice person\")\n            }\n          >\n            Copy Compliment To Clipboard\n          </PopoverContent.ListItem>\n          <PopoverContent.ListItem\n            variant=\"error\"\n            iconRight={<InkIcon.Error />}\n          >\n            Error Item\n          </PopoverContent.ListItem>\n          <PopoverContent.ListItem\n            asChild\n            iconRight={<InkIcon.Arrow className=\"ink:rotate-[225deg]\" />}\n          >\n            <a href=\"#something\" target=\"_self\">\n              Link Item\n            </a>\n          </PopoverContent.ListItem>\n        </PopoverPanel>\n      </>\n    ),\n  },\n};\n\nexport default meta;\ntype Story = StoryObj<typeof meta>;\n\nexport const Simple: Story = {\n  args: {},\n};\n"
  },
  {
    "path": "src/components/Popover/Popover.tsx",
    "content": "import { Popover as HeadlessPopover } from \"@headlessui/react\";\nimport { PropsWithChildren } from \"react\";\nimport { classNames } from \"../../util/classes\";\n\nexport interface PopoverProps extends PropsWithChildren {\n  className?: string;\n}\n\nexport const Popover = ({ children, className }: PopoverProps) => {\n  return (\n    <HeadlessPopover\n      className={classNames(\"ink:relative ink:font-default\", className)}\n    >\n      {children}\n    </HeadlessPopover>\n  );\n};\n\nPopover.displayName = \"Popover\";\n"
  },
  {
    "path": "src/components/Popover/PopoverButton.tsx",
    "content": "import { PopoverButton as HeadlessPopoverButton } from \"@headlessui/react\";\nimport { PropsWithChildren } from \"react\";\nimport { Button } from \"../Button\";\nimport { Slot } from \"../Slot\";\n\nexport interface PopoverButtonProps extends PropsWithChildren {\n  asChild?: boolean;\n  className?: string;\n  disabled?: boolean;\n  autoFocus?: boolean;\n}\n\nexport const PopoverButton: React.FC<PopoverButtonProps> = ({\n  asChild,\n  className,\n  disabled,\n  autoFocus,\n  ...props\n}) => {\n  return (\n    <HeadlessPopoverButton\n      as={asChild ? Slot : Button}\n      className={className}\n      disabled={disabled}\n      autoFocus={autoFocus}\n      {...(asChild ? {} : { variant: \"primary\", size: \"md\" })}\n      {...props}\n    />\n  );\n};\n\nPopoverButton.displayName = \"PopoverButton\";\n"
  },
  {
    "path": "src/components/Popover/PopoverPanel.tsx",
    "content": "import { PopoverPanel as HeadlessPopoverPanel } from \"@headlessui/react\";\nimport { PropsWithChildren } from \"react\";\nimport { Panel } from \"../Panel\";\nimport { classNames } from \"../../util/classes\";\n\nexport interface PopoverPanelProps extends PropsWithChildren {\n  className?: string;\n  headerContent?: React.ReactNode;\n}\n\nexport const PopoverPanel: React.FC<PopoverPanelProps> = ({\n  className,\n  headerContent,\n  children,\n}) => {\n  return (\n    <HeadlessPopoverPanel\n      className={classNames(\"ink:absolute ink:z-10\", className)}\n      anchor=\"bottom end\"\n    >\n      <Panel>\n        {headerContent && (\n          <div className=\"ink:flex ink:flex-col\">{headerContent}</div>\n        )}\n        <div className=\"ink:flex ink:flex-col ink:gap-0.5\">{children}</div>\n      </Panel>\n    </HeadlessPopoverPanel>\n  );\n};\n\nPopoverPanel.displayName = \"PopoverPanel\";\n"
  },
  {
    "path": "src/components/Popover/index.ts",
    "content": "export * as PopoverContent from \"./Content\";\nexport * from \"./Popover\";\nexport * from \"./PopoverButton\";\nexport * from \"./PopoverPanel\";\n"
  },
  {
    "path": "src/components/Radio/Radio.tsx",
    "content": "import { Radio as HeadlessRadio } from \"@headlessui/react\";\nimport { classNames } from \"../../util/classes\";\nimport { Slot } from \"../Slot\";\n\nexport interface RadioProps {\n  value: string;\n  asChild?: boolean;\n}\n\nexport const Radio: React.FC<RadioProps> = ({ value, asChild }) => {\n  const Component = asChild ? Slot : HeadlessRadio;\n  return (\n    <Component\n      value={value}\n      className={classNames(\n        \"ink:group ink:relative ink:flex ink:items-center ink:justify-center ink:size-3 ink:shrink-0 ink:cursor-pointer ink:rounded-full ink:box-border\",\n        \"ink:transition-colors ink:transition-default-animation\",\n        \"ink:border-2 ink:border-transparent ink:bg-button-secondary ink:shadow-xs\",\n        \"ink:ring-text-on-secondary ink:focus-visible:outline-none ink:focus-visible:text-on-primary ink:focus-visible:ring-2 ink:focus-visible:ring-offset-2\",\n        \"ink:data-checked:bg-button-primary ink:data-checked:hover:bg-button-primary-hover\"\n      )}\n    >\n      <div className=\"ink:absolute ink:inset-0 ink:flex ink:items-center ink:justify-center\">\n        <div className=\"ink:size-[10px] ink:rounded-full ink:bg-background-light ink:transition-opacity ink:transition-default-animation ink:opacity-0 ink:group-data-checked:opacity-100\" />\n      </div>\n    </Component>\n  );\n};\n\nRadio.displayName = \"Radio\";\n"
  },
  {
    "path": "src/components/Radio/RadioGroup.stories.tsx",
    "content": "import type { Meta, StoryObj } from \"@storybook/react\";\nimport { Radio, RadioGroup, RadioGroupProps, RadioLabel } from \"./index\";\nimport { fn } from \"@storybook/test\";\nimport { useEffect, useState } from \"react\";\n\nconst meta: Meta<RadioGroupProps> = {\n  title: \"Components/RadioGroup\",\n  component: RadioGroup,\n  tags: [\"autodocs\"],\n  args: {\n    onChange: fn(),\n    value: \"1\",\n    children: (\n      <>\n        <RadioLabel label=\"First\">\n          <Radio value=\"1\" />\n        </RadioLabel>\n        <RadioLabel label=\"Second\">\n          <Radio value=\"2\" />\n        </RadioLabel>\n      </>\n    ),\n  },\n};\n\nexport default meta;\ntype Story = StoryObj<typeof meta>;\n\nexport const Interactive: Story = {\n  render: (args) => {\n    const [value, setValue] = useState(args.value);\n    useEffect(() => {\n      setValue(args.value);\n    }, [args.value]);\n    return <RadioGroup {...args} value={value} onChange={setValue} />;\n  },\n};\n\nexport const WithDescription: Story = {\n  args: {\n    children: (\n      <>\n        <RadioLabel label=\"First\" description=\"This is a description\">\n          <Radio value=\"1\" />\n        </RadioLabel>\n        <RadioLabel label=\"Second\" description=\"This is another description\">\n          <Radio value=\"2\" />\n        </RadioLabel>\n      </>\n    ),\n  },\n  render: (args) => {\n    const [value, setValue] = useState(args.value);\n    useEffect(() => {\n      setValue(args.value);\n    }, [args.value]);\n    return <RadioGroup {...args} value={value} onChange={setValue} />;\n  },\n};\n"
  },
  {
    "path": "src/components/Radio/RadioGroup.tsx",
    "content": "import { RadioGroup as HeadlessRadioGroup } from \"@headlessui/react\";\nimport { PropsWithChildren } from \"react\";\n\nexport interface RadioGroupProps extends PropsWithChildren {\n  value: string;\n  onChange: (value: string) => void;\n}\n\nexport const RadioGroup: React.FC<RadioGroupProps> = ({\n  value,\n  onChange,\n  children,\n}) => {\n  return (\n    <HeadlessRadioGroup\n      className=\"ink:flex ink:flex-col ink:gap-2\"\n      value={value}\n      onChange={onChange}\n    >\n      {children}\n    </HeadlessRadioGroup>\n  );\n};\n\nRadioGroup.displayName = \"RadioGroup\";\n"
  },
  {
    "path": "src/components/Radio/RadioLabel.tsx",
    "content": "import { FieldLabel, FieldLabelProps } from \"../FieldLabel\";\n\nexport interface RadioLabelProps extends FieldLabelProps {}\n\nexport const RadioLabel: React.FC<RadioLabelProps> = (props) => {\n  return <FieldLabel {...props} />;\n};\n\nRadioLabel.displayName = \"RadioLabel\";\n"
  },
  {
    "path": "src/components/Radio/index.ts",
    "content": "export * from \"./Radio\";\nexport * from \"./RadioGroup\";\nexport * from \"./RadioLabel\";\n"
  },
  {
    "path": "src/components/SegmentedControl/SegmentedControl.stories.tsx",
    "content": "import type { Meta, StoryObj } from \"@storybook/react\";\nimport { fn } from \"@storybook/test\";\nimport { SegmentedControl, SegmentedControlProps } from \"./index\";\n\nconst meta: Meta<SegmentedControlProps<string>> = {\n  title: \"Components/SegmentedControl\",\n  component: SegmentedControl,\n  tags: [\"autodocs\"],\n  args: {\n    onOptionChange: fn(),\n    options: [\n      {\n        children: \"First\",\n        value: \"first\",\n        selectedByDefault: true,\n      },\n      {\n        children: \"Second\",\n        value: \"second\",\n      },\n      {\n        children: \"Third\",\n        value: \"third\",\n      },\n    ],\n  },\n};\n\nexport default meta;\ntype Story = StoryObj<typeof meta>;\n\nexport const Simple: Story = {\n  args: {},\n};\n\nexport const VariableTabWidth: Story = {\n  args: {\n    variableTabWidth: true,\n    options: Array.from(new Array(5)).map((_, i) => ({\n      selectedByDefault: i === 0,\n      children: (i + 1).toString().repeat(i + 1),\n      value: (i + 1).toString(),\n    })),\n  },\n};\n\nexport const AsLinks: Story = {\n  args: {\n    options: [\n      {\n        children: (\n          <a href=\"#first\" target=\"_self\">\n            First\n          </a>\n        ),\n        value: \"first\",\n        selectedByDefault: true,\n        asChild: true,\n      },\n      {\n        children: (\n          <a href=\"#second\" target=\"_self\">\n            Second\n          </a>\n        ),\n        value: \"second\",\n        asChild: true,\n      },\n      {\n        children: (\n          <a href=\"#third\" target=\"_self\">\n            Third\n          </a>\n        ),\n        value: \"third\",\n        asChild: true,\n      },\n    ],\n  },\n};\n\nexport const PrimaryVariant: Story = {\n  args: {\n    variant: \"primary\",\n    variableTabWidth: true,\n    options: [\n      {\n        children: <span>Home</span>,\n        value: \"yeah\",\n        selectedByDefault: true,\n      },\n      {\n        children: <span>Apps</span>,\n        value: \"done\",\n      },\n    ],\n  },\n};\n\nexport const TagVariant: Story = {\n  args: {\n    variant: \"tag\",\n    variableTabWidth: true,\n    options: [\n      {\n        children: <span>Home</span>,\n        value: \"yeah\",\n        selectedByDefault: true,\n      },\n      {\n        children: <span>Apps</span>,\n        value: \"done\",\n      },\n    ],\n  },\n};\n"
  },
  {
    "path": "src/components/SegmentedControl/SegmentedControl.tsx",
    "content": "import React, { useEffect, useMemo, useRef, useState } from \"react\";\nimport { classNames, variantClassNames } from \"../../util/classes\";\nimport { Slot } from \"../Slot\";\nimport { useWindowSize } from \"../../hooks/useWindowSize\";\n\nexport type SegmentedControlProps<TOptionValue extends string> = {\n  options: SegmentedControlOption<TOptionValue>[];\n  onOptionChange: (\n    option: SegmentedControlOption<TOptionValue>,\n    index: number\n  ) => void;\n  variableTabWidth?: boolean;\n  variant?: \"default\" | \"primary\" | \"tag\";\n};\n\nexport interface SegmentedControlOption<TOptionValue extends string> {\n  children: React.ReactNode;\n  value: TOptionValue;\n  selectedByDefault?: boolean;\n  asChild?: boolean;\n}\n\nexport const SegmentedControl = <TOptionValue extends string>({\n  options,\n  onOptionChange,\n  variableTabWidth,\n  variant = \"default\",\n}: SegmentedControlProps<TOptionValue>) => {\n  const itemsRef = useRef<Array<HTMLButtonElement | null>>([]);\n  const [selectedOption, setSelectedOption] = useState<TOptionValue | null>(\n    options.find((opt) => opt.selectedByDefault)?.value ?? null\n  );\n  const selectedIndex = useMemo(\n    () => options.findIndex((opt) => opt.value === selectedOption),\n    [options, selectedOption]\n  );\n  const windowWidth = useWindowSize();\n\n  const [isMounted, setIsMounted] = useState(false);\n  useEffect(() => {\n    // We need to wait for the component to be mounted before we can get the\n    // selected element's offsetLeft and offsetWidth.\n    setTimeout(() => {\n      setIsMounted(true);\n    }, 0);\n  }, []);\n\n  const { left, width } = useMemo(() => {\n    if (!isMounted) {\n      return { left: 0, width: 0 };\n    }\n    const selectedElement = itemsRef.current[selectedIndex];\n    return {\n      left: selectedElement?.offsetLeft || 0,\n      width: selectedElement?.offsetWidth || 0,\n    };\n  }, [itemsRef, selectedIndex, isMounted, windowWidth]);\n\n  return (\n    <div className=\"ink:relative ink:font-default ink:h-fit\">\n      <div\n        className={classNames(\n          \"ink:grid ink:h-5 ink:grid-flow-col ink:text-body-3-bold ink:rounded-md ink:p-0.5 ink:box-border ink:backdrop-blur-lg\",\n          variantClassNames(variant, {\n            default: \"ink:bg-background-container\",\n            primary: \"ink:bg-background-container\",\n            tag: \"\",\n          }),\n          variableTabWidth\n            ? \"ink:[grid-auto-columns:auto]\"\n            : \"ink:[grid-auto-columns:1fr]\"\n        )}\n      >\n        {options.map((option, index) => {\n          const ButtonComponent = option.asChild ? Slot : \"button\";\n\n          return (\n            <ButtonComponent\n              className={classNames(\n                \"ink:h-full ink:box-border ink:rounded-sm ink:relative ink:z-10 ink:transition-colors ink:transition-default-animation ink:hover:cursor-pointer ink:select-none ink:no-underline ink:flex ink:items-center ink:justify-center\",\n                selectedOption === option.value\n                  ? variantClassNames(variant, {\n                      default: \"ink:text-text-default\",\n                      primary: \"ink:text-text-on-primary\",\n                      tag: \"ink:text-text-default\",\n                    })\n                  : \"ink:text-text-muted ink:hover:text-text-default\",\n                variantClassNames(variant, {\n                  default: variableTabWidth ? \"ink:px-3\" : \"ink:px-4\",\n                  primary: variableTabWidth ? \"ink:px-3\" : \"ink:px-4\",\n                  tag: \"ink:px-2\",\n                })\n              )}\n              ref={(el) => {\n                itemsRef.current[index] = el;\n              }}\n              key={option.value}\n              onClick={() => {\n                setSelectedOption(option.value);\n                onOptionChange(option, index);\n              }}\n              draggable={false}\n            >\n              {option.children}\n            </ButtonComponent>\n          );\n        })}\n        {isMounted && selectedOption && (\n          <div\n            className=\"ink:absolute ink:py-0.5 ink:box-border ink:transition-[left,width] ink:transition-default-animation\"\n            style={{\n              top: 0,\n              bottom: 0,\n              left: `${left}px`,\n              width: `${width}px`,\n            }}\n          >\n            <div\n              className={classNames(\n                \"ink:w-full ink:h-full ink:rounded-sm\",\n                variantClassNames(variant, {\n                  default: \"ink:bg-background-light\",\n                  primary: \"ink:bg-button-primary\",\n                  tag: \"ink:bg-button-secondary\",\n                })\n              )}\n            />\n          </div>\n        )}\n      </div>\n    </div>\n  );\n};\n\nSegmentedControl.displayName = \"SegmentedControl\";\n"
  },
  {
    "path": "src/components/SegmentedControl/index.ts",
    "content": "export * from \"./SegmentedControl\";\n"
  },
  {
    "path": "src/components/Slot/Slot.tsx",
    "content": "/**\n * This is a modified version of Radix Primitives' Slot component.\n * It supports slottable children, which is useful for components that need to\n * render a slot inside a slot.\n *\n * It merges the initial implementation with the one that supports multiple children.\n *\n * See https://github.com/radix-ui/primitives/blob/main/packages/react/slot/src/Slot.tsx\n * for the original implementation.\n *\n * See https://github.com/radix-ui/primitives/blob/12e51326c7ddc7452916aabadf7db4a45352a6bd/packages/react/slot/src/Slot.tsx\n * for the variant that supports multiple children.\n */\n\nimport * as React from \"react\";\n\n// https://github.com/radix-ui/primitives/blob/main/packages/react/compose-refs/src/composeRefs.tsx\ntype PossibleRef<T> = React.Ref<T> | undefined;\n\nfunction setRef<T>(ref: PossibleRef<T>, value: T) {\n  if (typeof ref === \"function\") {\n    ref(value);\n  } else if (ref !== null && ref !== undefined) {\n    (ref as React.MutableRefObject<T>).current = value;\n  }\n}\n\nfunction composeRefs<T>(...refs: PossibleRef<T>[]) {\n  return (node: T) => refs.forEach((ref) => setRef(ref, node));\n}\n\n/* -------------------------------------------------------------------------------------------------\n * Slot\n * -----------------------------------------------------------------------------------------------*/\n\ninterface SlotProps extends React.HTMLAttributes<HTMLElement> {\n  children?: React.ReactNode;\n}\n\nconst Slot = React.forwardRef<HTMLElement, SlotProps>((props, forwardedRef) => {\n  const { children, ...slotProps } = props;\n\n  if (isSlottable(children)) {\n    const slottable = children;\n\n    return (\n      <SlotClone {...slotProps} ref={forwardedRef}>\n        {React.isValidElement<React.PropsWithChildren<unknown>>(\n          slottable.props.child\n        )\n          ? React.cloneElement(\n              slottable.props.child,\n              undefined,\n              slottable.props.children(slottable.props.child.props.children)\n            )\n          : null}\n      </SlotClone>\n    );\n  }\n\n  return (\n    <SlotClone {...slotProps} ref={forwardedRef}>\n      {children}\n    </SlotClone>\n  );\n});\n\nSlot.displayName = \"Slot\";\n\n/* -------------------------------------------------------------------------------------------------\n * SlotClone\n * -----------------------------------------------------------------------------------------------*/\n\ninterface SlotCloneProps {\n  children: React.ReactNode;\n}\n\nconst SlotClone = React.forwardRef<any, SlotCloneProps>(\n  (props, forwardedRef) => {\n    const { children, ...slotProps } = props;\n\n    if (React.isValidElement(children)) {\n      const childrenRef = getElementRef(children);\n\n      return React.cloneElement(children, {\n        ...mergeProps(slotProps, children.props as AnyProps),\n        // @ts-ignore\n        ref: forwardedRef\n          ? composeRefs(forwardedRef, childrenRef)\n          : childrenRef,\n      });\n    }\n\n    return React.Children.count(children) > 1\n      ? React.Children.only(null)\n      : null;\n  }\n);\n\nSlotClone.displayName = \"SlotClone\";\n\n/* -------------------------------------------------------------------------------------------------\n * Slottable\n * -----------------------------------------------------------------------------------------------*/\n\ntype SlottableProps = {\n  child: React.ReactNode;\n  children: (child: React.ReactNode) => React.JSX.Element;\n};\n\nconst Slottable = ({ child, children }: SlottableProps) => {\n  return children(child);\n};\n\n/* ---------------------------------------------------------------------------------------------- */\n\ntype AnyProps = Record<string, any>;\n\nfunction isSlottable(\n  child: React.ReactNode\n): child is React.ReactElement<SlottableProps> {\n  return React.isValidElement(child) && child.type === Slottable;\n}\n\nfunction mergeProps(slotProps: AnyProps, childProps: AnyProps) {\n  // all child props should override\n  const overrideProps = { ...childProps };\n\n  for (const propName in childProps) {\n    const slotPropValue = slotProps[propName];\n    const childPropValue = childProps[propName];\n\n    const isHandler = /^on[A-Z]/.test(propName);\n    if (isHandler) {\n      // if the handler exists on both, we compose them\n      if (slotPropValue && childPropValue) {\n        overrideProps[propName] = (...args: unknown[]) => {\n          childPropValue(...args);\n          slotPropValue(...args);\n        };\n      }\n      // but if it exists only on the slot, we use only this one\n      else if (slotPropValue) {\n        overrideProps[propName] = slotPropValue;\n      }\n    }\n    // if it's `style`, we merge them\n    else if (propName === \"style\") {\n      overrideProps[propName] = { ...slotPropValue, ...childPropValue };\n    } else if (propName === \"className\") {\n      overrideProps[propName] = [slotPropValue, childPropValue]\n        .filter(Boolean)\n        .join(\" \");\n    }\n  }\n\n  return { ...slotProps, ...overrideProps };\n}\n\n// Before React 19 accessing `element.props.ref` will throw a warning and suggest using `element.ref`\n// After React 19 accessing `element.ref` does the opposite.\n// https://github.com/facebook/react/pull/28348\n//\n// Access the ref using the method that doesn't yield a warning.\nfunction getElementRef(element: React.ReactElement) {\n  // React <=18 in DEV\n  let getter = Object.getOwnPropertyDescriptor(element.props, \"ref\")?.get;\n  let mayWarn = getter && \"isReactWarning\" in getter && getter.isReactWarning;\n  if (mayWarn) {\n    return (element as any).ref;\n  }\n\n  // React 19 in DEV\n  getter = Object.getOwnPropertyDescriptor(element, \"ref\")?.get;\n  mayWarn = getter && \"isReactWarning\" in getter && getter.isReactWarning;\n  if (mayWarn) {\n    return (element as any).ref;\n  }\n\n  // Not DEV\n  return (element as any).ref || (element as any).props.ref;\n}\n\nconst Root = Slot;\n\nexport { Root, Slot, Slottable };\nexport type { SlotProps };\n"
  },
  {
    "path": "src/components/Slot/index.ts",
    "content": "export * from \"./Slot\";\n"
  },
  {
    "path": "src/components/Tag/Tag.stories.tsx",
    "content": "import type { Meta, StoryObj } from \"@storybook/react\";\nimport { Tag, type TagProps } from \"./Tag\";\nimport { InkIcon } from \"../..\";\nimport { MatrixDecorator } from \"../../decorators/MatrixDecorator\";\n\nconst meta: Meta<TagProps> = {\n  decorators: [\n    MatrixDecorator<TagProps>({\n      first: {\n        key: \"variant\",\n        values: [\"fill\", \"outline\", \"filter\", \"featured\"],\n      },\n      second: { key: \"selected\", values: [false, true] },\n    }),\n  ],\n  title: \"Components/Tag\",\n  component: Tag,\n  tags: [\"autodocs\"],\n  args: {\n    children: \"Tag Content\",\n  },\n};\n\nexport default meta;\ntype Story = StoryObj<typeof meta>;\n\nexport const Default: Story = {\n  args: {},\n};\n\nexport const WithIcon: Story = {\n  args: {\n    icon: <InkIcon.InkLogo />,\n  },\n};\n"
  },
  {
    "path": "src/components/Tag/Tag.tsx",
    "content": "import { cva, type VariantProps } from \"class-variance-authority\";\nimport * as React from \"react\";\nimport { classNames } from \"../../util/classes\";\n\nconst tagVariants = cva(\n  \"ink:inline-flex ink:font-default ink:items-center ink:gap-1 ink:flex-shrink-0 ink:rounded-full ink:text-body-3-bold ink:font-bold ink:box-border\",\n  {\n    variants: {\n      variant: {\n        fill: \"ink:bg-background-container ink:text-text-muted ink:h-4 ink:px-1.5\",\n        outline:\n          \"ink:text-text-muted ink:border-background-container ink:border-[1.5px] ink:h-4 ink:px-1.5\",\n        filter:\n          \"ink:text-text-muted ink:hover:text-text-default ink:duration-200 ink:cursor-pointer ink:h-5 ink:px-1.5\",\n        featured:\n          \"ink:bg-background-container ink:text-text-on-secondary ink:text-caption-2-bold ink:h-3 ink:px-1 ink:rounded-xs\",\n        event:\n          \"ink:bg-button-secondary ink:backdrop-blur-lg ink:text-text-on-primary ink:text-caption-3-bold ink:h-5 ink:px-2\",\n      },\n      selected: {\n        true: \"\",\n        false: \"\",\n      },\n      hasIcon: {\n        true: \"\",\n        false: \"\",\n      },\n    },\n    compoundVariants: [\n      {\n        variant: \"filter\",\n        selected: true,\n        class: \"ink:bg-background-container ink:text-text-default\",\n      },\n    ],\n    defaultVariants: {\n      variant: \"fill\",\n      hasIcon: false,\n    },\n  }\n);\n\nexport interface TagProps\n  extends React.HTMLAttributes<HTMLDivElement>,\n    Omit<VariantProps<typeof tagVariants>, \"hasIcon\"> {\n  icon?: React.ReactNode;\n}\n\nexport const Tag = React.forwardRef<HTMLDivElement, TagProps>(function Tag(\n  { className, variant, selected, icon, children, ...props },\n  ref\n) {\n  return (\n    <div\n      ref={ref}\n      className={classNames(\n        tagVariants({ variant, selected, hasIcon: !!icon, className })\n      )}\n      {...props}\n    >\n      {icon && (\n        <div\n          className={classNames(\n            \"ink:flex ink:items-center ink:justify-center\",\n            variant === \"featured\" ? \"ink:size-1.5\" : \"ink:size-2\"\n          )}\n        >\n          {icon}\n        </div>\n      )}\n      {children}\n    </div>\n  );\n});\n\nTag.displayName = \"Tag\";\n"
  },
  {
    "path": "src/components/Tag/index.ts",
    "content": "export * from \"./Tag\";\n"
  },
  {
    "path": "src/components/Toggle/Toggle.stories.tsx",
    "content": "import type { Meta, StoryObj } from \"@storybook/react\";\nimport { Toggle, ToggleProps } from \"./index\";\nimport { fn } from \"@storybook/test\";\nimport { useEffect, useState } from \"react\";\n\nconst meta: Meta<ToggleProps> = {\n  title: \"Components/Toggle\",\n  component: Toggle,\n  tags: [\"autodocs\"],\n  args: {\n    checked: false,\n    onChange: fn(),\n  },\n};\n\nexport default meta;\ntype Story = StoryObj<typeof meta>;\n\nexport const Interactive: Story = {\n  args: {},\n  render: (args) => {\n    const [checked, setChecked] = useState(args.checked);\n    useEffect(() => {\n      setChecked(args.checked);\n    }, [args.checked]);\n    return <Toggle {...args} checked={checked} onChange={setChecked} />;\n  },\n};\n"
  },
  {
    "path": "src/components/Toggle/Toggle.tsx",
    "content": "import { Switch } from \"@headlessui/react\";\nimport { classNames } from \"../../util/classes\";\n\nexport interface ToggleProps {\n  checked: boolean;\n  onChange: (enabled: boolean) => void;\n}\n\nexport const Toggle: React.FC<ToggleProps> = ({ checked, onChange }) => {\n  return (\n    <Switch\n      checked={checked}\n      onChange={onChange}\n      className={classNames(\n        \"ink:group ink:relative ink:inline-flex ink:h-4 ink:w-6 ink:shrink-0 ink:cursor-pointer ink:rounded-full ink:box-border\",\n        \"ink:transition-colors ink:transition-default-animation\",\n        \"ink:bg-button-secondary\",\n        \"ink:ring-text-on-secondary ink:focus-visible:outline-none ink:focus-visible:text-on-primary ink:focus-visible:ring-2 ink:focus-visible:ring-offset-2\",\n        \"ink:data-checked:bg-status-success\",\n        \"ink:flex ink:items-center ink:p-0.5\"\n      )}\n    >\n      <span\n        style={\n          /**\n           * Somehow, we cannot use `calc(100%-var(--ink-spacing-1_5))` directly in the class name\n           * So this is a small workaround to make it work.\n           */\n          {\n            \"--ink-translate-x\": \"calc(100% - var(--ink-spacing-1))\",\n          } as React.CSSProperties\n        }\n        className={classNames(\n          \"ink:box-border ink:pointer-events-none ink:inline-block ink:size-3 ink:transform ink:rounded-full ink:bg-text-on-primary ink:shadow ink:ring-0\",\n          \"ink:transition ink:transition-default-animation\",\n          \"ink:group-data-checked:translate-x-(--ink-translate-x)\"\n        )}\n      />\n      <span className=\"ink:sr-only\">Toggle switch</span>\n    </Switch>\n  );\n};\n\nToggle.displayName = \"Toggle\";\n"
  },
  {
    "path": "src/components/Toggle/index.ts",
    "content": "export * from \"./Toggle\";\n"
  },
  {
    "path": "src/components/Typography/Typography.stories.tsx",
    "content": "import type { Meta, StoryObj } from \"@storybook/react\";\nimport { Typography, TypographyProps } from \"./Typography\";\n\nconst variants = [\n  \"display-1\",\n  \"display-2\",\n  \"h1\",\n  \"h2\",\n  \"h3\",\n  \"h4\",\n  \"h5\",\n  \"body-1\",\n  \"body-2-regular\",\n  \"body-2-bold\",\n  \"body-3-regular\",\n  \"body-3-bold\",\n  \"caption-1-regular\",\n  \"caption-1-bold\",\n  \"caption-2-regular\",\n  \"caption-2-bold\",\n] as const;\n\nconst meta: Meta<TypographyProps> = {\n  title: \"Design/Typography\",\n  decorators: [\n    (Story, { args }) => (\n      <div className=\"ink:p-4 ink:flex ink:flex-col ink:gap-4 ink:text-text-default\">\n        {variants.map((variant) => (\n          <Story\n            key={variant}\n            args={{\n              children: (\n                <div>\n                  ink:text-{variant} - The quick brown fox jumps over the lazy\n                  dog\n                </div>\n              ),\n              ...args,\n              variant,\n            }}\n          />\n        ))}\n      </div>\n    ),\n  ],\n  component: Typography,\n  parameters: {\n    layout: \"centered\",\n  },\n  tags: [\"autodocs\"],\n  args: {},\n};\n\nexport default meta;\ntype Story = StoryObj<typeof meta>;\n\nexport const Simple: Story = {\n  args: {},\n};\n"
  },
  {
    "path": "src/components/Typography/Typography.tsx",
    "content": "import { classNames, variantClassNames } from \"../../util/classes\";\nimport { HTMLAttributes, PropsWithChildren } from \"react\";\nimport { Slot } from \"../Slot\";\n\nexport interface TypographyProps\n  extends PropsWithChildren,\n    HTMLAttributes<HTMLHeadingElement | HTMLDivElement> {\n  variant:\n    | \"display-1\"\n    | \"display-2\"\n    | \"h1\"\n    | \"h2\"\n    | \"h3\"\n    | \"h4\"\n    | \"h5\"\n    | \"body-1\"\n    | \"body-2-regular\"\n    | \"body-2-bold\"\n    | \"body-3-regular\"\n    | \"body-3-bold\"\n    | \"caption-1-regular\"\n    | \"caption-1-bold\"\n    | \"caption-2-regular\"\n    | \"caption-2-bold\";\n  className?: string;\n  asChild?: boolean;\n}\n\nexport const Typography: React.FC<TypographyProps> = ({\n  variant,\n  className,\n  children,\n  asChild,\n  ...restProps\n}) => {\n  const Component = asChild ? Slot : \"div\";\n  return (\n    <Component\n      className={classNames(\n        \"ink:font-default\",\n        /**\n         * It would be tempting to put those in a string template, but then Tailwind won't be able to detect the classes here\n         * and won't include them in the production build until we actually use them somewhere.\n         **/\n        variantClassNames(variant, {\n          \"display-1\": \"ink:text-display-1\",\n          \"display-2\": \"ink:text-display-2\",\n          h1: \"ink:text-h1\",\n          h2: \"ink:text-h2\",\n          h3: \"ink:text-h3\",\n          h4: \"ink:text-h4\",\n          h5: \"ink:text-h5\",\n          \"body-1\": \"ink:text-body-1\",\n          \"body-2-regular\": \"ink:text-body-2-regular\",\n          \"body-2-bold\": \"ink:text-body-2-bold\",\n          \"body-3-regular\": \"ink:text-body-3-regular\",\n          \"body-3-bold\": \"ink:text-body-3-bold\",\n          \"caption-1-regular\": \"ink:text-caption-1-regular\",\n          \"caption-1-bold\": \"ink:text-caption-1-bold\",\n          \"caption-2-regular\": \"ink:text-caption-2-regular\",\n          \"caption-2-bold\": \"ink:text-caption-2-bold\",\n        }),\n        className\n      )}\n      {...restProps}\n    >\n      {children}\n    </Component>\n  );\n};\n\nTypography.displayName = \"Typography\";\n"
  },
  {
    "path": "src/components/Typography/index.ts",
    "content": "export * from \"./Typography\";\n"
  },
  {
    "path": "src/components/Wallet/ConnectWallet.stories.tsx",
    "content": "import type { Meta, StoryObj } from \"@storybook/react\";\n\nimport { ConnectWallet, type ConnectWalletProps } from \"./index\";\nimport { WalletProvider } from \"../../decorators/WalletProvider\";\nimport { PopoverContent } from \"../Popover\";\nimport { InkIcon } from \"../..\";\n\nconst meta: Meta<ConnectWalletProps> = {\n  title: \"Components/ConnectWallet\",\n  decorators: [\n    WalletProvider,\n    (Story) => <div className=\"ink:min-h-[300px]\">{Story()}</div>,\n  ],\n  component: ConnectWallet,\n  tags: [\"autodocs\"],\n  argTypes: {},\n  args: {},\n};\n\nexport default meta;\ntype Story = StoryObj<typeof meta>;\n\nexport const Simple: Story = {\n  args: {},\n};\n\nexport const WithProfileAndSettings: Story = {\n  args: {\n    listItems: (\n      <>\n        <PopoverContent.ListItem iconLeft={<InkIcon.Profile />}>\n          Profile\n        </PopoverContent.ListItem>\n        <PopoverContent.ListItem iconLeft={<InkIcon.Settings />}>\n          Settings\n        </PopoverContent.ListItem>\n      </>\n    ),\n  },\n};\n"
  },
  {
    "path": "src/components/Wallet/ConnectWallet.tsx",
    "content": "import { useAccount, useBalance, useConnect, useDisconnect } from \"wagmi\";\nimport { Button } from \"../Button\";\nimport {\n  InkIcon,\n  Popover,\n  PopoverButton,\n  PopoverContent,\n  PopoverPanel,\n} from \"../..\";\nimport { Address } from \"viem\";\nimport { trimAddress } from \"../../util/trim\";\nimport { inkSepolia } from \"wagmi/chains\";\nimport { useEnsImageOrDefault } from \"../../hooks/useEnsImageOrDefault\";\nimport { useEnsNameOrDefault } from \"../../hooks/useEnsNameOrDefault\";\nimport { PlaceholderUntilLoaded } from \"../Effects\";\nimport { useIsUnderWindowBreakpoint } from \"../../hooks/useWindowBreakpoint\";\nimport { useState } from \"react\";\nimport { useEffect } from \"react\";\n\nexport interface ConnectWalletProps {\n  className?: string;\n  listItems?: React.ReactNode;\n}\n\nexport const ConnectWallet: React.FC<ConnectWalletProps> = ({\n  className,\n  listItems,\n}) => {\n  const { address, isConnected } = useAccount();\n  const { connect, connectors } = useConnect();\n  const ensName = useEnsNameOrDefault({ address });\n  const ensImage = useEnsImageOrDefault({ address });\n  const isSmallWindow = useIsUnderWindowBreakpoint({ size: \"sm\" });\n\n  const [hasLoaded, setHasLoaded] = useState(false);\n  useEffect(() => {\n    setHasLoaded(true);\n  }, []);\n\n  return (\n    <Popover>\n      <PopoverButton asChild>\n        <Button\n          variant={isConnected ? \"wallet\" : \"primary\"}\n          className={className}\n          iconLeft={\n            isConnected && !isSmallWindow ? (\n              <img src={ensImage} alt={`avatar for ${ensName}`} />\n            ) : undefined\n          }\n          rounded={isSmallWindow ? \"full\" : \"default\"}\n        >\n          <PlaceholderUntilLoaded\n            placeholder={\n              <>\n                <div className=\"ink:hidden ink:sm:flex ink:items-center ink:justify-center\">\n                  Connecting...\n                </div>\n                <span className=\"ink:inline ink:sm:hidden\">···</span>\n              </>\n            }\n            isLoading={!hasLoaded}\n          >\n            {isConnected ? (\n              <>\n                <div className=\"ink:size-4 ink:*:w-4 ink:*:rounded-full ink:block ink:sm:hidden\">\n                  <img src={ensImage} alt={`avatar for ${ensName}`} />\n                </div>\n                <span className=\"ink:hidden ink:sm:inline\">{ensName}</span>\n              </>\n            ) : (\n              <>\n                <span className=\"ink:hidden ink:sm:inline\">Connect</span>\n                <InkIcon.Wallet className=\"ink:block ink:sm:hidden\" />\n              </>\n            )}\n          </PlaceholderUntilLoaded>\n        </Button>\n      </PopoverButton>\n\n      <PopoverPanel\n        className=\"ink:z-100\"\n        headerContent={\n          isConnected ? (\n            <ConnectedWalletPopupHeader address={address!} />\n          ) : undefined\n        }\n      >\n        {isConnected ? (\n          <ConnectedWalletSection address={address!} listItems={listItems} />\n        ) : (\n          <div className=\"ink:flex ink:flex-col ink:gap-2\">\n            {connectors.map((connector) => (\n              <PopoverContent.ListItem\n                key={connector.uid}\n                onClick={() => connect({ connector })}\n              >\n                {connector.name}\n              </PopoverContent.ListItem>\n            ))}\n          </div>\n        )}\n      </PopoverPanel>\n    </Popover>\n  );\n};\n\nconst ConnectedWalletPopupHeader = ({ address }: { address: Address }) => {\n  const {\n    isLoading,\n    isSuccess,\n    data: balance,\n  } = useBalance({\n    address,\n    chainId: inkSepolia.id,\n  });\n\n  if (isLoading) {\n    return null;\n  }\n\n  return (\n    <div className=\"ink:text-body-2-bold ink:p-1.5 ink:bg-background-container ink:rounded-md ink:flex ink:gap-1.5 ink:font-default\">\n      <div className=\"ink:flex ink:flex-col ink:flex-1\">\n        <div className=\"ink:text-text-muted ink:text-caption-1-bold\">\n          Balance\n        </div>\n        <div className=\"ink:text-h4 ink:text-text-default\">\n          {isSuccess ? `${balance.value} ${balance.symbol}` : \"...\"}\n        </div>\n      </div>\n      <div>\n        <Button asChild variant=\"primary\" rounded=\"full\">\n          <a href=\"https://inkonchain.com/bridge\" target=\"_blank\">\n            <InkIcon.Deposit />\n          </a>\n        </Button>\n      </div>\n    </div>\n  );\n};\n\nconst ConnectedWalletSection = ({\n  address,\n  listItems,\n}: {\n  address: Address;\n  listItems?: React.ReactNode;\n}) => {\n  const { disconnect } = useDisconnect();\n  return (\n    <>\n      {listItems}\n      <PopoverContent.ListItem\n        iconLeft={<InkIcon.Copy />}\n        onClick={() => navigator.clipboard.writeText(address)}\n      >\n        {trimAddress(address)}\n      </PopoverContent.ListItem>\n      <PopoverContent.ListItem\n        variant=\"error\"\n        iconLeft={<InkIcon.Disconnect />}\n        onClick={() => disconnect()}\n      >\n        Disconnect\n      </PopoverContent.ListItem>\n    </>\n  );\n};\n\nConnectWallet.displayName = \"ConnectWallet\";\n"
  },
  {
    "path": "src/components/Wallet/index.ts",
    "content": "export * from \"./ConnectWallet\";\n"
  },
  {
    "path": "src/components/index.ts",
    "content": "export * from \"./Alert\";\nexport * from \"./Button\";\nexport * from \"./Card\";\nexport * from \"./Checkbox\";\nexport * from \"./Input\";\nexport * from \"./Listbox\";\nexport * from \"./ListItem\";\nexport * from \"./Modal\";\nexport * from \"./Popover\";\nexport * from \"./SegmentedControl\";\nexport * from \"./Tag\";\nexport * from \"./Toggle\";\nexport * from \"./Typography\";\nexport * from \"./Wallet\";\n"
  },
  {
    "path": "src/decorators/ContainerColor.tsx",
    "content": "import { Decorator } from \"@storybook/react\";\n\nexport const ContainerColor: Decorator = (Story) => {\n  return (\n    <div className=\"ink:bg-background-container\">\n      <Story />\n    </div>\n  );\n};\n"
  },
  {
    "path": "src/decorators/MatrixDecorator.tsx",
    "content": "import { Decorator } from \"@storybook/react\";\n\ntype MatrixDefinition<TProps, TKey extends keyof TProps = keyof TProps> = {\n  [P in TKey]: {\n    key: P;\n    values: Array<TProps[P]>;\n  };\n}[TKey];\n\nexport const MatrixDecorator =\n  <\n    TProps,\n    TFirst extends keyof TProps = keyof TProps,\n    TSecond extends keyof TProps = keyof TProps,\n  >({\n    first: { key: firstKey, values: firstValues },\n    second: { key: secondKey, values: secondValues },\n  }: {\n    first: MatrixDefinition<TProps, TFirst>;\n    second: MatrixDefinition<TProps, TSecond>;\n  }): Decorator =>\n  (Story, { args, parameters }) => {\n    if (parameters.disableMatrix) return <Story />;\n\n    return (\n      <div className=\"ink:flex ink:flex-col ink:items-center ink:gap-2\">\n        {firstValues.map((firstValue, i) => (\n          <div key={`${String(firstKey)}-${i}`} className=\"ink:flex ink:gap-2\">\n            {secondValues.map((secondValue, j) => {\n              return (\n                <Story\n                  key={`${String(firstKey)}-${i}-${j}`}\n                  args={{\n                    ...args,\n                    [firstKey]: firstValue,\n                    [secondKey]: secondValue,\n                  }}\n                />\n              );\n            })}\n          </div>\n        ))}\n      </div>\n    );\n  };\n"
  },
  {
    "path": "src/decorators/WalletProvider.tsx",
    "content": "import { QueryClient, QueryClientProvider } from \"@tanstack/react-query\";\nimport { metaMask, mock } from \"wagmi/connectors\";\nimport { inkConfig } from \"../providers.index\";\nimport { createConfig, WagmiProvider } from \"wagmi\";\nimport { Decorator } from \"@storybook/react\";\nimport { DEFAULT_MOCK_ACCOUNT } from \"../util/mocks\";\n\nconst config = createConfig({\n  connectors: [\n    metaMask(),\n    mock({\n      accounts: [DEFAULT_MOCK_ACCOUNT],\n      features: {\n        defaultConnected: true,\n        reconnect: true,\n      },\n    }),\n  ],\n  chains: inkConfig.chains,\n  transports: inkConfig.transports,\n  ssr: true,\n});\n\nconst queryClient = new QueryClient();\n\nexport const WalletProvider: Decorator = (Story) => {\n  return (\n    <WagmiProvider config={config}>\n      <QueryClientProvider client={queryClient}>\n        <Story />\n      </QueryClientProvider>\n    </WagmiProvider>\n  );\n};\n"
  },
  {
    "path": "src/global.d.ts",
    "content": "/// <reference types=\"vite-plugin-svgr/client\" />\n\ndeclare module \"*?base64\" {\n  const value: string;\n  export default value;\n}\n\ntype StringWithAutocomplete<T> = T | (string & Record<never, never>);\n"
  },
  {
    "path": "src/hooks/index.ts",
    "content": "export * from \"./useInkThemeClass\";\n"
  },
  {
    "path": "src/hooks/useEnsImageOrDefault.ts",
    "content": "import { useEnsAvatar } from \"wagmi\";\nimport Avatar from \"../images/avatar.png?base64\";\nimport { normalize } from \"viem/ens\";\nimport { Address } from \"viem\";\n\nexport const useEnsImageOrDefault = ({ address }: { address?: Address }) => {\n  const { data: avatar } = useEnsAvatar({ name: normalize(address || \"\") });\n\n  return avatar || Avatar;\n};\n"
  },
  {
    "path": "src/hooks/useEnsNameOrDefault.ts",
    "content": "import { Address } from \"viem\";\nimport { useEnsName } from \"wagmi\";\nimport { trimAddress } from \"../util/trim\";\nimport { DEFAULT_MOCK_ACCOUNT } from \"../util/mocks\";\n\nexport const useEnsNameOrDefault = ({\n  address,\n}: {\n  address: Address | undefined;\n}) => {\n  const { data: ensName } = useEnsName({ address });\n\n  if (address === DEFAULT_MOCK_ACCOUNT) {\n    return \"mock.account.ink.eth\";\n  }\n\n  return ensName ?? trimAddress(address);\n};\n"
  },
  {
    "path": "src/hooks/useInkThemeClass.ts",
    "content": "import { useEffect } from \"react\";\n\nconst themeClasses = [\"dark\", \"light\", \"contrast\", \"neo\", \"morpheus\"] as const;\n\nexport function useInkThemeClass(\n  theme: \"default\" | (typeof themeClasses)[number]\n) {\n  useEffect(() => {\n    themeClasses.forEach((t) => {\n      const className = `ink:${t}-theme`;\n      if (theme === t) {\n        document.documentElement.classList.add(className);\n      } else {\n        document.documentElement.classList.remove(className);\n      }\n    });\n  }, [theme]);\n}\n"
  },
  {
    "path": "src/hooks/useWindowBreakpoint.ts",
    "content": "import { useMemo } from \"react\";\nimport { useWindowSize } from \"./useWindowSize\";\n\nconst BREAKPOINTS = {\n  sm: 640,\n  md: 768,\n  lg: 1024,\n};\n\nexport const useIsUnderWindowBreakpoint = ({\n  size,\n}: {\n  size: keyof typeof BREAKPOINTS;\n}) => {\n  const { width } = useWindowSize();\n\n  return useMemo(() => {\n    return width < BREAKPOINTS[size];\n  }, [width, size]);\n};\n"
  },
  {
    "path": "src/hooks/useWindowSize.ts",
    "content": "import { useState, useEffect } from \"react\";\n\ninterface WindowSize {\n  width: number;\n  height: number;\n}\n\nexport const useWindowSize = (): WindowSize => {\n  const [windowSize, setWindowSize] = useState<WindowSize>({\n    width: window.innerWidth,\n    height: window.innerHeight,\n  });\n\n  useEffect(() => {\n    const handleResize = () => {\n      setWindowSize({\n        width: window.innerWidth,\n        height: window.innerHeight,\n      });\n    };\n\n    window.addEventListener(\"resize\", handleResize);\n\n    return () => {\n      window.removeEventListener(\"resize\", handleResize);\n    };\n  }, []);\n\n  return windowSize;\n};\n"
  },
  {
    "path": "src/icons/AllIcons.css",
    "content": ".tooltip-on-hover {\n  position: relative;\n}\n\n.tooltip-on-hover:before {\n  display: block;\n  content: attr(data-title);\n  position: absolute;\n  top: 0;\n  transform: translateX(-50%) translateY(-125%);\n  background-color: var(--ink-button-primary);\n  color: var(--ink-text-on-primary);\n  padding: 4px 8px;\n  border-radius: 8px;\n  opacity: 0;\n  z-index: 1;\n  pointer-events: none;\n  width: 0;\n  left: 0;\n}\n\n.tooltip-on-hover:hover:before {\n  left: 50%;\n  transition: opacity 0.1s ease-in-out;\n  opacity: 1;\n  width: auto;\n}\n"
  },
  {
    "path": "src/icons/AllIcons.tsx",
    "content": "import { classNames } from \"../util/classes\";\nimport * as Icons from \"./index\";\nimport \"./AllIcons.css\";\nimport React from \"react\";\n\ninterface IconsOrFolder {\n  [key: string]:\n    | React.ComponentType<React.SVGProps<SVGSVGElement>>\n    | IconsOrFolder;\n}\n\nexport const AllIcons: React.FC<{\n  containerClassName?: string;\n  iconClassName?: string;\n}> = ({ containerClassName, iconClassName }) => {\n  return (\n    <div\n      className={classNames(\n        \"ink:flex ink:flex-wrap ink:gap-2 ink:text-text-default\",\n        containerClassName\n      )}\n    >\n      <div className=\"ink:text-body-2-bold\">Click to copy icon name</div>\n      <IconsOrFolder\n        title=\"InkIcon\"\n        iconsOrFolder={Icons}\n        iconClassName={classNames(\"tooltip-on-hover\", iconClassName)}\n      />\n    </div>\n  );\n};\n\nfunction IconsOrFolder({\n  title,\n  iconsOrFolder,\n  iconClassName,\n}: {\n  title: string;\n  iconsOrFolder: IconsOrFolder;\n  iconClassName?: string;\n}) {\n  return (\n    <div className={classNames(\"ink:flex ink:flex-col ink:gap-2 ink:pl-2\")}>\n      <div className=\"ink:text-caption-1-bold ink:text-text-muted\">{title}</div>\n\n      <div className=\"ink:flex ink:flex-wrap ink:gap-2\">\n        {Object.entries(iconsOrFolder).map(([name, IconOrFolder]) => {\n          if (!isIconFolder(IconOrFolder)) {\n            return (\n              <div\n                key={name}\n                className=\"tooltip-on-hover ink:cursor-pointer ink:whitespace-nowrap\"\n                data-title={`<${title}.${name} />`}\n                onClick={() =>\n                  navigator.clipboard.writeText(`<${title}.${name} />`)\n                }\n              >\n                <IconOrFolder\n                  className={classNames(\"ink:size-4\", iconClassName)}\n                />\n              </div>\n            );\n          }\n        })}\n      </div>\n\n      {Object.entries(iconsOrFolder).map(([name, IconOrFolder]) => {\n        if (isIconFolder(IconOrFolder)) {\n          return (\n            <IconsOrFolder\n              key={name}\n              title={`${title}.${name}`}\n              iconsOrFolder={IconOrFolder}\n              iconClassName={iconClassName}\n            />\n          );\n        }\n      })}\n    </div>\n  );\n}\n\nfunction isIconFolder(icon: IconsOrFolder[string]): icon is IconsOrFolder {\n  return typeof icon === \"object\";\n}\n"
  },
  {
    "path": "src/icons/Icons.stories.ts",
    "content": "import type { Meta, StoryObj } from \"@storybook/react\";\nimport { AllIcons } from \"./AllIcons\";\n\nconst meta: Meta<{}> = {\n  title: \"Design/Icons\",\n  component: AllIcons,\n  parameters: {\n    layout: \"centered\",\n  },\n  tags: [\"autodocs\"],\n  argTypes: {},\n  args: {},\n};\n\nexport default meta;\ntype Story = StoryObj<typeof meta>;\n\nexport const AllIconsRow: Story = {\n  args: {},\n};\n\nexport const AllIconsWithColor: Story = {\n  args: {\n    containerClassName: \"ink:text-button-primary\",\n  },\n};\n\nexport const AllIconsWithDifferentSize: Story = {\n  args: {\n    iconClassName: \"ink:size-2\",\n  },\n};\n"
  },
  {
    "path": "src/icons/Logo/Placeholder.tsx",
    "content": "import { SVGProps, useId } from \"react\";\n\nexport const Placeholder = (props: SVGProps<SVGSVGElement>) => {\n  const id = useId();\n  return (\n    <svg\n      width=\"48\"\n      height=\"48\"\n      viewBox=\"0 0 48 48\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n      {...props}\n    >\n      <mask\n        id={`${id}-mask`}\n        style={{ maskType: \"alpha\" }}\n        maskUnits=\"userSpaceOnUse\"\n        x=\"0\"\n        y=\"0\"\n        width=\"48\"\n        height=\"48\"\n      >\n        <path\n          d=\"M47.9885 24.0077C48.0525 22.8733 47.8445 22.0106 47.4766 21.2916C46.4847 19.1668 44.3089 18.6395 43.253 15.2365C42.805 14.0543 42.837 12.904 42.821 11.7696C42.837 10.9229 42.821 10.0921 42.4851 9.22934C42.2291 8.49441 41.7811 7.75949 40.9652 7.02457C40.9172 6.97664 40.8692 6.92871 40.8212 6.88078C40.4052 6.43344 39.9733 6.1139 39.5253 5.87426C38.3095 5.13933 37.2535 5.13934 36.1017 5.13934C34.9818 5.07543 33.8299 5.0275 32.726 4.61211C29.1423 3.28605 28.6944 1.43277 26.7426 0.538082C26.0226 0.170621 25.1587 -0.0530492 24.0228 0.0108571C23.9108 0.0108571 23.8149 0.0268346 23.7029 0.0268346C23.0949 0.010858 22.551 0.106717 22.071 0.266483C19.6651 0.898752 19.1697 2.59445 16.7115 4.0539C16.6591 4.08501 16.6025 4.11161 16.5479 4.13864C16.5085 4.15814 16.467 4.17528 16.4277 4.19492C13.4723 5.6717 11.7232 4.87105 9.81621 5.36301C8.9043 5.53875 7.99239 5.98609 7.04848 7.04055C6.9857 7.1346 6.89377 7.20649 6.81259 7.28521C6.29026 7.79175 5.94227 8.31304 5.70461 8.86188C4.40873 11.2743 5.52863 12.9838 3.84879 16.8981C3.7368 17.1537 3.60881 17.3774 3.46482 17.6011C2.28094 19.3585 0.985065 19.9336 0.377124 21.6591C0.10515 22.2982 -0.0388336 23.0491 0.00916172 24.0077C-0.0388336 24.9503 0.105154 25.7012 0.36113 26.3403C0.985069 28.1136 2.32894 28.6728 3.52882 30.5261C3.64081 30.7018 3.7368 30.8936 3.8328 31.1013C5.48064 34.9197 4.44073 36.6451 5.60862 38.9777C5.88059 39.6647 6.31255 40.3357 7.03249 40.9588C7.06448 40.9908 7.11247 41.0227 7.14447 41.0547C7.8164 41.7736 8.47234 42.189 9.12828 42.4286C11.3361 43.3553 13.1439 42.1571 16.4716 43.8506C16.7275 43.9624 16.9675 44.1062 17.1915 44.25C18.9993 45.4802 19.6713 46.8062 21.3831 47.4932C22.103 47.8447 22.9509 48.0524 23.9908 47.9885C24.2256 47.9885 24.4608 47.9757 24.6953 47.9637C25.1077 47.9424 25.4839 47.8829 25.8313 47.7852C25.8415 47.7823 25.852 47.7808 25.8627 47.7808C25.8733 47.7808 25.8842 47.7794 25.8945 47.7768C28.6145 47.0853 28.6542 44.9021 32.694 43.4192C34.0379 42.9079 35.4297 42.9559 36.7736 42.844C37.4935 42.8281 38.1975 42.7482 38.9334 42.4127C39.6373 42.1411 40.3093 41.7097 40.9492 40.9908C41.0132 40.9269 41.0932 40.847 41.1572 40.7831C41.7011 40.2558 42.0691 39.7126 42.3091 39.1694C42.789 38.1629 42.821 37.2363 42.805 36.2457C42.821 35.1114 42.789 33.9611 43.237 32.7788C44.2929 29.3918 46.4527 28.8645 47.4446 26.7716C47.8445 26.0207 48.0525 25.158 47.9885 24.0077Z\"\n          fill={`url(#${id}-paint0)`}\n        />\n        <path\n          d=\"M47.9885 24.0077C48.0525 22.8733 47.8445 22.0106 47.4766 21.2916C46.4847 19.1668 44.3089 18.6395 43.253 15.2365C42.805 14.0543 42.837 12.904 42.821 11.7696C42.837 10.9229 42.821 10.0921 42.4851 9.22934C42.2291 8.49441 41.7811 7.75949 40.9652 7.02457C40.9172 6.97664 40.8692 6.92871 40.8212 6.88078C40.4052 6.43344 39.9733 6.1139 39.5253 5.87426C38.3095 5.13933 37.2535 5.13934 36.1017 5.13934C34.9818 5.07543 33.8299 5.0275 32.726 4.61211C29.1423 3.28605 28.6944 1.43277 26.7426 0.538082C26.0226 0.170621 25.1587 -0.0530492 24.0228 0.0108571C23.9108 0.0108571 23.8149 0.0268346 23.7029 0.0268346C23.0949 0.010858 22.551 0.106717 22.071 0.266483C19.6651 0.898752 19.1697 2.59445 16.7115 4.0539C16.6591 4.08501 16.6025 4.11161 16.5479 4.13864C16.5085 4.15814 16.467 4.17528 16.4277 4.19492C13.4723 5.6717 11.7232 4.87105 9.81621 5.36301C8.9043 5.53875 7.99239 5.98609 7.04848 7.04055C6.9857 7.1346 6.89377 7.20649 6.81259 7.28521C6.29026 7.79175 5.94227 8.31304 5.70461 8.86188C4.40873 11.2743 5.52863 12.9838 3.84879 16.8981C3.7368 17.1537 3.60881 17.3774 3.46482 17.6011C2.28094 19.3585 0.985065 19.9336 0.377124 21.6591C0.10515 22.2982 -0.0388336 23.0491 0.00916172 24.0077C-0.0388336 24.9503 0.105154 25.7012 0.36113 26.3403C0.985069 28.1136 2.32894 28.6728 3.52882 30.5261C3.64081 30.7018 3.7368 30.8936 3.8328 31.1013C5.48064 34.9197 4.44073 36.6451 5.60862 38.9777C5.88059 39.6647 6.31255 40.3357 7.03249 40.9588C7.06448 40.9908 7.11247 41.0227 7.14447 41.0547C7.8164 41.7736 8.47234 42.189 9.12828 42.4286C11.3361 43.3553 13.1439 42.1571 16.4716 43.8506C16.7275 43.9624 16.9675 44.1062 17.1915 44.25C18.9993 45.4802 19.6713 46.8062 21.3831 47.4932C22.103 47.8447 22.9509 48.0524 23.9908 47.9885C24.2256 47.9885 24.4608 47.9757 24.6953 47.9637C25.1077 47.9424 25.4839 47.8829 25.8313 47.7852C25.8415 47.7823 25.852 47.7808 25.8627 47.7808C25.8733 47.7808 25.8842 47.7794 25.8945 47.7768C28.6145 47.0853 28.6542 44.9021 32.694 43.4192C34.0379 42.9079 35.4297 42.9559 36.7736 42.844C37.4935 42.8281 38.1975 42.7482 38.9334 42.4127C39.6373 42.1411 40.3093 41.7097 40.9492 40.9908C41.0132 40.9269 41.0932 40.847 41.1572 40.7831C41.7011 40.2558 42.0691 39.7126 42.3091 39.1694C42.789 38.1629 42.821 37.2363 42.805 36.2457C42.821 35.1114 42.789 33.9611 43.237 32.7788C44.2929 29.3918 46.4527 28.8645 47.4446 26.7716C47.8445 26.0207 48.0525 25.158 47.9885 24.0077Z\"\n          fill={`url(#${id}-paint1)`}\n        />\n      </mask>\n      <g mask={`url(#${id}-mask)`}>\n        <rect width=\"48\" height=\"48\" fill={`url(#${id}-paint2)`} />\n      </g>\n      <defs>\n        <radialGradient\n          id={`${id}-paint0`}\n          cx=\"0\"\n          cy=\"0\"\n          r=\"1\"\n          gradientUnits=\"userSpaceOnUse\"\n          gradientTransform=\"translate(24 -0.151619) rotate(90) scale(48.3033)\"\n        >\n          <stop stop-color=\"#2E2E2E\" />\n          <stop offset=\"1\" stop-color=\"#080808\" />\n        </radialGradient>\n        <radialGradient\n          id={`${id}-paint1`}\n          cx=\"0\"\n          cy=\"0\"\n          r=\"1\"\n          gradientUnits=\"userSpaceOnUse\"\n          gradientTransform=\"translate(46.906 -4.75865) rotate(129.211) scale(84.0086 264.059)\"\n        >\n          <stop stop-color=\"#8049F2\" />\n          <stop offset=\"1\" stop-color=\"#6D4EAE\" stop-opacity=\"0\" />\n        </radialGradient>\n        <radialGradient\n          id={`${id}-paint2`}\n          cx=\"0\"\n          cy=\"0\"\n          r=\"1\"\n          gradientUnits=\"userSpaceOnUse\"\n          gradientTransform=\"translate(46.906 -4.75865) rotate(129.211) scale(84.0086 264.059)\"\n        >\n          <stop stop-color=\"#160F1F\" />\n          <stop offset=\"1\" stop-color=\"#7132F5\" />\n        </radialGradient>\n      </defs>\n    </svg>\n  );\n};\n"
  },
  {
    "path": "src/icons/Logo/index.ts",
    "content": "/**\n * This file is auto-generated by the `import-svgs.mjs` script.\n */\n\nexport { default as Ink } from \"./Ink.svg?react\";\nexport * from \"./Placeholder.tsx\";\n"
  },
  {
    "path": "src/icons/Page/index.ts",
    "content": "/**\n * This file is auto-generated by the `import-svgs.mjs` script.\n */\n\nexport { default as One } from \"./One.svg?react\";\nexport { default as Three } from \"./Three.svg?react\";\nexport { default as Two } from \"./Two.svg?react\";\n"
  },
  {
    "path": "src/icons/Social/index.ts",
    "content": "/**\n * This file is auto-generated by the `import-svgs.mjs` script.\n */\n\nexport { default as Discord } from \"./Discord.svg?react\";\nexport { default as Farcaster } from \"./Farcaster.svg?react\";\nexport { default as Github } from \"./Github.svg?react\";\nexport { default as Mirror } from \"./Mirror.svg?react\";\nexport { default as Telegram } from \"./Telegram.svg?react\";\nexport { default as X } from \"./X.svg?react\";\n"
  },
  {
    "path": "src/icons/index.ts",
    "content": "/**\n * This file is auto-generated by the `import-svgs.mjs` script.\n */\n\nexport { default as Apps } from \"./Apps.svg?react\";\nexport { default as Arrow } from \"./Arrow.svg?react\";\nexport { default as ArrowDiagonal } from \"./ArrowDiagonal.svg?react\";\nexport { default as Bridge } from \"./Bridge.svg?react\";\nexport { default as Calendar } from \"./Calendar.svg?react\";\nexport { default as Check } from \"./Check.svg?react\";\nexport { default as CheckBadge } from \"./CheckBadge.svg?react\";\nexport { default as CheckFill } from \"./CheckFill.svg?react\";\nexport { default as Chevron } from \"./Chevron.svg?react\";\nexport { default as Close } from \"./Close.svg?react\";\nexport { default as CloseSmall } from \"./CloseSmall.svg?react\";\nexport { default as Code } from \"./Code.svg?react\";\nexport { default as Copy } from \"./Copy.svg?react\";\nexport { default as Deposit } from \"./Deposit.svg?react\";\nexport { default as Disconnect } from \"./Disconnect.svg?react\";\nexport { default as Dots } from \"./Dots.svg?react\";\nexport { default as Error } from \"./Error.svg?react\";\nexport { default as Filter } from \"./Filter.svg?react\";\nexport { default as History } from \"./History.svg?react\";\nexport { default as Home } from \"./Home.svg?react\";\nexport { default as Info } from \"./Info.svg?react\";\nexport { default as InkLogo } from \"./InkLogo.svg?react\";\nexport { default as Loading } from \"./Loading.svg?react\";\nexport { default as Location } from \"./Location.svg?react\";\nexport { default as Mail } from \"./Mail.svg?react\";\nexport { default as Menu } from \"./Menu.svg?react\";\nexport { default as Minus } from \"./Minus.svg?react\";\nexport { default as Moon } from \"./Moon.svg?react\";\nexport { default as Panel } from \"./Panel.svg?react\";\nexport { default as Plus } from \"./Plus.svg?react\";\nexport { default as PlusSmall } from \"./PlusSmall.svg?react\";\nexport { default as Power } from \"./Power.svg?react\";\nexport { default as Profile } from \"./Profile.svg?react\";\nexport { default as Search } from \"./Search.svg?react\";\nexport { default as Settings } from \"./Settings.svg?react\";\nexport { default as Sun } from \"./Sun.svg?react\";\nexport { default as Swap } from \"./Swap.svg?react\";\nexport { default as Users } from \"./Users.svg?react\";\nexport { default as VerifiedIcon } from \"./VerifiedIcon.svg?react\";\nexport { default as Wallet } from \"./Wallet.svg?react\";\nexport * as Logo from \"./Logo/index.ts\";\nexport * as Page from \"./Page/index.ts\";\nexport * as Social from \"./Social/index.ts\";\n"
  },
  {
    "path": "src/index.ts",
    "content": "import \"./tailwind.css\";\n\nexport * from \"./components\";\nexport * from \"./hooks\";\nexport * as InkIcon from \"./icons\";\nexport * from \"./layout\";\n"
  },
  {
    "path": "src/layout/ForStories/ExampleDynamicContent.tsx",
    "content": "import { InkIcon } from \"../..\";\nimport { classNames } from \"../../util/classes\";\nimport { InkHeader } from \"../InkParts\";\nimport { InkPanel } from \"../InkParts/InkPanel\";\n\nconst ExamplePanel = ({\n  className,\n  text,\n}: {\n  className?: string;\n  text: string;\n}) => (\n  <InkPanel className={classNames(\"ink:min-h-[200px]\", className)}>\n    <InkHeader title={text} icon={<InkIcon.Settings />} />\n    <div className=\"ink:flex-1\">{text}</div>\n  </InkPanel>\n);\n\nexport const ExampleDynamicContent = ({\n  className,\n  columns,\n}: {\n  className?: string;\n  columns?: number;\n}) => {\n  if (!columns || columns === 1)\n    return <ExamplePanel className={className} text=\"Only Content\" />;\n  return (\n    <>\n      <ExamplePanel className={className} text=\"Column 1\" />\n      {columns > 1 && <ExamplePanel className={className} text=\"Column 2\" />}\n      {columns > 2 && <ExamplePanel className={className} text=\"Column 3\" />}\n    </>\n  );\n};\n"
  },
  {
    "path": "src/layout/ForStories/ExampleLayoutLinks.tsx",
    "content": "import { InkIcon } from \"../..\";\nimport { InkLayoutLink } from \"../InkLayout/InkNavLink\";\n\nexport const EXAMPLE_LINKS: InkLayoutLink[] = [\n  {\n    children: \"Home\",\n    href: \"#home\",\n    leftIcon: <InkIcon.Home />,\n    target: \"_self\",\n    active: true,\n  },\n  {\n    children: \"Settings\",\n    href: \"#settings\",\n    leftIcon: <InkIcon.Settings />,\n    target: \"_self\",\n  },\n];\n"
  },
  {
    "path": "src/layout/ForStories/ExampleMobileNav.tsx",
    "content": "import { EXAMPLE_LINKS } from \"./ExampleLayoutLinks\";\nimport {\n  InkLayoutMobileNav,\n  InkLayoutMobileNavProps,\n} from \"../InkLayout/MobileNav\";\nimport { useInkLayoutContext } from \"../InkLayout/InkLayoutContext\";\n\nexport const ExampleMobileNav = (\n  props: Omit<InkLayoutMobileNavProps, \"links\">\n) => {\n  const { setIsMobileNavOpen } = useInkLayoutContext();\n  return (\n    <InkLayoutMobileNav\n      links={EXAMPLE_LINKS}\n      bottom={<div>Bottom content</div>}\n      {...props}\n      onLinkClick={() => setIsMobileNavOpen(false)}\n    />\n  );\n};\n"
  },
  {
    "path": "src/layout/ForStories/ExampleSideNav.tsx",
    "content": "import { InkLayoutSideNav } from \"../InkLayout/InkLayoutSideNav\";\nimport { EXAMPLE_LINKS } from \"./ExampleLayoutLinks\";\n\nexport const ExampleSideNav = () => {\n  return (\n    <InkLayoutSideNav\n      links={EXAMPLE_LINKS}\n      bottom={<div>Bottom content</div>}\n    />\n  );\n};\n"
  },
  {
    "path": "src/layout/ForStories/ExampleTopNav.tsx",
    "content": "import { SegmentedControl } from \"../../components/SegmentedControl\";\n\nexport const ExampleTopNav = () => {\n  return (\n    <SegmentedControl\n      options={[\n        { children: \"Home\", value: \"home\", selectedByDefault: true },\n        { children: \"Settings\", value: \"settings\" },\n      ]}\n      onOptionChange={() => {}}\n    />\n  );\n};\n"
  },
  {
    "path": "src/layout/InkLayout/InkLayout.stories.tsx",
    "content": "import type { Meta, StoryObj } from \"@storybook/react\";\nimport { InkIcon } from \"../..\";\nimport { InkLayout, InkLayoutProps, InkLayoutSideNav } from \"./index\";\nimport { InkPageLayout } from \"../InkParts/InkPageLayout\";\nimport { ExampleSideNav } from \"../ForStories/ExampleSideNav\";\nimport { ExampleTopNav } from \"../ForStories/ExampleTopNav\";\nimport { InkPanel } from \"../InkParts/InkPanel\";\nimport { ExampleMobileNav } from \"../ForStories/ExampleMobileNav\";\n\n/**\n * This layout component provides a unified layout that can be used for most pages.\n * <br/>\n * It's content is defined by the children prop, which can be used with the [InkPageLayout component](?path=/docs/layouts-inkpagelayout--docs)\n */\nconst meta: Meta<InkLayoutProps> = {\n  title: \"Layouts/InkLayout\",\n  component: InkLayout,\n  parameters: {\n    layout: \"fullscreen\",\n  },\n  tags: [\"autodocs\"],\n  args: {\n    children: (\n      <InkPageLayout>\n        <InkPanel>\n          <div>Some content</div>\n        </InkPanel>\n      </InkPageLayout>\n    ),\n    headerContent: <div>Header content</div>,\n    topNavigation: <ExampleTopNav />,\n    sideNavigation: <ExampleSideNav />,\n    mobileNavigation: <ExampleMobileNav />,\n  },\n};\n\nexport default meta;\ntype Story = StoryObj<typeof meta>;\n\nexport const Simple: Story = {\n  args: {},\n};\n\n/**\n * The side nav can be a custom component for routing, for instance, if you want to use NextJS' own {`<Link />`} component.\n */\nexport const SideNavWithCustomButtons: Story = {\n  args: {\n    sideNavigation: (\n      <InkLayoutSideNav\n        links={[\n          {\n            children: <a className=\"ink:text-button-primary!\">Home</a>,\n            href: \"#home\",\n            leftIcon: <InkIcon.Home />,\n            target: \"_self\",\n            asChild: true,\n            active: true,\n          },\n          {\n            children: <a className=\"ink:text-button-primary!\">Settings</a>,\n            href: \"#settings\",\n            leftIcon: <InkIcon.Settings />,\n            target: \"_self\",\n            asChild: true,\n          },\n        ]}\n      />\n    ),\n    children: (\n      <InkPageLayout>\n        <InkPanel>\n          The side nav can be a custom component for routing, for instance, if\n          you want to use NextJS' own {`<Link />`} component.\n        </InkPanel>\n      </InkPageLayout>\n    ),\n  },\n};\n\n/**\n * The side nav can be a custom component for routing, for instance, if you want to use NextJS' own {`<Link />`} component.\n */\nexport const StickySideNav: Story = {\n  args: {\n    children: (\n      <InkPageLayout>\n        <InkPanel className=\"ink:h-[2000px]\">\n          <div className=\"ink:flex ink:flex-col ink:flex-1\">\n            <div className=\"ink:flex-grow\">\n              If the main content is bigger than the screen, the side nav will\n              be sticky.\n            </div>\n            <div className=\"ink:flex ink:flex-0\">Bottom</div>\n          </div>\n        </InkPanel>\n      </InkPageLayout>\n    ),\n  },\n};\n"
  },
  {
    "path": "src/layout/InkLayout/InkLayout.tsx",
    "content": "import { PropsWithChildren } from \"react\";\nimport { classNames } from \"../../util/classes\";\nimport { Button, InkIcon } from \"../..\";\nimport { useInkLayoutContext, InkLayoutProvider } from \"./InkLayoutContext\";\n\nexport interface InkLayoutProps extends PropsWithChildren {\n  className?: string;\n  mainIcon?: React.ReactNode;\n  headerContent?: React.ReactNode;\n  sideNavigation?: React.ReactNode;\n  topNavigation?: React.ReactNode;\n  mobileNavigation?: React.ReactNode;\n  /** Makes the layout really close to the edges of the screen, meaning you will have to handle the padding yourself. */\n  snug?: boolean;\n}\n\nexport const InkLayout: React.FC<InkLayoutProps> = (props) => {\n  return (\n    <InkLayoutProvider>\n      <InkLayoutContent {...props} />\n    </InkLayoutProvider>\n  );\n};\n\nconst InkLayoutContent = ({\n  className,\n  mainIcon = <InkIcon.Logo.Placeholder className=\"ink:size-5\" />,\n  headerContent,\n  sideNavigation,\n  topNavigation,\n  mobileNavigation,\n  snug = false,\n  children,\n}: InkLayoutProps) => {\n  const { isMobileNavOpen, setIsMobileNavOpen } = useInkLayoutContext();\n  return (\n    <>\n      <div\n        className={classNames(\n          \"ink:flex ink:flex-col ink:min-h-full ink:min-w-[320px] ink:font-default ink:text-text-default ink:gap-5 ink:box-border ink:w-full\",\n          className\n        )}\n      >\n        <div className=\"ink:w-full ink:grid ink:grid-cols-[1fr_auto_1fr] ink:justify-between ink:items-center ink:gap-3 ink:px-3 ink:sm:px-5 ink:py-2 ink:box-border ink:sticky ink:top-0 ink:z-20 ink:backdrop-blur-lg ink:lg:backdrop-blur-none\">\n          <div className=\"ink:flex ink:gap-1 ink:justify-start ink:items-center\">\n            <div className=\"ink:hidden ink:lg:block ink:size-5\">{mainIcon}</div>\n            {mobileNavigation && (\n              <Button\n                variant=\"transparent\"\n                size=\"md\"\n                rounded=\"full\"\n                className=\"ink:lg:hidden\"\n                onClick={() => setIsMobileNavOpen(!isMobileNavOpen)}\n              >\n                {isMobileNavOpen ? <InkIcon.Close /> : <InkIcon.Menu />}\n              </Button>\n            )}\n          </div>\n\n          <div className=\"ink:flex ink:items-center ink:justify-center ink:gap-2\">\n            <div className=\"ink:block ink:lg:hidden ink:size-5\">{mainIcon}</div>\n            {topNavigation && (\n              <div className=\"ink:hidden ink:lg:block\">{topNavigation}</div>\n            )}\n          </div>\n          <div className=\"ink:flex ink:gap-1 ink:justify-end ink:items-center\">\n            {headerContent}\n          </div>\n        </div>\n        <div\n          className={classNames(\n            \"ink:flex ink:flex-1 ink:box-border ink:shrink-0 ink:w-full ink:relative\",\n            !snug && \"ink:px-3 ink:sm:px-5\",\n            sideNavigation && \"ink:lg:pl-0\"\n          )}\n        >\n          {sideNavigation && (\n            <div\n              style={\n                {\n                  /** Header height + header top padding + header-content gap */\n                  \"--ink-side-nav-height\":\n                    \"calc(var(--ink-spacing-6) + var(--ink-spacing-5) + var(--ink-spacing-4))\",\n                } as React.CSSProperties\n              }\n              className={classNames(\n                \"ink:w-[244px] ink:px-4 ink:hidden ink:lg:block ink:shrink-0 ink:box-border ink:sticky ink:z-10 ink:bottom-0 ink:top-(--ink-side-nav-height) ink:max-h-[calc(100vh-var(--ink-side-nav-height))]\"\n              )}\n            >\n              {sideNavigation}\n            </div>\n          )}\n          <div\n            className={classNames(\n              \"ink:flex-grow ink:flex ink:box-border ink:pb-5 ink:overflow-hidden ink:transition-[filter]\",\n              isMobileNavOpen && \"ink:blur-[5px] ink:lg:blur-none\"\n            )}\n          >\n            {children}\n          </div>\n        </div>\n      </div>\n      {isMobileNavOpen && (\n        <div\n          style={\n            {\n              /** 40px components height + 16px top spacing + 16px spacing between header and content */\n              \"--ink-mobile-nav-height\":\n                \"calc(var(--ink-spacing-5) + var(--ink-spacing-2) + var(--ink-spacing-2))\",\n            } as React.CSSProperties\n          }\n          className={classNames(\n            \"ink:fixed ink:lg:hidden ink:lg:pointer-events-none ink:inset-0 ink:top-[var(--ink-mobile-nav-height)] ink:z-50\",\n            \"ink:bg-background-light/20 ink:backdrop-blur-lg\",\n            \"ink:transition-default-animation ink:opacity-100 ink:starting:opacity-0\"\n          )}\n        >\n          {mobileNavigation}\n        </div>\n      )}\n    </>\n  );\n};\n\nInkLayout.displayName = \"InkLayout\";\n"
  },
  {
    "path": "src/layout/InkLayout/InkLayoutContext.tsx",
    "content": "import { createContext, useContext, useEffect, useState } from \"react\";\n\nconst InkLayoutContext = createContext<{\n  isMobileNavOpen: boolean;\n  setIsMobileNavOpen: (isOpen: boolean) => void;\n}>({\n  isMobileNavOpen: false,\n  setIsMobileNavOpen: () => {},\n});\n\nexport const useInkLayoutContext = () => {\n  return useContext(InkLayoutContext);\n};\n\nexport const InkLayoutProvider = ({\n  children,\n}: {\n  children: React.ReactNode;\n}) => {\n  const [isMobileNavOpen, setIsMobileNavOpen] = useState(false);\n\n  useEffect(() => {\n    isMobileNavOpen\n      ? (document.body.style.overflow = \"hidden\")\n      : (document.body.style.overflow = \"auto\");\n  }, [isMobileNavOpen]);\n\n  return (\n    <InkLayoutContext.Provider value={{ isMobileNavOpen, setIsMobileNavOpen }}>\n      {children}\n    </InkLayoutContext.Provider>\n  );\n};\n\nInkLayoutProvider.displayName = \"InkLayoutProvider\";\n"
  },
  {
    "path": "src/layout/InkLayout/InkLayoutSideNav.tsx",
    "content": "import React from \"react\";\nimport { InkLayoutLink, InkNavLink } from \"./InkNavLink\";\n\nexport interface InkLayoutSideNavProps {\n  links: InkLayoutLink[];\n  bottom?: React.ReactNode;\n}\n\nexport const InkLayoutSideNav: React.FC<InkLayoutSideNavProps> = ({\n  links,\n  bottom,\n}) => {\n  return (\n    <nav className=\"ink:h-full ink:flex ink:flex-col ink:font-default ink:text-text-default ink:text-body-3-bold ink:pb-4 ink:gap-4 ink:box-border\">\n      <div className=\"ink:flex-1 ink:flex ink:flex-col\">\n        {links.map((link) => {\n          return <InkNavLink {...link} key={link.href} />;\n        })}\n      </div>\n      <div className=\"ink:flex-1 ink:flex ink:flex-col ink:justify-end\">\n        {bottom}\n      </div>\n    </nav>\n  );\n};\n\nInkLayoutSideNav.displayName = \"InkLayoutSideNav\";\n"
  },
  {
    "path": "src/layout/InkLayout/InkNavLink.tsx",
    "content": "import React from \"react\";\nimport { classNames, variantClassNames } from \"../../util/classes\";\nimport { Slot, Slottable } from \"../../components/Slot\";\n\nexport interface InkLayoutLink extends React.ComponentPropsWithoutRef<\"a\"> {\n  children: React.ReactNode;\n  onClick?: React.MouseEventHandler<HTMLElement>;\n  href?: string;\n  leftIcon?: React.ReactNode;\n  rightIcon?: React.ReactNode;\n  target?: StringWithAutocomplete<\"_blank\" | \"_self\">;\n  asChild?: boolean;\n  active?: boolean;\n}\n\nexport interface InkNavLinkProps extends InkLayoutLink {\n  variant?: \"default\" | \"mobile\";\n}\n\nexport const InkNavLink: React.FC<InkNavLinkProps> = ({\n  href,\n  leftIcon,\n  rightIcon,\n  children,\n  className = \"\",\n  asChild,\n  onClick,\n  active,\n  variant = \"default\",\n  ...props\n}) => {\n  const Component = asChild ? Slot : \"a\";\n\n  const iconClasses = classNames(\n    variantClassNames(variant, {\n      default: \"ink:size-3 ink:p-0.5\",\n      mobile: \"ink:size-3\",\n    })\n  );\n\n  return (\n    <Component\n      href={href}\n      className={classNames(\n        \"ink:flex ink:items-center ink:px-1.5 ink:text-inherit ink:no-underline ink:rounded-md ink:box-border ink:hover:text-text-default\",\n        variantClassNames(variant, {\n          default: classNames(\n            \"ink:gap-1 ink:py-1 ink:text-body-3-bold\",\n            active\n              ? \"ink:bg-background-container ink:text-text-default\"\n              : \"ink:text-text-muted\"\n          ),\n          mobile:\n            \"ink:gap-2 ink:py-1.5 ink:text-body-1-bold ink:text-text-default ink:hover:bg-background-container\",\n        }),\n        className\n      )}\n      draggable={false}\n      onClick={onClick}\n      {...props}\n    >\n      <Slottable child={children}>\n        {(child) => (\n          <>\n            {leftIcon && <div className={iconClasses}>{leftIcon}</div>}\n            <div\n              className={classNames(\n                \"ink:flex-1 ink:flex ink:items-center ink:justify-between\",\n                variantClassNames(variant, {\n                  default: \"ink:gap-1\",\n                  mobile: \"ink:gap-2\",\n                })\n              )}\n            >\n              {child}\n              {rightIcon && <div className={iconClasses}>{rightIcon}</div>}\n            </div>\n          </>\n        )}\n      </Slottable>\n    </Component>\n  );\n};\n\nInkNavLink.displayName = \"InkNavLink\";\n"
  },
  {
    "path": "src/layout/InkLayout/MobileNav/InkLayoutMobileNav.stories.tsx",
    "content": "import type { Meta, StoryObj } from \"@storybook/react\";\nimport {\n  InkLayoutMobileNav,\n  InkLayoutMobileNavProps,\n} from \"./InkLayoutMobileNav\";\nimport { EXAMPLE_LINKS } from \"../../ForStories/ExampleLayoutLinks\";\n\nconst meta: Meta<InkLayoutMobileNavProps> = {\n  decorators: [\n    (Story) => (\n      <>\n        <div className=\"ink:w-full ink:h-full ink:box-border\" />\n        <Story />\n      </>\n    ),\n  ],\n  title: \"Layouts/InkLayoutMobileNav\",\n  component: InkLayoutMobileNav,\n  parameters: {\n    layout: \"fullscreen\",\n  },\n  tags: [\"autodocs\"],\n  args: {\n    links: EXAMPLE_LINKS,\n  },\n};\n\nexport default meta;\ntype Story = StoryObj<typeof meta>;\n\nexport const Simple: Story = {\n  args: {},\n};\n"
  },
  {
    "path": "src/layout/InkLayout/MobileNav/InkLayoutMobileNav.tsx",
    "content": "import React from \"react\";\nimport { InkLayoutLink, InkNavLink } from \"../InkNavLink\";\nimport { InkIcon } from \"../../..\";\n\nexport interface InkLayoutMobileNavProps {\n  links: InkLayoutLink[];\n  onLinkClick?: React.MouseEventHandler<HTMLElement>;\n  bottom?: React.ReactNode;\n}\n\nexport const InkLayoutMobileNav: React.FC<InkLayoutMobileNavProps> = ({\n  links,\n  onLinkClick,\n  bottom,\n}) => {\n  return (\n    <nav className=\"ink:h-full ink:w-full ink:p-3 ink:box-border ink:font-default ink:text-text-default ink:gap-4 ink:flex ink:flex-col ink:pb-4\">\n      <div className=\"ink:flex ink:flex-col ink:gap-1\">\n        {links.map((link) => {\n          return (\n            <InkNavLink\n              {...link}\n              key={link.href}\n              onClick={onLinkClick}\n              variant=\"mobile\"\n              rightIcon={\n                typeof link.rightIcon === \"undefined\" ? (\n                  <InkIcon.Chevron className=\"ink:text-text-muted ink:rotate-270\" />\n                ) : (\n                  link.rightIcon\n                )\n              }\n            />\n          );\n        })}\n      </div>\n      <div className=\"ink:flex-1 ink:flex ink:flex-col ink:justify-end\">\n        {bottom}\n      </div>\n    </nav>\n  );\n};\n\nInkLayoutMobileNav.displayName = \"InkLayoutMobileNav\";\n"
  },
  {
    "path": "src/layout/InkLayout/MobileNav/index.ts",
    "content": "export * from \"./InkLayoutMobileNav\";\n"
  },
  {
    "path": "src/layout/InkLayout/index.ts",
    "content": "export * from \"./InkLayout\";\nexport { useInkLayoutContext } from \"./InkLayoutContext\";\nexport * from \"./InkLayoutSideNav\";\nexport * from \"./InkNavLink\";\nexport * from \"./MobileNav\";\n"
  },
  {
    "path": "src/layout/InkParts/InkHeader.stories.tsx",
    "content": "import type { Meta, StoryObj } from \"@storybook/react\";\nimport { InkHeader, InkHeaderProps } from \"./InkHeader\";\nimport { InkIcon } from \"../..\";\n\n/**\n * This component provides a unified header that can be used at the top of a page or a modal.\n */\nconst meta: Meta<InkHeaderProps> = {\n  decorators: [\n    (Story) => (\n      <div className=\"ink:w-full ink:p-3 ink:bg-background-container ink:rounded-lg\">\n        <Story />\n      </div>\n    ),\n  ],\n  title: \"Layouts/InkHeader\",\n  component: InkHeader,\n  tags: [\"autodocs\"],\n  args: {\n    title: \"Example Title\",\n  },\n};\n\nexport default meta;\ntype Story = StoryObj<typeof meta>;\n\nexport const Simple: Story = {\n  args: {},\n};\n\nexport const WithIcon: Story = {\n  args: {\n    icon: <InkIcon.Home />,\n  },\n};\n"
  },
  {
    "path": "src/layout/InkParts/InkHeader.tsx",
    "content": "import { PropsWithChildren } from \"react\";\nimport { classNames } from \"../../util/classes\";\n\nexport interface InkHeaderProps extends PropsWithChildren {\n  title: React.ReactNode;\n  children?: React.ReactNode;\n  icon?: React.ReactNode;\n}\n\nexport const InkHeader: React.FC<InkHeaderProps> = ({\n  title,\n  icon,\n  children,\n}) => {\n  return (\n    <div\n      className={classNames(\n        \"ink:w-full ink:flex ink:items-center ink:justify-between ink:font-default ink:box-border ink:gap-2 ink:text-text-default\"\n      )}\n    >\n      <div className=\"ink:text-h4 ink:whitespace-nowrap\">{title}</div>\n      {children}\n      <div className=\"ink:size-3 ink:shrink-0\">{icon}</div>\n    </div>\n  );\n};\n\nInkHeader.displayName = \"InkHeader\";\n"
  },
  {
    "path": "src/layout/InkParts/InkPageLayout.stories.tsx",
    "content": "import type { Meta, StoryObj } from \"@storybook/react\";\nimport { InkPageLayout, InkPageLayoutProps } from \"./InkPageLayout\";\nimport { InkLayout } from \"../InkLayout\";\nimport { ExampleDynamicContent } from \"../ForStories/ExampleDynamicContent\";\n\n/**\n * This component provides a column layout for a page.\n * The `columns` prop determines the number of columns to display. You must then pass the same number of children to the component.\n * <br/>\n * Note that the `InkLayout` component is included only as an example. It is not required for this component to function.\n */\nconst meta: Meta<InkPageLayoutProps> = {\n  parameters: {\n    layout: \"fullscreen\",\n  },\n  decorators: [\n    (Story, { args }) => (\n      <InkLayout\n        sideNavigation={<div>Side Navigation</div>}\n        headerContent={<div>Header Content</div>}\n      >\n        <Story\n          args={{\n            ...args,\n            children: args.children ?? (\n              <ExampleDynamicContent columns={args.columns} />\n            ),\n          }}\n        />\n      </InkLayout>\n    ),\n  ],\n  title: \"Layouts/InkPageLayout\",\n  component: InkPageLayout,\n  tags: [\"autodocs\"],\n  args: {\n    columns: 1,\n  },\n};\n\nexport default meta;\ntype Story = StoryObj<typeof meta>;\n\nexport const Simple: Story = {\n  args: {},\n};\n"
  },
  {
    "path": "src/layout/InkParts/InkPageLayout.tsx",
    "content": "import { PropsWithChildren } from \"react\";\nimport { classNames, variantClassNames } from \"../../util/classes\";\n\nexport interface InkPageLayoutProps extends PropsWithChildren {\n  columns?: 1 | 2 | 3;\n}\n\nexport const InkPageLayout: React.FC<InkPageLayoutProps> = ({\n  columns = 1,\n  children,\n}) => {\n  return (\n    <div\n      className={classNames(\n        \"ink:grid ink:gap-1 ink:*:min-h-full ink:auto-rows-min ink:md:auto-rows-auto ink:flex-1\",\n        variantClassNames(columns, {\n          1: \"ink:grid-cols-1\",\n          2: \"ink:md:grid-cols-[minmax(240px,1fr)_360px]\",\n          3: \"ink:*:first:sm:row-span-2 ink:*:first:xl:row-span-1 ink:md:auto-rows-min ink:xl:auto-rows-auto ink:md:grid-cols-[240px_minmax(240px,1fr)] ink:xl:grid-cols-[240px_minmax(240px,1fr)_360px]\",\n        }),\n        \"ink:*:bg-background-light ink:*:rounded-lg\"\n      )}\n    >\n      {children}\n    </div>\n  );\n};\n\nInkPageLayout.displayName = \"InkPageLayout\";\n"
  },
  {
    "path": "src/layout/InkParts/InkPanel.stories.tsx",
    "content": "import type { Meta, StoryObj } from \"@storybook/react\";\nimport { InkHeader, InkIcon, InkPanel, InkPanelProps } from \"../..\";\n\n/**\n * This component provides a simple layout container with a header and a content area.\n */\nconst meta: Meta<InkPanelProps> = {\n  title: \"Layouts/InkPanel\",\n  component: InkPanel,\n  tags: [\"autodocs\"],\n  args: {\n    size: \"md\",\n    children: (\n      <>\n        <InkHeader\n          title=\"A header is always nice\"\n          icon={<InkIcon.Settings />}\n        />\n        <div>And then some text here, how fun! And some more!</div>\n        <div>Some footer</div>\n      </>\n    ),\n  },\n};\n\nexport default meta;\ntype Story = StoryObj<typeof meta>;\n\nexport const Simple: Story = {\n  args: {},\n};\n\n/**\n * Centering the content will make the content centered, but the header will still be at the top.\n */\nexport const Centered: Story = {\n  args: {\n    centered: true,\n  },\n};\n\n/**\n * The automatic size will make the panel take space depending on the content.\n */\nexport const AutomaticSize: Story = {\n  args: {\n    size: \"auto\",\n  },\n};\n\n/**\n * Centering the content will make the content centered, but the header will still be at the top.\n */\nexport const CenteredWithoutHeader: Story = {\n  args: {\n    centered: true,\n    children: <div>Just some content here</div>,\n  },\n};\n"
  },
  {
    "path": "src/layout/InkParts/InkPanel.tsx",
    "content": "import { PropsWithChildren } from \"react\";\nimport { classNames, variantClassNames } from \"../../util/classes\";\nimport { forwardRef } from \"react\";\n\nexport interface InkPanelProps extends PropsWithChildren {\n  className?: string;\n  size?: \"auto\" | \"lg\" | \"md\";\n  centered?: boolean;\n  shadow?: boolean;\n}\n\nexport const InkPanel = forwardRef<HTMLDivElement, InkPanelProps>(\n  (\n    { className, size = \"auto\", centered = false, shadow = false, children },\n    ref\n  ) => {\n    return (\n      <div\n        ref={ref}\n        className={classNames(\n          \"ink:flex ink:flex-col ink:justify-between ink:gap-3 ink:p-3 ink:box-border\",\n          \"ink:*:nth-2:flex-1 ink:*:nth-2:flex ink:*:nth-2:items-start ink:*:nth-2:justify-start\",\n          \"ink:bg-background-light ink:rounded-lg\",\n          \"ink:font-default ink:text-text-default\",\n          \"ink:transition-default-animation ink:in-data-closed:scale-95 ink:in-data-closed:opacity-0\",\n          shadow && \"ink:shadow-md\",\n          variantClassNames(size, {\n            auto: \"\",\n            lg: \"ink:min-w-[320px] ink:sm:min-w-[640px] ink:min-h-[480px] ink:max-w-4xl\",\n            md: \"ink:min-w-[200px] ink:sm:min-w-[300px] ink:min-h-[300px]\",\n          }),\n          centered &&\n            \"ink:justify-center ink:items-center ink:*:nth-2:items-center ink:*:nth-2:justify-center\",\n          className\n        )}\n      >\n        {children}\n      </div>\n    );\n  }\n);\n\nInkPanel.displayName = \"InkPanel\";\n"
  },
  {
    "path": "src/layout/InkParts/index.ts",
    "content": "export * from \"./InkHeader\";\nexport * from \"./InkPageLayout\";\nexport * from \"./InkPanel\";\n"
  },
  {
    "path": "src/layout/index.ts",
    "content": "export * from \"./InkLayout\";\nexport * from \"./InkParts\";\n"
  },
  {
    "path": "src/providers.index.ts",
    "content": "import { Chain } from \"viem\";\nimport { http, Transport } from \"wagmi\";\nimport { inkSepolia } from \"wagmi/chains\";\n\nconst chains = [inkSepolia] as const satisfies Chain[];\nconst transports = {\n  [inkSepolia.id]: http(),\n} as const satisfies Record<Chain[\"id\"], Transport>;\n\nexport const inkConfig = {\n  chains,\n  transports,\n} as const;\n"
  },
  {
    "path": "src/stories/Welcome.mdx",
    "content": "import { Meta } from \"@storybook/blocks\";\nimport Banner from \"../images/banner.webp?base64\";\n\n<Meta title=\"Welcome\" />\n\n<img\n  src={Banner}\n  alt=\"Ink Kit Banner\"\n  style={{ width: \"100%\", marginBottom: \"2rem\", borderRadius: \"8px\" }}\n/>\n\n# Welcome to Ink Kit\n\nInk Kit is an onchain-focused SDK that delivers a delightful developer experience with ready-to-use app layout templates, themes, and magical animated components.\n\n## Install\n\n```bash\nnpm install @inkonchain/ink-kit\n# or\npnpm install @inkonchain/ink-kit\n```\n\n## Usage\n\n```tsx\n// Import styles first at the root of your project (required)\nimport \"@inkonchain/ink-kit/style.css\";\n```\n\n```tsx\n// Import components as needed\nimport { Button } from \"@inkonchain/ink-kit\";\n\nfunction App() {\n  return (\n    <div>\n      <Button onClick={() => {}} size=\"md\" variant=\"secondary\">\n        Ship It\n      </Button>\n    </div>\n  );\n}\n```\n\nNote: Ink Kit classes are prefixed with `ink:` and can be customized using CSS variables instead of Tailwind classes. They should be imported first so that your own custom classes are taking precedence.\n\n## Key Features\n\n- 🎨 **Customizable app layout templates**\n- ✨ **Magical animated components**\n- 🎭 **Vibrant themes**\n- ⛓️ **Onchain-focused development**\n- 🚀 **Efficient developer experience**\n- 📱 **Polished, engaging interfaces**\n\n## Theming\n\nBy default, Ink Kit provides a couple of themes already in the stylesheet:\n\n- Light (`light-theme`)\n- Dark (`dark-theme`)\n- Contrast (`contrast-theme`)\n- Neo (`neo-theme`)\n- Morpheus (`morpheus-theme`)\n\nTo specify which theme to use, add the `ink:THEME_ID` to your document root:\n\n```tsx\n<html class=\"ink:dark-theme\">\n  ...\n```\n\nIf you want to programmatically set this value, you can use the `useInkThemeClass`:\n\n```tsx\nconst theme = getMyCurrentTheme();\nuseInkThemeClass(theme === \"light\" ? \"ink:neo-theme\" : \"ink:dark-theme\");\n```\n\n### Custom Theme\n\nTo create a custom theme, you can override CSS variables:\n\n```css\n:root {\n  --ink-button-primary: rgb(10, 55, 10);\n  ...\n}\n```\n\nTo see examples on specific colors that you can override, check the following [theme](https://github.com/inkonchain/ink-kit/tree/main/src/styles/theme) section of the Ink Kit repository.\n\n## Resources\n\n- **Documentation**: Browse components and examples in the sidebar\n- **Contributing**: Visit our [GitHub repository](https://github.com/inkonchain/ink-kit)\n\n## WIP Notice\n\nThis is a work in progress: we are constantly adding new components, improving the developer experience, and fixing bugs.\n"
  },
  {
    "path": "src/styles/Colors.stories.tsx",
    "content": "import type { Meta, StoryObj } from \"@storybook/react\";\nimport { classNames } from \"../util/classes\";\n\nfunction Colors() {\n  const colors = [\n    \"ink:bg-button-primary ink:text-text-on-primary\",\n    \"ink:bg-button-secondary ink:text-text-on-secondary\",\n    \"ink:bg-background-dark\",\n    \"ink:bg-background-dark-transparent\",\n    \"ink:bg-background-light\",\n    \"ink:bg-background-light-transparent\",\n    \"ink:bg-background-light-invisible\",\n    \"ink:bg-background-container\",\n    \"ink:bg-status-success-bg ink:text-status-success\",\n    \"ink:bg-status-error-bg ink:text-status-error\",\n    \"ink:bg-status-alert-bg ink:text-status-alert\",\n  ];\n  const independentColors = [\n    \"ink:bg-ink-light-purple ink:text-text-on-primary\",\n    \"ink:bg-ink-dark-purple ink:text-text-on-primary\",\n  ];\n  return (\n    <div className=\"ink:flex ink:gap-2 ink:flex-wrap ink:font-default\">\n      <h3 className=\"ink:text-h3 ink:text-text-default ink:w-full\">Colors</h3>\n      {colors.map((color) => (\n        <div\n          key={color}\n          className={classNames(\n            \"ink:px-2 ink:py-1 ink:rounded-full ink:text-[#999]\",\n            color\n          )}\n        >\n          {color}\n        </div>\n      ))}\n      <h3 className=\"ink:text-h3 ink:text-text-default ink:w-full\">\n        Theme-Independent Colors\n      </h3>\n      {independentColors.map((color) => (\n        <div\n          key={color}\n          className={classNames(\n            \"ink:px-2 ink:py-1 ink:rounded-full ink:text-[#999]\",\n            color\n          )}\n        >\n          {color}\n        </div>\n      ))}\n    </div>\n  );\n}\n\nconst meta: Meta = {\n  title: \"Design/Colors\",\n  component: Colors,\n  parameters: {\n    layout: \"centered\",\n  },\n  tags: [\"autodocs\"],\n};\n\nexport default meta;\ntype Story = StoryObj<typeof meta>;\n\nexport const Simple: Story = {\n  args: {},\n};\n"
  },
  {
    "path": "src/styles/Shadows.stories.tsx",
    "content": "import type { Meta, StoryObj } from \"@storybook/react\";\nimport { classNames } from \"../util/classes\";\n\nfunction Shadows() {\n  const shadows = [\"ink:shadow-xs\", \"ink:shadow-md\", \"ink:shadow-lg\"];\n  return (\n    <div className=\"ink:flex ink:gap-8 ink:flex-wrap ink:font-default\">\n      {shadows.map((sh) => (\n        <div\n          key={sh}\n          className={classNames(\n            \"ink:size-[200px] ink:flex ink:items-center ink:justify-center ink:rounded-lg ink:bg-background-light ink:text-[#999]\",\n            sh\n          )}\n        >\n          {sh}\n        </div>\n      ))}\n    </div>\n  );\n}\n\nconst meta: Meta = {\n  title: \"Design/Shadows\",\n  component: Shadows,\n  parameters: {\n    layout: \"centered\",\n  },\n  tags: [\"autodocs\"],\n};\n\nexport default meta;\ntype Story = StoryObj<typeof meta>;\n\nexport const Simple: Story = {\n  args: {},\n};\n"
  },
  {
    "path": "src/styles/theme/colors.base.css",
    "content": "/*\n  Colors in this file are automatically computed using the other variables.\n  You can override them in a theme if you need specific colors, but these should look good without it.\n*/\n\n:root {\n  --ink-base-font-default: \"Plus Jakarta Sans\";\n\n  /* Background */\n  --ink-background-dark-transparent: color-mix(\n    in srgb,\n    var(--ink-background-dark) 20%,\n    transparent\n  );\n  --ink-background-light-transparent: color-mix(\n    in srgb,\n    var(--ink-background-light) 50%,\n    transparent\n  );\n  --ink-background-light-invisible: color-mix(\n    in srgb,\n    var(--ink-background-light) 0%,\n    transparent\n  );\n  --ink-background-container: color-mix(\n    in srgb,\n    var(--ink-button-primary) 6%,\n    transparent\n  );\n\n  /* Button */\n  --ink-button-primary-hover: color-mix(\n    in srgb,\n    var(--ink-button-primary) 90%,\n    transparent\n  );\n  --ink-button-primary-pressed: color-mix(\n    in srgb,\n    var(--ink-button-primary) 80%,\n    transparent\n  );\n  --ink-button-secondary: color-mix(\n    in srgb,\n    var(--ink-button-primary) 6%,\n    transparent\n  );\n  --ink-button-secondary-hover: color-mix(\n    in srgb,\n    var(--ink-button-secondary) 50%,\n    transparent\n  );\n  --ink-button-secondary-pressed: color-mix(\n    in srgb,\n    var(--ink-button-secondary-hover) 50%,\n    transparent\n  );\n\n  /* Text */\n  --ink-text-muted: color-mix(\n    in srgb,\n    var(--ink-text-default) 50%,\n    transparent\n  );\n  --ink-text-on-primary-disabled: color-mix(\n    in srgb,\n    var(--ink-text-on-primary) 40%,\n    transparent\n  );\n  --ink-text-on-secondary-disabled: color-mix(\n    in srgb,\n    var(--ink-text-on-secondary) 50%,\n    transparent\n  );\n\n  /* Status */\n  --ink-status-success-bg: color-mix(\n    in srgb,\n    var(--ink-status-success) 8%,\n    transparent\n  );\n  --ink-status-alert-bg: color-mix(\n    in srgb,\n    var(--ink-status-alert) 8%,\n    transparent\n  );\n  --ink-status-error-bg: color-mix(\n    in srgb,\n    var(--ink-status-error) 8%,\n    transparent\n  );\n\n  /* Radius */\n  --ink-base-radius-full: 9999px;\n  --ink-base-radius-xxl: 64px;\n  --ink-base-radius-xl: 48px;\n  --ink-base-radius-lg: 24px;\n  --ink-base-radius-md: 16px;\n  --ink-base-radius-sm: 12px;\n  --ink-base-radius-xs: 8px;\n\n  /* Shadows */\n  --ink-base-shadow-xs-color: color-mix(\n    in srgb,\n    var(--ink-background-shadow) 6%,\n    transparent\n  );\n  --ink-base-shadow-md-color: color-mix(\n    in srgb,\n    var(--ink-background-shadow) 8%,\n    transparent\n  );\n  --ink-base-shadow-lg-color: color-mix(\n    in srgb,\n    var(--ink-background-shadow) 10%,\n    transparent\n  );\n\n  /* Blur */\n  --ink-base-blur-sm: 48px;\n  --ink-base-blur-lg: 128px;\n\n  /* Independent Colors */\n  --ink-color-light-purple: #b9aaef;\n  --ink-color-dark-purple: #5c479d;\n}\n"
  },
  {
    "path": "src/styles/theme/colors.contrast.css",
    "content": ":root,\n:root.ink\\:contrast-theme {\n  /* Background */\n  --ink-background-dark: rgba(221, 221, 221, 1);\n  --ink-background-light: rgba(255, 255, 255, 1);\n  --ink-background-container: rgba(0, 0, 0, 0.1);\n  --ink-background-shadow: rgba(0, 0, 0, 1);\n\n  /* Button */\n  --ink-button-primary: rgba(0, 0, 0, 1);\n\n  /* Text */\n  --ink-text-default: rgba(0, 0, 0, 1);\n  --ink-text-on-primary: rgba(255, 255, 255, 1);\n  --ink-text-on-secondary: rgba(0, 0, 0, 1);\n\n  /* Status */\n  --ink-status-success: rgba(61, 166, 103, 1);\n  --ink-status-alert: rgba(231, 149, 74, 1);\n  --ink-status-error: rgba(236, 109, 109, 1);\n}\n"
  },
  {
    "path": "src/styles/theme/colors.dark.css",
    "content": ":root,\n:root.ink\\:dark-theme {\n  /* Background */\n  --ink-background-dark: rgba(18, 17, 24);\n  --ink-background-light: rgb(45, 45, 52);\n  --ink-background-container: rgba(187, 180, 255, 0.05);\n\n  /* Button */\n  --ink-button-primary: rgb(113, 50, 245);\n\n  /* Text */\n  --ink-text-default: rgb(255, 255, 255);\n  --ink-text-on-primary: rgba(255, 255, 255, 1);\n  --ink-text-on-secondary: rgba(138, 97, 255, 1);\n\n  /* Status */\n  --ink-status-success: rgb(61, 166, 103);\n  --ink-status-alert: rgb(231, 149, 74);\n  --ink-status-error: rgb(236, 109, 109);\n}\n\n/*\n  This allows us to use the dark theme over the light theme by default, depending on user preference.\n  The overrides should _exactly_ match the variables above.\n*/\n@media (prefers-color-scheme: dark) {\n  :root {\n    /* Background */\n    --ink-background-dark: rgba(18, 17, 24);\n    --ink-background-light: rgb(45, 45, 52);\n    --ink-background-container: rgba(187, 180, 255, 0.05);\n\n    /* Button */\n    --ink-button-primary: rgb(113, 50, 245);\n\n    /* Text */\n    --ink-text-default: rgb(255, 255, 255);\n    --ink-text-on-primary: rgba(255, 255, 255, 1);\n    --ink-text-on-secondary: rgba(138, 97, 255, 1);\n\n    /* Status */\n    --ink-status-success: rgb(61, 166, 103);\n    --ink-status-alert: rgb(231, 149, 74);\n    --ink-status-error: rgb(236, 109, 109);\n  }\n}\n"
  },
  {
    "path": "src/styles/theme/colors.light.css",
    "content": ":root,\n:root.ink\\:light-theme {\n  /* Background */\n  --ink-background-dark: rgba(244, 243, 249);\n  --ink-background-light: rgb(255, 255, 255);\n  --ink-background-shadow: rgba(22, 15, 31, 1);\n\n  /* Button */\n  --ink-button-primary: rgb(113, 50, 245);\n\n  /* Text */\n  --ink-text-default: rgb(22, 15, 31);\n  --ink-text-on-primary: rgb(255, 255, 255);\n  --ink-text-on-secondary: rgb(113, 50, 245);\n\n  /* Status */\n  --ink-status-success: rgb(61, 166, 103);\n  --ink-status-alert: rgb(231, 149, 74);\n  --ink-status-error: rgb(236, 109, 109);\n}\n"
  },
  {
    "path": "src/styles/theme/colors.morpheus.css",
    "content": ":root,\n:root.ink\\:morpheus-theme {\n  /* Background */\n  --ink-background-dark: rgba(15, 13, 35, 1);\n  --ink-background-light: rgba(27, 23, 73, 1);\n  --ink-background-container: rgba(45, 39, 104, 1);\n  --ink-background-shadow: rgba(15, 13, 35, 1);\n\n  /* Button */\n  --ink-button-primary: rgba(205, 54, 96, 1);\n  --ink-button-secondary: rgba(0, 106, 182, 1);\n\n  /* Text */\n  --ink-text-default: rgba(255, 255, 255);\n  --ink-text-on-primary: rgba(255, 255, 255, 1);\n  --ink-text-on-secondary: rgba(255, 255, 255, 1);\n\n  /* Status */\n  --ink-status-success: rgba(0, 106, 182, 1);\n  --ink-status-alert: rgba(254, 185, 6, 1);\n  --ink-status-error: rgba(205, 54, 96, 1);\n}\n"
  },
  {
    "path": "src/styles/theme/colors.neo.css",
    "content": ":root,\n:root.ink\\:neo-theme {\n  --ink-base-font-default: \"Departure Mono\";\n\n  /* Background */\n  --ink-background-dark: rgb(7, 9, 8);\n  --ink-background-light: rgb(19, 28, 23);\n  --ink-background-container: rgb(30, 46, 37);\n  --ink-background-shadow: rgba(7, 9, 8, 1);\n\n  /* Button */\n  --ink-button-primary: rgba(6, 254, 110);\n\n  /* Text */\n  --ink-text-default: rgba(255, 255, 255);\n  --ink-text-muted: rgba(6, 254, 110, 0.5);\n  --ink-text-on-primary: rgba(7, 9, 8);\n  --ink-text-on-secondary: rgba(6, 254, 110);\n\n  /* Status */\n  --ink-status-success: rgba(6, 254, 110);\n  --ink-status-alert: rgba(254, 185, 6);\n  --ink-status-error: rgba(248, 97, 97);\n\n  --ink-base-radius-full: 0px;\n  --ink-base-radius-xxl: 0px;\n  --ink-base-radius-xl: 0px;\n  --ink-base-radius-lg: 0px;\n  --ink-base-radius-md: 0px;\n  --ink-base-radius-sm: 0px;\n  --ink-base-radius-xs: 0px;\n}\n"
  },
  {
    "path": "src/tailwind.css",
    "content": "@import url(\"./styles/theme/colors.dark.css\") layer(ink-theme);\n@import url(\"./styles/theme/colors.neo.css\") layer(ink-theme);\n@import url(\"./styles/theme/colors.morpheus.css\") layer(ink-theme);\n@import url(\"./styles/theme/colors.contrast.css\") layer(ink-theme);\n@import url(\"./styles/theme/colors.light.css\") layer(ink-theme);\n@import url(\"./styles/theme/colors.base.css\") layer(ink-theme);\n\n/* We still need those directive to import the CSS in a Tailwind V3 package */\n@tailwind base;\n@tailwind utilities;\n\n@import \"tailwindcss/theme\" prefix(ink);\n@import \"tailwindcss/utilities\" prefix(ink);\n\n@layer base {\n  @font-face {\n    font-family: \"Plus Jakarta Sans\";\n    src: url(\"./styles/fonts/PlusJakartaSans-VariableFont_wght.ttf\");\n  }\n\n  @font-face {\n    font-family: \"Departure Mono\";\n    src: url(\"./styles/fonts/DepartureMono-Regular.woff\");\n  }\n\n  input,\n  textarea,\n  select,\n  button {\n    border: 0px solid;\n    border-radius: 0;\n    padding: 0;\n    color: inherit;\n    background-color: transparent;\n  }\n\n  input,\n  textarea,\n  select,\n  button {\n    font-family: inherit;\n    font-feature-settings: inherit;\n    font-variation-settings: inherit;\n    font-size: 100%;\n    font-weight: inherit;\n    line-height: inherit;\n    letter-spacing: inherit;\n    color: inherit;\n    margin: 0;\n    padding: 0;\n  }\n\n  .ink\\:font-default * {\n    /** Required for Safari to have proper font weights */\n    font-synthesis: none;\n  }\n\n  @keyframes svg-path-dash {\n    from {\n      stroke-dashoffset: var(--svg-path-dash-offset);\n    }\n    to {\n      stroke-dashoffset: 0;\n    }\n  }\n}\n\n@theme {\n  /* Fonts */\n  --font-*: initial;\n  --font-default: var(--ink-base-font-default);\n\n  /* Radius */\n  --radius-*: initial;\n  --radius-full: var(--ink-base-radius-full);\n  --radius-xxl: var(--ink-base-radius-xxl);\n  --radius-xl: var(--ink-base-radius-xl);\n  --radius-lg: var(--ink-base-radius-lg);\n  --radius-md: var(--ink-base-radius-md);\n  --radius-sm: var(--ink-base-radius-sm);\n  --radius-xs: var(--ink-base-radius-xs);\n\n  /* Colors */\n  --color-*: initial;\n  --color-background-dark: var(--ink-background-dark);\n  --color-background-dark-transparent: var(--ink-background-dark-transparent);\n  --color-background-container: var(--ink-background-container);\n  --color-background-light: var(--ink-background-light);\n  --color-background-light-transparent: var(--ink-background-light-transparent);\n  --color-background-light-invisible: var(--ink-background-light-invisible);\n  --color-background-shadow: var(--ink-background-shadow);\n\n  --color-button-primary: var(--ink-button-primary);\n  --color-button-primary-hover: var(--ink-button-primary-hover);\n  --color-button-primary-pressed: var(--ink-button-primary-pressed);\n  --color-button-secondary: var(--ink-button-secondary);\n  --color-button-secondary-hover: var(--ink-button-secondary-hover);\n  --color-button-secondary-pressed: var(--ink-button-secondary-pressed);\n\n  --color-text-default: var(--ink-text-default);\n  --color-text-muted: var(--ink-text-muted);\n  --color-text-on-primary: var(--ink-text-on-primary);\n  --color-text-on-primary-disabled: var(--ink-text-on-primary-disabled);\n  --color-text-on-secondary: var(--ink-text-on-secondary);\n  --color-text-on-secondary-disabled: var(--ink-text-on-secondary-disabled);\n\n  --color-status-success: var(--ink-status-success);\n  --color-status-success-bg: var(--ink-status-success-bg);\n  --color-status-alert: var(--ink-status-alert);\n  --color-status-alert-bg: var(--ink-status-alert-bg);\n  --color-status-error: var(--ink-status-error);\n  --color-status-error-bg: var(--ink-status-error-bg);\n\n  --color-default-app-icon-gradient: var(--ink-default-app-icon-gradient);\n\n  /* Independent Colors */\n  --color-ink-light-purple: var(--ink-color-light-purple);\n  --color-ink-dark-purple: var(--ink-color-dark-purple);\n\n  /* Typography */\n  --text-*: initial;\n\n  --text-display-1: 118px;\n  --text-display-1--line-height: 112px;\n  --text-display-1--font-weight: 500;\n\n  --text-display-2: 96px;\n  --text-display-2--line-height: 96px;\n  --text-display-2--font-weight: 500;\n\n  --text-h1: 72px;\n  --text-h1--line-height: 72px;\n  --text-h1--font-weight: 500;\n\n  --text-h2: 48px;\n  --text-h2--line-height: 48px;\n  --text-h2--font-weight: 500;\n\n  --text-h3: 32px;\n  --text-h3--line-height: 36px;\n  --text-h3--font-weight: 700;\n\n  --text-h4: 24px;\n  --text-h4--line-height: 28px;\n  --text-h4--font-weight: 700;\n\n  --text-h5: 20px;\n  --text-h5--line-height: 24px;\n  --text-h5--font-weight: 700;\n\n  --text-body-1-regular: 18px;\n  --text-body-1-regular--line-height: 24px;\n  --text-body-1-regular--font-weight: 400;\n\n  --text-body-1-bold: 18px;\n  --text-body-1-bold--line-height: 24px;\n  --text-body-1-bold--font-weight: 600;\n\n  --text-body-2-regular: 16px;\n  --text-body-2-regular--line-height: 20px;\n  --text-body-2-regular--font-weight: 400;\n\n  --text-body-2-bold: 16px;\n  --text-body-2-bold--line-height: 20px;\n  --text-body-2-bold--font-weight: 700;\n\n  --text-body-3-regular: 14px;\n  --text-body-3-regular--line-height: 18px;\n  --text-body-3-regular--font-weight: 400;\n\n  --text-body-3-bold: 14px;\n  --text-body-3-bold--line-height: 18px;\n  --text-body-3-bold--font-weight: 700;\n\n  --text-caption-1-regular: 12px;\n  --text-caption-1-regular--line-height: 16px;\n  --text-caption-1-regular--font-weight: 400;\n\n  --text-caption-1-bold: 12px;\n  --text-caption-1-bold--line-height: 16px;\n  --text-caption-1-bold--font-weight: 700;\n\n  --text-caption-2-regular: 11px;\n  --text-caption-2-regular--line-height: 16px;\n  --text-caption-2-regular--font-weight: 400;\n\n  --text-caption-2-bold: 11px;\n  --text-caption-2-bold--line-height: 16px;\n  --text-caption-2-bold--font-weight: 700;\n\n  /* Spacing */\n  --spacing-*: initial;\n  --spacing-0: 0px;\n  --spacing-0_5: 4px;\n  --spacing-1: 8px;\n  --spacing-1_5: 12px;\n  --spacing-2: 16px;\n  --spacing-3: 24px;\n  --spacing-4: 32px;\n  --spacing-5: 40px;\n  --spacing-6: 48px;\n  --spacing-8: 64px;\n  --spacing-12: 96px;\n  --spacing-16: 128px;\n\n  /* Shadows */\n  --shadow-*: initial;\n  --shadow-xs: 0px 4px 8px -2px var(--ink-base-shadow-xs-color);\n  --shadow-md: 0px 12px 16px -4px var(--ink-base-shadow-md-color);\n  --shadow-lg: 0px 32px 64px -12px var(--ink-base-shadow-lg-color);\n\n  /* Blur */\n  --blur-*: initial;\n  --blur-sm: var(--ink-base-blur-sm);\n  --blur-lg: var(--ink-base-blur-lg);\n\n  /* Rotation */\n  --rotation-225: 225deg;\n  --rotation-270: 270deg;\n}\n\n@utility transition-default-animation {\n  @apply ink:duration-200 ink:ease-in-out;\n}\n\n/**\n * For this animation to work, the SVG path must have a stroke attribute.\n * Set `animate-svg-path` on the Icon element, then apply `animate-svg-path-start` when you want the animation to play (e.g. on hover).\n */\n@utility animate-svg-path {\n  --svg-path-dash-duration: 0.25s;\n  --svg-path-dash-offset: 24;\n  --svg-path-dash-delay: 0.1s;\n  --svg-path-dash-easing: ease-in-out;\n\n  > path[stroke] {\n    stroke-dasharray: var(--svg-path-dash-offset);\n    stroke-dashoffset: var(--svg-path-dash-offset);\n  }\n}\n\n@utility animate-svg-path-start {\n  > path[stroke] {\n    animation: svg-path-dash var(--svg-path-dash-duration)\n      var(--svg-path-dash-delay) var(--svg-path-dash-easing) forwards;\n  }\n}\n"
  },
  {
    "path": "src/util/classes.ts",
    "content": "import { type ClassValue, clsx } from \"clsx\";\nimport { extendTailwindMerge } from \"tailwind-merge\";\n\nconst colors = [\n  \"text-default\",\n  \"text-muted\",\n  \"text-on-primary\",\n  \"text-on-primary-disabled\",\n  \"text-on-secondary\",\n  \"text-on-secondary-disabled\",\n  \"background-dark\",\n  \"background-dark-transparent\",\n  \"background-container\",\n  \"background-light\",\n  \"background-light-transparent\",\n  \"background-light-invisible\",\n  \"button-primary\",\n  \"button-primary-hover\",\n  \"button-primary-pressed\",\n  \"button-secondary\",\n  \"button-secondary-hover\",\n  \"button-secondary-pressed\",\n  \"status-success\",\n  \"status-success-bg\",\n  \"status-alert\",\n  \"status-alert-bg\",\n  \"status-error\",\n  \"status-error-bg\",\n];\n\nconst customTwMerge = extendTailwindMerge({\n  override: {\n    classGroups: {\n      rounded: [\n        \"rounded-xs\",\n        \"rounded-sm\",\n        \"rounded-md\",\n        \"rounded-lg\",\n        \"rounded-full\",\n      ],\n      \"font-size\": [\n        \"text-h1\",\n        \"text-h2\",\n        \"text-h3\",\n        \"text-h4\",\n        \"text-body-1-regular\",\n        \"text-body-1-bold\",\n        \"text-body-2-regular\",\n        \"text-body-2-bold\",\n        \"text-body-3-regular\",\n        \"text-body-3-bold\",\n        \"text-caption-1-regular\",\n        \"text-caption-1-bold\",\n        \"text-caption-2\",\n      ],\n      \"text-color\": colors.map((color) => `text-${color}`),\n      \"bg-color\": colors.map((color) => `bg-${color}`),\n      \"border-color\": colors.map((color) => `border-${color}`),\n      \"ring-color\": colors.map((color) => `ring-${color}`),\n      \"shadow-color\": colors.map((color) => `shadow-${color}`),\n    },\n  },\n});\n\nexport function classNames(...classes: ClassValue[]) {\n  return customTwMerge(clsx(...classes));\n}\n\nexport function variantClassNames<T extends string | number>(\n  variant: T,\n  classes: Required<Record<T, string>>\n) {\n  return classes[variant];\n}\n"
  },
  {
    "path": "src/util/mocks.ts",
    "content": "export const DEFAULT_MOCK_ACCOUNT =\n  \"0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\";\n"
  },
  {
    "path": "src/util/trim.ts",
    "content": "import { Address } from \"viem\";\n\nexport const trimAddress = (address?: Address) => {\n  if (!address || address.length < 10) return \"\";\n  return `${address.slice(0, 6)}...${address.slice(-4)}`;\n};\n"
  },
  {
    "path": "tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"ES5\",\n    \"useDefineForClassFields\": true,\n    \"lib\": [\"ES2020\", \"DOM\", \"DOM.Iterable\"],\n    \"module\": \"ESNext\",\n    \"skipLibCheck\": true,\n    \"moduleResolution\": \"bundler\",\n    \"allowImportingTsExtensions\": true,\n    \"allowJs\": true,\n    \"resolveJsonModule\": true,\n    \"isolatedModules\": true,\n    \"noEmit\": true,\n    \"jsx\": \"react-jsx\",\n    \"strict\": true,\n    \"noUnusedLocals\": true,\n    \"noUnusedParameters\": true,\n    \"noFallthroughCasesInSwitch\": true,\n    \"declaration\": true\n  },\n  \"include\": [\"src\"],\n  \"exclude\": [\"src/**/*.stories.ts\"]\n}\n"
  },
  {
    "path": "vite.config.mts",
    "content": "import { defineConfig } from \"vite\";\nimport dts from \"vite-plugin-dts\";\nimport svgr from \"vite-plugin-svgr\";\nimport preserveUseClientDirective from \"rollup-plugin-preserve-use-client\";\nimport tailwindcss from \"@tailwindcss/vite\";\nimport { peerDependencies } from \"./package.json\";\nimport { Plugin } from \"vite\";\nimport fs from \"fs\";\n\nconst base64Loader: Plugin = {\n  name: \"base64-loader\",\n  transform(_: any, id: string) {\n    const [path, query] = id.split(\"?\");\n    if (query != \"base64\") return null;\n\n    const data = fs.readFileSync(path);\n    const base64 = data.toString(\"base64\");\n    const extension = path.split(\".\").pop();\n\n    return `export default 'data:image/${extension};base64,${base64}';`;\n  },\n};\n\nexport default defineConfig({\n  build: {\n    lib: {\n      entry: {\n        index: \"./src/index.ts\",\n        providers: \"./src/providers.index.ts\",\n      },\n      name: \"vite-react-ts-button\",\n      fileName: (format, entryName) => `${entryName}.${format}.js`,\n      formats: [\"cjs\", \"es\"],\n    },\n    rollupOptions: {\n      /** \"react/jsx-runtime\" is needed to support both React 18 and 19, plus it makes the bundle smaller */\n      external: [\n        \"react/jsx-runtime\",\n        \"wagmi/connectors\",\n        \"wagmi/chains\",\n        ...Object.keys(peerDependencies),\n      ],\n    },\n    sourcemap: true,\n    emptyOutDir: true,\n  },\n  plugins: [\n    preserveUseClientDirective(),\n    tailwindcss(),\n    dts(),\n    svgr({\n      include: \"**/*.svg?react\",\n    }),\n    base64Loader,\n  ],\n});\n"
  }
]